Skip to main content

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}