domain/entities.rs
1//! Core pet-resort entities and operational records.
2//!
3//! ## Operator-summary
4//!
5//! This module supports the shared staff view of pets, customers, reservations, care profiles,
6//! documents, vaccine records, care notes, incidents, messages, and approval records. It can
7//! reduce labor by keeping the facts needed for triage, safety review, handoff, document review,
8//! customer-message approval, and manager queues in one normalized shape instead of scattering
9//! them across source-system payloads and free-text notes.
10//!
11//! It must not automate live booking changes, provider writes, customer sends, payment/refund
12//! actions, medical/vaccine/behavior decisions, incident closure, or policy exceptions.
13//! Authoritative facts remain the named source record, source document/storage object, policy
14//! snapshot, reviewer approval, audit event, and typed domain value for each field. Review
15//! gates protect pets, customers, and staff by tying sensitive records to explicit approval
16//! targets and lifecycle states before downstream workflows may treat them as cleared.
17//!
18//! These structs and enums are the normalized domain facts used by workflow, policy, storage, and
19//! source adapters. They should be read as normalized operating records: every field is either a source-backed
20//! fact, a reviewable derived state, or a safety/labor signal used to reduce manual resort work
21//! without bypassing manager, medical, behavior, payment, or customer-message gates.
22
23use chrono::{DateTime, NaiveDate, Utc};
24use nutype::nutype;
25#[allow(unused_imports)]
26use serde::{Deserialize, Serialize};
27use uuid::Uuid;
28
29use bon::Builder;
30
31use crate::{
32 agent, care, customer, document, incident, location, message, payment, pet, policy, portal,
33 temperament, vaccine,
34};
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
37/// Stable identifier for a resort location across source imports, policies, reports, and workflows.
38pub struct LocationId(pub Uuid);
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
41/// Stable identifier for the customer/account responsible for pets, reservations, messages, and payments.
42pub struct CustomerId(pub Uuid);
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
45/// Stable identifier for a pet whose care, temperament, vaccine, and reservation facts drive safety decisions.
46pub struct PetId(pub Uuid);
47
48/// Reservation-facing source vocabulary embedded in core entity records.
49pub mod reservation {
50 use serde::{Deserialize, Serialize};
51 use uuid::Uuid;
52
53 use super::PortalProvider;
54
55 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
56 /// Provider or source identifier retained as the stable join key.
57 pub struct Id(pub Uuid);
58
59 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
60 /// Normalized lifecycle states used to reconcile source-system data with domain workflows.
61 pub enum Status {
62 /// Inquiry state or source category preserved for normalized resort records.
63 Inquiry,
64 /// Reservation has been requested but not yet confirmed.
65 Requested,
66 /// Missing info state or source category preserved for normalized resort records.
67 MissingInfo,
68 /// Vaccine pending state or source category preserved for normalized resort records.
69 VaccinePending,
70 /// Special review state or source category preserved for normalized resort records.
71 SpecialReview,
72 /// Waitlisted state or source category preserved for normalized resort records.
73 Waitlisted,
74 /// Offered state or source category preserved for normalized resort records.
75 Offered,
76 /// Reservation has been accepted by the resort.
77 Confirmed,
78 /// Pet has arrived and is in care.
79 CheckedIn,
80 /// Active state or source category preserved for normalized resort records.
81 Active,
82 /// Pet has left care and the stay is complete.
83 CheckedOut,
84 /// Reservation is no longer active.
85 Cancelled,
86 /// Rejected state or source category preserved for normalized resort records.
87 Rejected,
88 }
89
90 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
91 /// Origin channel for a reservation or operational fact before it becomes trusted domain evidence.
92 pub enum Source {
93 /// Portal state or source category preserved for normalized resort records.
94 Portal(PortalProvider),
95 /// Website form state or source category preserved for normalized resort records.
96 WebsiteForm,
97 /// Phone transcript state or source category preserved for normalized resort records.
98 PhoneTranscript,
99 /// Sms state or source category preserved for normalized resort records.
100 Sms,
101 /// Email state or source category preserved for normalized resort records.
102 Email,
103 /// Staff created state or source category preserved for normalized resort records.
104 StaffCreated,
105 }
106}
107
108#[nutype(
109 sanitize(trim),
110 validate(not_empty, len_char_max = 120),
111 derive(
112 Debug,
113 Clone,
114 PartialEq,
115 Eq,
116 PartialOrd,
117 Ord,
118 Hash,
119 Serialize,
120 Deserialize
121 )
122)]
123pub struct StaffId(String);
124
125/// Manager identifier used when approvals, overrides, or escalations require accountable leadership.
126#[nutype(
127 sanitize(trim),
128 validate(not_empty, len_char_max = 120),
129 derive(
130 Debug,
131 Clone,
132 PartialEq,
133 Eq,
134 PartialOrd,
135 Ord,
136 Hash,
137 Serialize,
138 Deserialize
139 )
140)]
141pub struct ManagerId(String);
142
143#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
144/// Resort location record that scopes local capabilities, timezone, brand, and policy references.
145pub struct Location {
146 /// Id retained from source records for staff review, safety gates, and workflow joins.
147 pub id: LocationId,
148 /// Brand retained from source records for staff review, safety gates, and workflow joins.
149 pub brand: Brand,
150 /// Contact or display name used by staff.
151 pub name: location::Name,
152 /// Timezone retained from source records for staff review, safety gates, and workflow joins.
153 pub timezone: location::Timezone,
154 /// Capabilities retained from source records for staff review, safety gates, and workflow joins.
155 pub capabilities: Vec<ServiceKind>,
156 /// Policies retained from source records for staff review, safety gates, and workflow joins.
157 pub policies: LocationPolicyRefs,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
161/// Brand family used to group multi-site operating records without losing local resort identity.
162pub enum Brand {
163 /// Nva pet resorts state or source category preserved for normalized resort records.
164 NvaPetResorts,
165 /// Pet suites state or source category preserved for normalized resort records.
166 PetSuites,
167 /// Contact or display name used by staff.
168 NeighborhoodPetResort {
169 /// Name attached to this variant for reviewers and adapters.
170 name: location::Name,
171 },
172}
173
174#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
175/// References to the local policy set that controls automation, vaccine, and play-safety decisions.
176pub struct LocationPolicyRefs {
177 /// Vaccine policy id retained from source records for staff review, safety gates, and workflow joins.
178 pub vaccine_policy_id: policy::Id,
179 /// Deposit policy id retained from source records for staff review, safety gates, and workflow joins.
180 pub deposit_policy_id: policy::Id,
181 /// Playgroup policy id retained from source records for staff review, safety gates, and workflow joins.
182 pub playgroup_policy_id: policy::Id,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
186/// Customer/account profile used for reservation ownership, consent-sensitive messaging, and follow-up work.
187pub struct Customer {
188 /// Id retained from source records for staff review, safety gates, and workflow joins.
189 pub id: CustomerId,
190 /// Full name retained from source records for staff review, safety gates, and workflow joins.
191 pub full_name: customer::Name,
192 /// Email retained from source records for staff review, safety gates, and workflow joins.
193 pub email: Option<customer::Email>,
194 /// Mobile phone retained from source records for staff review, safety gates, and workflow joins.
195 pub mobile_phone: Option<customer::Phone>,
196 /// Preferred contact retained from source records for staff review, safety gates, and workflow joins.
197 pub preferred_contact: ContactChannel,
198 /// Portal account retained from source records for staff review, safety gates, and workflow joins.
199 pub portal_account: Option<PortalAccountRef>,
200}
201
202#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
203/// Link to the customer portal account that supplied or owns source records.
204pub struct PortalAccountRef {
205 /// Provider retained from source records for staff review, safety gates, and workflow joins.
206 pub provider: PortalProvider,
207 /// External customer id retained from source records for staff review, safety gates, and workflow joins.
208 pub external_customer_id: portal::CustomerId,
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
212/// Portal provider that owns the account or operational record.
213pub enum PortalProvider {
214 /// Gingr reservation and pet-care operating system.
215 Gingr,
216 /// Non-dog, non-cat pet handled by exception policy.
217 Other(String),
218}
219
220#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
221/// Customer contact channel preference or observed route used by draft/message workflows.
222pub enum ContactChannel {
223 /// Email state or source category preserved for normalized resort records.
224 Email,
225 /// Sms state or source category preserved for normalized resort records.
226 Sms,
227 /// Phone state or source category preserved for normalized resort records.
228 Phone,
229 /// Portal state or source category preserved for normalized resort records.
230 Portal,
231}
232
233#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
234/// Pet profile carrying identity, species, age, sex, sterilization, temperament, and care facts for safe service decisions.
235pub struct Pet {
236 /// Id retained from source records for staff review, safety gates, and workflow joins.
237 pub id: PetId,
238 /// Customer id retained from source records for staff review, safety gates, and workflow joins.
239 pub customer_id: CustomerId,
240 /// Contact or display name used by staff.
241 pub name: pet::Name,
242 /// Species retained from source records for staff review, safety gates, and workflow joins.
243 pub species: Species,
244 /// Birth date retained from source records for staff review, safety gates, and workflow joins.
245 pub birth_date: Option<NaiveDate>,
246 /// Sex retained from source records for staff review, safety gates, and workflow joins.
247 pub sex: Option<Sex>,
248 /// Spay neuter status retained from source records for staff review, safety gates, and workflow joins.
249 pub spay_neuter_status: SpayNeuterStatus,
250 #[builder(default)]
251 /// Temperament retained from source records for staff review, safety gates, and workflow joins.
252 pub temperament: TemperamentProfile,
253 #[builder(default)]
254 /// Care profile retained from source records for staff review, safety gates, and workflow joins.
255 pub care_profile: CareProfile,
256}
257
258#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
259/// Pet species category used by boarding/daycare/play policies and labor planning.
260pub enum Species {
261 /// Dog guest, using dog-specific policy and capacity rules.
262 Dog,
263 /// Cat guest, using cat-specific policy and accommodation rules.
264 Cat,
265 /// Non-dog, non-cat pet handled by exception policy.
266 Other(String),
267}
268
269#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
270/// Recorded pet sex when the source system supplies it.
271pub enum Sex {
272 /// Female pet sex recorded for profile and policy context.
273 Female,
274 /// Male pet sex recorded for profile and policy context.
275 Male,
276 /// Provider role or status could not be mapped confidently.
277 Unknown,
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
281/// Spay/neuter status used by group-play eligibility, safety review, and policy gating.
282pub enum SpayNeuterStatus {
283 /// Pet has been spayed for policy and playgroup eligibility checks.
284 Spayed,
285 /// Pet has been neutered for policy and playgroup eligibility checks.
286 Neutered,
287 /// Pet is intact and may trigger extra policy review.
288 Intact,
289 /// Provider role or status could not be mapped confidently.
290 Unknown,
291}
292
293#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder, Default)]
294/// Temperament evidence used to decide group-play, individual care, and behavior-review routing.
295pub struct TemperamentProfile {
296 #[builder(default)]
297 /// Group play observation retained from source records for staff review, safety gates, and workflow joins.
298 pub group_play_observation: temperament::GroupPlayObservation,
299 #[builder(default)]
300 /// People orientation retained from source records for staff review, safety gates, and workflow joins.
301 pub people_orientation: temperament::PeopleOrientation,
302 #[builder(default)]
303 /// Rating retained from source records for staff review, safety gates, and workflow joins.
304 pub rating: temperament::Rating,
305 #[builder(default)]
306 /// Behavior observations retained from source records for staff review, safety gates, and workflow joins.
307 pub behavior_observations: Vec<temperament::BehaviorObservation>,
308 #[builder(default)]
309 /// Staff notes retained from source records for staff review, safety gates, and workflow joins.
310 pub staff_notes: Vec<temperament::StaffNote>,
311}
312
313impl TemperamentProfile {
314 /// Reports whether temperament facts require staff evaluation before group play or similar services.
315 pub fn needs_staff_play_evaluation(&self) -> bool {
316 self.group_play_observation.needs_staff_evaluation()
317 }
318}
319
320#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
321/// Feeding, medication, handling, and special-care summary used for staff handoffs and briefings.
322pub struct CareProfile {
323 /// Feeding instructions retained from source records for staff review, safety gates, and workflow joins.
324 pub feeding_instructions: Option<care::FeedingInstruction>,
325 /// Medications retained from source records for staff review, safety gates, and workflow joins.
326 pub medications: Vec<MedicationInstruction>,
327 /// Allergies retained from source records for staff review, safety gates, and workflow joins.
328 pub allergies: Vec<care::AllergyName>,
329 /// Medical conditions retained from source records for staff review, safety gates, and workflow joins.
330 pub medical_conditions: Vec<care::MedicalConditionName>,
331 /// Emergency contact retained from source records for staff review, safety gates, and workflow joins.
332 pub emergency_contact: Option<care::ContactRef>,
333 /// Veterinarian contact retained from source records for staff review, safety gates, and workflow joins.
334 pub veterinarian_contact: Option<care::ContactRef>,
335}
336
337#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
338/// Medication instruction that must remain explicit for care safety and shift handoff evidence.
339pub struct MedicationInstruction {
340 /// Contact or display name used by staff.
341 pub name: care::MedicationName,
342 /// Dose retained from source records for staff review, safety gates, and workflow joins.
343 pub dose: care::MedicationDose,
344 /// Schedule retained from source records for staff review, safety gates, and workflow joins.
345 pub schedule: care::MedicationSchedule,
346 /// Review requirement retained from source records for staff review, safety gates, and workflow joins.
347 pub review_requirement: care::MedicationReviewRequirement,
348}
349
350#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
351/// Reservation record tying customer, pet, service, status, deposit, add-ons, and safety stops together.
352pub struct Reservation {
353 /// Id retained from source records for staff review, safety gates, and workflow joins.
354 pub id: reservation::Id,
355 /// Location id retained from source records for staff review, safety gates, and workflow joins.
356 pub location_id: LocationId,
357 /// Customer id retained from source records for staff review, safety gates, and workflow joins.
358 pub customer_id: CustomerId,
359 /// Pet ids retained from source records for staff review, safety gates, and workflow joins.
360 pub pet_ids: Vec<PetId>,
361 /// Requested service that drives scheduling and labor estimates.
362 pub service: ServiceKind,
363 /// Status retained from source records for staff review, safety gates, and workflow joins.
364 pub status: reservation::Status,
365 /// Starts at retained from source records for staff review, safety gates, and workflow joins.
366 pub starts_at: DateTime<Utc>,
367 /// Ends at retained from source records for staff review, safety gates, and workflow joins.
368 pub ends_at: DateTime<Utc>,
369 /// Deposit retained from source records for staff review, safety gates, and workflow joins.
370 pub deposit: Option<Deposit>,
371 /// Source retained from source records for staff review, safety gates, and workflow joins.
372 pub source: reservation::Source,
373 #[builder(default)]
374 /// Requested add ons retained from source records for staff review, safety gates, and workflow joins.
375 pub requested_add_ons: Vec<AddOn>,
376 #[builder(default)]
377 /// Hard stops retained from source records for staff review, safety gates, and workflow joins.
378 pub hard_stops: Vec<HardStop>,
379}
380
381#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
382/// Resort service line used for labor planning, capacity, policy, upsell, and workflow routing.
383pub enum ServiceKind {
384 /// Overnight stay service line.
385 Boarding,
386 /// Single-day play visit without overnight lodging.
387 DayPlay,
388 /// Daytime boarding care with lodging-style supervision.
389 DayBoarding,
390 /// Grooming service line or care-note category.
391 Grooming,
392 /// Training service line or care-note category.
393 Training,
394 /// Day-spa service package.
395 DaySpa,
396}
397
398/// Shared deposit type used by reservation, payment, and approval records.
399pub type Deposit = payment::Deposit;
400/// Shared payment status used by checkout, deposit, refund, and approval records.
401pub type PaymentStatus = payment::DepositStatus;
402
403#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
404/// Optional reservation add-ons that affect labor, revenue, care planning, or customer follow-up.
405pub enum AddOn {
406 /// Group-play add-on or accommodation feature.
407 GroupPlay,
408 /// Individual play add-on for pets not suited to group play.
409 IndividualPlay,
410 /// Premium suite with webcam visibility.
411 WebcamSuite,
412 /// Bath offered before departure from boarding.
413 ExitBath,
414 /// Progress report shared with the customer during care.
415 PawgressReport,
416 /// Medication service that requires care instructions.
417 MedicationAdministration,
418 /// Non-dog, non-cat pet handled by exception policy.
419 Other(crate::reservation::AddOnLabel),
420}
421
422#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
423/// Non-ignorable condition that blocks or routes a reservation before staff or customer action proceeds.
424pub enum HardStop {
425 /// Missing required vaccine state or source category preserved for normalized resort records.
426 MissingRequiredVaccine(policy::VaccineName),
427 /// Ineligible for group play state or source category preserved for normalized resort records.
428 IneligibleForGroupPlay(policy::play::IneligibilityReason),
429 /// Pet is in heat and requires policy handling.
430 InHeat,
431 /// Age below minimum weeks state or source category preserved for normalized resort records.
432 AgeBelowMinimumWeeks(crate::reservation::AgeThreshold),
433 /// Medical or medication information requires review before service.
434 MedicalOrMedicationReviewRequired,
435 /// Behavior history requires review before service.
436 BehaviorReviewRequired,
437 /// Deposit must be collected before the booking is secure.
438 DepositRequired,
439}
440
441#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
442/// Stable identifier for a document artifact used as vaccine, waiver, medical, or incident evidence.
443pub struct DocumentId(pub Uuid);
444
445#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
446/// Stable identifier for a vaccine compliance record tied to a pet and proof document.
447pub struct VaccineRecordId(pub Uuid);
448
449/// Care-note vocabulary for staff-visible, customer-visible, and internal handoff notes.
450pub mod care_note {
451 use nutype::nutype;
452 #[allow(unused_imports)]
453 use serde::{Deserialize, Serialize};
454 use uuid::Uuid;
455
456 use super::{IncidentId, PetId, reservation};
457
458 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
459 /// Provider or source identifier retained as the stable join key.
460 pub struct Id(pub Uuid);
461
462 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
463 /// Subject that a care, document, incident, audit, or message record is about.
464 pub enum Subject {
465 /// Pet record participating in the workflow.
466 Pet(PetId),
467 /// Reservation record participating in the workflow.
468 Reservation(reservation::Id),
469 /// Incident record participating in the workflow.
470 Incident(IncidentId),
471 }
472
473 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
474 /// Care-note category used to route safety, feeding, medication, behavior, and staff handoff information.
475 pub enum Kind {
476 /// Feeding state or source category preserved for normalized resort records.
477 Feeding,
478 /// Medication state or source category preserved for normalized resort records.
479 Medication,
480 /// Medical state or source category preserved for normalized resort records.
481 Medical,
482 /// Behavior state or source category preserved for normalized resort records.
483 Behavior,
484 /// Grooming service line or care-note category.
485 Grooming,
486 /// Training service line or care-note category.
487 Training,
488 /// General state or source category preserved for normalized resort records.
489 General,
490 }
491
492 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
493 /// Visibility rule that determines whether a care note may be shown to customers or only staff.
494 pub enum Visibility {
495 /// Internal only state or source category preserved for normalized resort records.
496 InternalOnly,
497 /// Customer visible state or source category preserved for normalized resort records.
498 CustomerVisible,
499 /// Customer visible after review state or source category preserved for normalized resort records.
500 CustomerVisibleAfterReview,
501 }
502
503 #[nutype(
504 sanitize(trim),
505 validate(not_empty, len_char_max = 2000),
506 derive(
507 Debug,
508 Clone,
509 PartialEq,
510 Eq,
511 PartialOrd,
512 Ord,
513 Hash,
514 Serialize,
515 Deserialize
516 )
517 )]
518 pub struct Body(String);
519}
520
521#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
522/// Stable identifier for a pet, customer, or operational incident requiring evidence and follow-up.
523pub struct IncidentId(pub Uuid);
524
525#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
526/// Stable identifier for a customer or internal message workflow.
527pub struct MessageId(pub Uuid);
528
529/// Approval record vocabulary for review-gated automation outcomes.
530pub mod approval {
531 use bon::Builder;
532 use chrono::{DateTime, Utc};
533 use serde::{Deserialize, Serialize};
534 use uuid::Uuid;
535
536 use super::{
537 ActorRef, DocumentId, IncidentId, MessageId, VaccineRecordId, policy, reservation,
538 };
539
540 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
541 /// Provider or source identifier retained as the stable join key.
542 pub struct Id(pub Uuid);
543
544 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
545 /// Approval record showing who decided, what target was reviewed, and what lifecycle state resulted.
546 pub struct Record {
547 /// Id retained from source records for staff review, safety gates, and workflow joins.
548 pub id: Id,
549 /// Target retained from source records for staff review, safety gates, and workflow joins.
550 pub target: Target,
551 /// Gate retained from source records for staff review, safety gates, and workflow joins.
552 pub gate: policy::ReviewGate,
553 /// Lifecycle retained from source records for staff review, safety gates, and workflow joins.
554 pub lifecycle: Lifecycle,
555 /// Requested by retained from source records for staff review, safety gates, and workflow joins.
556 pub requested_by: ActorRef,
557 /// Requested at retained from source records for staff review, safety gates, and workflow joins.
558 pub requested_at: DateTime<Utc>,
559 #[builder(default)]
560 /// Audit refs retained from source records for staff review, safety gates, and workflow joins.
561 pub audit_refs: Vec<crate::audit::EventId>,
562 }
563
564 impl Record {
565 /// Returns the normalized operational status represented by this record.
566 pub fn status(&self) -> Status {
567 self.lifecycle.status()
568 }
569
570 /// Reports whether this approval gate currently applies to the target workflow.
571 pub fn is_applicable(&self) -> bool {
572 matches!(self.lifecycle, Lifecycle::Approved { .. })
573 }
574
575 /// Reports whether the review lifecycle has reached an approval, rejection, or non-applicable endpoint.
576 pub fn is_terminal_decision(&self) -> bool {
577 self.lifecycle.is_terminal_decision()
578 }
579
580 /// Returns the accountable actor and timestamp when the review reached a terminal decision.
581 pub fn decision_actor_and_time(&self) -> Option<(&ActorRef, DateTime<Utc>)> {
582 self.lifecycle.decision_actor_and_time()
583 }
584 }
585
586 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
587 /// Operational artifact that an approval gate is allowed to approve, reject, or mark non-applicable.
588 pub enum Target {
589 /// Reservation record participating in the workflow.
590 Reservation(reservation::Id),
591 /// Customer or pet document participating in review.
592 Document(DocumentId),
593 /// Vaccination document or status record under review.
594 VaccineRecord(VaccineRecordId),
595 /// Incident record participating in the workflow.
596 Incident(IncidentId),
597 /// Customer communication record participating in approval.
598 Message(MessageId),
599 }
600
601 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
602 /// Approval lifecycle state for draft, requested, approved, rejected, or non-applicable review gates.
603 pub enum Lifecycle {
604 /// Approval requested state or source category preserved for normalized resort records.
605 ApprovalRequested,
606 /// Approved state or source category preserved for normalized resort records.
607 Approved {
608 /// Decided by retained from source records for staff review, safety gates, and workflow joins.
609 decided_by: ActorRef,
610 /// Decided at retained from source records for staff review, safety gates, and workflow joins.
611 decided_at: DateTime<Utc>,
612 },
613 /// Rejected state or source category preserved for normalized resort records.
614 Rejected {
615 /// Decided by retained from source records for staff review, safety gates, and workflow joins.
616 decided_by: ActorRef,
617 /// Decided at retained from source records for staff review, safety gates, and workflow joins.
618 decided_at: DateTime<Utc>,
619 },
620 /// Reservation is no longer active.
621 Cancelled,
622 /// Superseded state or source category preserved for normalized resort records.
623 Superseded,
624 }
625
626 impl Lifecycle {
627 /// Returns the normalized operational status represented by this record.
628 pub fn status(&self) -> Status {
629 match self {
630 Self::ApprovalRequested => Status::ApprovalRequested,
631 Self::Approved { .. } => Status::Approved,
632 Self::Rejected { .. } => Status::Rejected,
633 Self::Cancelled => Status::Cancelled,
634 Self::Superseded => Status::Superseded,
635 }
636 }
637
638 /// Reports whether the review lifecycle has reached an approval, rejection, or non-applicable endpoint.
639 pub fn is_terminal_decision(&self) -> bool {
640 matches!(self, Self::Approved { .. } | Self::Rejected { .. })
641 }
642
643 /// Returns the accountable actor and timestamp when the review reached a terminal decision.
644 pub fn decision_actor_and_time(&self) -> Option<(&ActorRef, DateTime<Utc>)> {
645 match self {
646 Self::Approved {
647 decided_by,
648 decided_at,
649 }
650 | Self::Rejected {
651 decided_by,
652 decided_at,
653 } => Some((decided_by, *decided_at)),
654 Self::ApprovalRequested | Self::Cancelled | Self::Superseded => None,
655 }
656 }
657 }
658
659 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
660 /// Normalized lifecycle states used to reconcile source-system data with domain workflows.
661 pub enum Status {
662 /// Approval requested state or source category preserved for normalized resort records.
663 ApprovalRequested,
664 /// Approved state or source category preserved for normalized resort records.
665 Approved,
666 /// Rejected state or source category preserved for normalized resort records.
667 Rejected,
668 /// Reservation is no longer active.
669 Cancelled,
670 /// Superseded state or source category preserved for normalized resort records.
671 Superseded,
672 }
673}
674
675#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
676/// Document record tying storage, classification, source, scan, redaction, and review status together.
677pub struct Document {
678 /// Id retained from source records for staff review, safety gates, and workflow joins.
679 pub id: DocumentId,
680 /// Location id retained from source records for staff review, safety gates, and workflow joins.
681 pub location_id: LocationId,
682 /// Subject retained from source records for staff review, safety gates, and workflow joins.
683 pub subject: DocumentSubject,
684 /// Classification retained from source records for staff review, safety gates, and workflow joins.
685 pub classification: document::Classification,
686 /// Source retained from source records for staff review, safety gates, and workflow joins.
687 pub source: document::Source,
688 /// Uploaded by actor retained from source records for staff review, safety gates, and workflow joins.
689 pub uploaded_by_actor: ActorRef,
690 /// Uploaded at retained from source records for staff review, safety gates, and workflow joins.
691 pub uploaded_at: DateTime<Utc>,
692 /// Original file retained from source records for staff review, safety gates, and workflow joins.
693 pub original_file: document::OriginalFile,
694 /// Storage ref retained from source records for staff review, safety gates, and workflow joins.
695 pub storage_ref: document::StorageRef,
696 /// Virus scan status retained from source records for staff review, safety gates, and workflow joins.
697 pub virus_scan_status: document::VirusScanStatus,
698 /// Pii redaction status retained from source records for staff review, safety gates, and workflow joins.
699 pub pii_redaction_status: document::PiiRedactionStatus,
700 /// Verification status retained from source records for staff review, safety gates, and workflow joins.
701 pub verification_status: document::Status,
702 #[builder(default)]
703 /// Audit refs retained from source records for staff review, safety gates, and workflow joins.
704 pub audit_refs: Vec<crate::audit::EventId>,
705}
706
707impl Document {
708 /// Reports whether the document must be reviewed before agents or staff treat it as usable evidence.
709 pub fn requires_human_review_before_use(&self) -> bool {
710 matches!(
711 self.verification_status,
712 document::Status::Received
713 | document::Status::Extracting
714 | document::Status::ExtractionFailed
715 | document::Status::AwaitingReview
716 | document::Status::QuarantinedRejected
717 ) || !matches!(self.virus_scan_status, document::VirusScanStatus::Passed)
718 }
719}
720
721#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
722/// Entity or workflow subject a document is evidence for.
723pub enum DocumentSubject {
724 /// Customer record participating in the workflow.
725 Customer(CustomerId),
726 /// Pet record participating in the workflow.
727 Pet(PetId),
728 /// Reservation record participating in the workflow.
729 Reservation(reservation::Id),
730 /// Incident record participating in the workflow.
731 Incident(IncidentId),
732}
733
734#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
735/// Vaccine compliance record linking pet, vaccine name, expiration, proof document, and review status.
736pub struct VaccineRecord {
737 /// Id retained from source records for staff review, safety gates, and workflow joins.
738 pub id: VaccineRecordId,
739 /// Pet receiving the grooming or care service.
740 pub pet_id: PetId,
741 /// Vaccine name retained from source records for staff review, safety gates, and workflow joins.
742 pub vaccine_name: policy::VaccineName,
743 /// Source document id retained from source records for staff review, safety gates, and workflow joins.
744 pub source_document_id: DocumentId,
745 /// Status retained from source records for staff review, safety gates, and workflow joins.
746 pub status: vaccine::Status,
747 /// Effective on retained from source records for staff review, safety gates, and workflow joins.
748 pub effective_on: NaiveDate,
749 /// Expires on retained from source records for staff review, safety gates, and workflow joins.
750 pub expires_on: Option<NaiveDate>,
751 /// Review gate retained from source records for staff review, safety gates, and workflow joins.
752 pub review_gate: policy::ReviewGate,
753 #[builder(default)]
754 /// Audit refs retained from source records for staff review, safety gates, and workflow joins.
755 pub audit_refs: Vec<crate::audit::EventId>,
756}
757
758impl VaccineRecord {
759 /// Reports whether vaccine proof is still unverified, rejected, or otherwise unsafe for compliance automation.
760 pub fn requires_human_review_before_compliance(&self) -> bool {
761 matches!(
762 self.status,
763 vaccine::Status::SuggestedExtracted
764 | vaccine::Status::PendingReview
765 | vaccine::Status::Rejected
766 | vaccine::Status::ExceptionRequested
767 )
768 }
769}
770
771#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
772/// Care note with author, visibility, subject, body, source, and review-sensitive timestamps.
773pub struct CareNote {
774 /// Id retained from source records for staff review, safety gates, and workflow joins.
775 pub id: care_note::Id,
776 /// Subject retained from source records for staff review, safety gates, and workflow joins.
777 pub subject: care_note::Subject,
778 /// Kind retained from source records for staff review, safety gates, and workflow joins.
779 pub kind: care_note::Kind,
780 /// Visibility retained from source records for staff review, safety gates, and workflow joins.
781 pub visibility: care_note::Visibility,
782 /// Body retained from source records for staff review, safety gates, and workflow joins.
783 pub body: care_note::Body,
784 /// Author retained from source records for staff review, safety gates, and workflow joins.
785 pub author: ActorRef,
786 /// Recorded at retained from source records for staff review, safety gates, and workflow joins.
787 pub recorded_at: DateTime<Utc>,
788 #[builder(default)]
789 /// Audit refs retained from source records for staff review, safety gates, and workflow joins.
790 pub audit_refs: Vec<crate::audit::EventId>,
791}
792
793impl CareNote {
794 /// Reports whether this care note may be surfaced to customers without an additional approval gate.
795 pub fn is_customer_visible_without_review(&self) -> bool {
796 matches!(self.visibility, care_note::Visibility::CustomerVisible)
797 && !matches!(
798 self.kind,
799 care_note::Kind::Medication | care_note::Kind::Medical | care_note::Kind::Behavior
800 )
801 }
802}
803
804#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
805/// Incident record used for manager attention, safety follow-up, customer messaging, and audit evidence.
806pub struct Incident {
807 /// Id retained from source records for staff review, safety gates, and workflow joins.
808 pub id: IncidentId,
809 /// Location id retained from source records for staff review, safety gates, and workflow joins.
810 pub location_id: LocationId,
811 /// Primary subject retained from source records for staff review, safety gates, and workflow joins.
812 pub primary_subject: IncidentSubject,
813 /// Category retained from source records for staff review, safety gates, and workflow joins.
814 pub category: incident::Category,
815 /// Severity retained from source records for staff review, safety gates, and workflow joins.
816 pub severity: incident::Severity,
817 /// Status retained from source records for staff review, safety gates, and workflow joins.
818 pub status: incident::Status,
819 /// Reported by retained from source records for staff review, safety gates, and workflow joins.
820 pub reported_by: ActorRef,
821 /// Reported at retained from source records for staff review, safety gates, and workflow joins.
822 pub reported_at: DateTime<Utc>,
823 /// Summary retained from source records for staff review, safety gates, and workflow joins.
824 pub summary: incident::Summary,
825 #[builder(default)]
826 /// Required review gates retained from source records for staff review, safety gates, and workflow joins.
827 pub required_review_gates: Vec<policy::ReviewGate>,
828 #[builder(default)]
829 /// Audit refs retained from source records for staff review, safety gates, and workflow joins.
830 pub audit_refs: Vec<crate::audit::EventId>,
831}
832
833impl Incident {
834 /// Reports whether the incident is still active enough to require manager attention.
835 pub fn requires_manager_attention(&self) -> bool {
836 matches!(
837 self.status,
838 incident::Status::NeedsManagerReview | incident::Status::LegalHold
839 ) || matches!(
840 self.severity,
841 incident::Severity::High | incident::Severity::Critical
842 ) || self
843 .required_review_gates
844 .contains(&policy::ReviewGate::ManagerApproval)
845 }
846}
847
848#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
849/// Entity or workflow subject affected by an incident.
850pub enum IncidentSubject {
851 /// Pet record participating in the workflow.
852 Pet(PetId),
853 /// Reservation record participating in the workflow.
854 Reservation(reservation::Id),
855 /// Customer record participating in the workflow.
856 Customer(CustomerId),
857 /// Resort location record participating in the workflow.
858 Location(LocationId),
859}
860
861#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Builder)]
862/// Customer/internal message record that tracks subject, channel, draft/reference body, approval, and delivery state.
863pub struct Message {
864 /// Id retained from source records for staff review, safety gates, and workflow joins.
865 pub id: MessageId,
866 /// Subject retained from source records for staff review, safety gates, and workflow joins.
867 pub subject: MessageSubject,
868 /// Direction retained from source records for staff review, safety gates, and workflow joins.
869 pub direction: message::Direction,
870 /// Channel retained from source records for staff review, safety gates, and workflow joins.
871 pub channel: message::Channel,
872 /// Status retained from source records for staff review, safety gates, and workflow joins.
873 pub status: message::Status,
874 /// Body ref retained from source records for staff review, safety gates, and workflow joins.
875 pub body_ref: message::BodyRef,
876 /// Approval gate retained from source records for staff review, safety gates, and workflow joins.
877 pub approval_gate: Option<policy::ReviewGate>,
878 #[builder(default)]
879 /// Audit refs retained from source records for staff review, safety gates, and workflow joins.
880 pub audit_refs: Vec<crate::audit::EventId>,
881}
882
883impl Message {
884 /// Reports whether the message is still a draft or awaiting approval before any outbound send.
885 pub fn requires_approval_before_send(&self) -> bool {
886 self.approval_gate.is_some()
887 || matches!(self.status, message::Status::ApprovalRequested)
888 || matches!(self.direction, message::Direction::OutboundDraft)
889 }
890}
891
892#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
893/// Entity or workflow subject that a message refers to.
894pub enum MessageSubject {
895 /// Customer record participating in the workflow.
896 Customer(CustomerId),
897 /// Pet record participating in the workflow.
898 Pet(PetId),
899 /// Reservation record participating in the workflow.
900 Reservation(reservation::Id),
901 /// Incident record participating in the workflow.
902 Incident(IncidentId),
903 /// Approval decision record participating in audit history.
904 Approval(approval::Id),
905}
906
907/// Audit vocabulary for source-backed event trails across automated and staff actions.
908pub mod audit {
909 use chrono::{DateTime, Utc};
910 use nutype::nutype;
911 #[allow(unused_imports)]
912 use serde::{Deserialize, Serialize};
913 use std::collections::BTreeMap;
914
915 use super::{
916 CustomerId, DocumentId, IncidentId, LocationId, MessageId, PetId, VaccineRecordId,
917 approval, care_note, reservation,
918 };
919
920 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
921 /// Audit event capturing actor, subject, action, timestamp, and metadata evidence.
922 pub struct Event {
923 /// At retained from source records for staff review, safety gates, and workflow joins.
924 pub at: DateTime<Utc>,
925 /// Actor retained from source records for staff review, safety gates, and workflow joins.
926 pub actor: super::ActorRef,
927 /// Subject retained from source records for staff review, safety gates, and workflow joins.
928 pub subject: Subject,
929 /// Action retained from source records for staff review, safety gates, and workflow joins.
930 pub action: Action,
931 /// Metadata retained from source records for staff review, safety gates, and workflow joins.
932 pub metadata: BTreeMap<MetadataKey, MetadataValue>,
933 }
934
935 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
936 /// Subject that a care, document, incident, audit, or message record is about.
937 pub enum Subject {
938 /// Customer record participating in the workflow.
939 Customer(CustomerId),
940 /// Pet record participating in the workflow.
941 Pet(PetId),
942 /// Reservation record participating in the workflow.
943 Reservation(reservation::Id),
944 /// Resort location record participating in the workflow.
945 Location(LocationId),
946 /// Customer or pet document participating in review.
947 Document(DocumentId),
948 /// Vaccination document or status record under review.
949 VaccineRecord(VaccineRecordId),
950 /// Care note state or source category preserved for normalized resort records.
951 CareNote(care_note::Id),
952 /// Incident record participating in the workflow.
953 Incident(IncidentId),
954 /// Customer communication record participating in approval.
955 Message(MessageId),
956 /// Approval decision record participating in audit history.
957 Approval(approval::Id),
958 /// Workflow event state or source category preserved for normalized resort records.
959 WorkflowEvent(crate::workflow::EventId),
960 /// External system object referenced from domain history.
961 External {
962 /// Provider retained from source records for staff review, safety gates, and workflow joins.
963 provider: crate::workflow::external::Provider,
964 /// Id retained from source records for staff review, safety gates, and workflow joins.
965 id: crate::workflow::external::Id,
966 },
967 }
968
969 #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
970 /// Auditable action category produced by staff, source ingestion, policy, approval, or automation.
971 pub enum Action {
972 /// Customer profile updated state or source category preserved for normalized resort records.
973 CustomerProfileUpdated,
974 /// Pet profile updated state or source category preserved for normalized resort records.
975 PetProfileUpdated,
976 /// Reservation status suggested state or source category preserved for normalized resort records.
977 ReservationStatusSuggested,
978 /// Reservation status changed state or source category preserved for normalized resort records.
979 ReservationStatusChanged,
980 /// Policy decision recorded state or source category preserved for normalized resort records.
981 PolicyDecisionRecorded,
982 /// Document received state or source category preserved for normalized resort records.
983 DocumentReceived,
984 /// Vaccine record review requested state or source category preserved for normalized resort records.
985 VaccineRecordReviewRequested,
986 /// Incident status changed state or source category preserved for normalized resort records.
987 IncidentStatusChanged,
988 /// Message approval requested state or source category preserved for normalized resort records.
989 MessageApprovalRequested,
990 /// Approval decision recorded state or source category preserved for normalized resort records.
991 ApprovalDecisionRecorded,
992 /// Workflow event recorded state or source category preserved for normalized resort records.
993 WorkflowEventRecorded,
994 /// Extension point for provider-specific values not modeled directly.
995 Extension(ActionLabel),
996 }
997
998 /// Human-readable audit action label for imported or locally defined operational events.
999 #[nutype(
1000 sanitize(trim),
1001 validate(not_empty, len_char_max = 160),
1002 derive(
1003 Debug,
1004 Clone,
1005 PartialEq,
1006 Eq,
1007 PartialOrd,
1008 Ord,
1009 Hash,
1010 Serialize,
1011 Deserialize
1012 )
1013 )]
1014 pub struct ActionLabel(String);
1015
1016 /// Audit metadata key used to preserve source evidence without flattening it into prose.
1017 #[nutype(
1018 sanitize(trim),
1019 validate(not_empty, len_char_max = 80),
1020 derive(
1021 Debug,
1022 Clone,
1023 PartialEq,
1024 Eq,
1025 PartialOrd,
1026 Ord,
1027 Hash,
1028 Serialize,
1029 Deserialize
1030 )
1031 )]
1032 pub struct MetadataKey(String);
1033
1034 /// Audit metadata value attached to an event for review, reporting, or source repair.
1035 #[nutype(
1036 sanitize(trim),
1037 validate(not_empty, len_char_max = 500),
1038 derive(
1039 Debug,
1040 Clone,
1041 PartialEq,
1042 Eq,
1043 PartialOrd,
1044 Ord,
1045 Hash,
1046 Serialize,
1047 Deserialize
1048 )
1049 )]
1050 pub struct MetadataValue(String);
1051}
1052
1053#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1054/// Actor that performed or is accountable for an audited action.
1055pub enum ActorRef {
1056 /// Customer record participating in the workflow.
1057 Customer(CustomerId),
1058 /// Staff id retained from source records for staff review, safety gates, and workflow joins.
1059 Staff {
1060 /// Staff id attached to this variant for reviewers and adapters.
1061 staff_id: StaffId,
1062 },
1063 /// Manager id retained from source records for staff review, safety gates, and workflow joins.
1064 Manager {
1065 /// Manager id attached to this variant for reviewers and adapters.
1066 manager_id: ManagerId,
1067 },
1068 /// System state or source category preserved for normalized resort records.
1069 System,
1070 /// Workflow retained from source records for staff review, safety gates, and workflow joins.
1071 Agent {
1072 /// Workflow attached to this variant for reviewers and adapters.
1073 workflow: agent::Name,
1074 },
1075}