Skip to main content

domain/
lead.rs

1//! Cross-service lead conversion triage for resort sales follow-up.
2//!
3//! These types describe resort sales/intake state independent of any one
4//! service line. They promote web/phone/SMS/source facts into validated sales
5//! workflow state so follow-up labor, booking readiness, and revenue opportunities
6//! are visible without letting an agent invent availability or bypass staff review.
7
8use nutype::nutype;
9#[allow(unused_imports)]
10use serde::{Deserialize, Serialize};
11
12use crate::entities::{CustomerId, ServiceKind};
13use crate::operations;
14
15#[nutype(
16    sanitize(trim),
17    validate(not_empty, len_char_max = 160),
18    derive(
19        Debug,
20        Clone,
21        PartialEq,
22        Eq,
23        PartialOrd,
24        Ord,
25        Hash,
26        Serialize,
27        Deserialize
28    )
29)]
30/// Validated local-referral/source name for lead provenance.
31pub struct SourceName(String);
32
33#[nutype(
34    sanitize(trim),
35    validate(not_empty, len_char_max = 160),
36    derive(
37        Debug,
38        Clone,
39        PartialEq,
40        Eq,
41        PartialOrd,
42        Ord,
43        Hash,
44        Serialize,
45        Deserialize
46    )
47)]
48/// Validated campaign name used to connect lead work to marketing sources.
49pub struct CampaignName(String);
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
52/// Lead triage record that turns source contact evidence into safe sales follow-up work.
53pub struct Triage {
54    /// Existing customer record when staff can link the lead to a known account.
55    pub customer_id: Option<CustomerId>,
56    /// Channel or campaign that explains where the lead came from.
57    pub source: Source,
58    /// Service or change the customer appears to be asking about.
59    pub intent: Intent,
60    /// Sales stage used to rank follow-up labor and booking readiness.
61    pub stage: ConversionStage,
62    /// Requested resort service when the source evidence is specific enough.
63    pub requested_service: Option<ServiceKind>,
64    /// Staff-safe next step; automation may draft, route, or summarize but not book or promise capacity.
65    pub next_action: NextAction,
66}
67
68#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
69/// Lead source retained so marketing and intake teams can audit where demand originated.
70pub enum Source {
71    /// Lead originated from a website form and may be routed to intake follow-up.
72    WebsiteForm,
73    /// Lead originated from a phone call or voicemail that staff may need to summarize or return.
74    Phone,
75    /// Lead originated from SMS and should respect texting consent and response boundaries.
76    Sms,
77    /// Lead originated from email and can support draft replies after staff-safe triage.
78    Email,
79    /// Lead originated from social media and may need attribution or identity verification.
80    SocialMedia,
81    /// Local referral name staff can verify before attributing the lead source.
82    LocalReferral {
83        /// Referral source name preserved for staff attribution and deduplication.
84        source_name: SourceName,
85    },
86    /// Contact or display name used by staff.
87    Campaign {
88        /// Campaign name preserved for marketing attribution and follow-up reporting.
89        name: CampaignName,
90    },
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94/// Prospect intent signal used to route boarding, daycare, grooming, or training follow-up.
95pub enum Intent {
96    /// New prospect asking about onboarding, requirements, availability, or first booking.
97    NewCustomerIntake,
98    /// Prospect wants boarding pricing or availability that staff must confirm before promising.
99    BoardingQuote,
100    /// Prospect is asking about daycare trial or evaluation; staff must confirm eligibility steps.
101    DaycareTrial,
102    /// Prospect wants grooming scheduling, which depends on service, pet, and capacity review.
103    GroomingAppointment,
104    /// Prospect wants training consultation routed to the appropriate trainer or intake path.
105    TrainingConsult,
106    /// Existing customer appears to need a booking or profile change rather than new intake.
107    ExistingCustomerChange,
108    /// Lead intent is unclear; automation may summarize but staff must classify before booking promises.
109    Unknown,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
113/// Conversion stage that separates new inquiries from booked, lost, or inactive demand.
114pub enum ConversionStage {
115    /// New lead awaiting first staff or automated draft response.
116    New,
117    /// Staff or automation attempted contact and the next step depends on response evidence.
118    ContactAttempted,
119    /// Lead is paused until the customer supplies missing answers or documents.
120    WaitingOnCustomer,
121    /// Lead cannot be booked until vaccine, pet profile, policy, or other requirements are confirmed.
122    MissingRequirements,
123    /// Intake evidence looks booking-ready, but staff must still confirm capacity and policies before committing.
124    ReadyToBook,
125    /// Lead has converted into booked or active customer work and should avoid duplicate sales follow-up.
126    Converted,
127    /// Lead is inactive or declined, retained for attribution and future analysis.
128    Lost,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
132/// Human-safe next step for converting a lead without overpromising capacity or policy.
133pub enum NextAction {
134    /// Automation may draft a reply, but sending still follows channel and approval gates.
135    DraftReply,
136    /// Ask for pet profile details needed before eligibility or booking review.
137    RequestMissingPetProfile,
138    /// Ask for vaccine proof before trial, daycare, boarding, or grooming readiness decisions.
139    RequestVaccineProof,
140    /// Staff-confirmed availability can be offered; automation must not invent or hold times.
141    OfferReservationTimes,
142    /// Route to staff when source facts, policy, or customer context are too ambiguous for automation.
143    RouteToHuman {
144        /// Business reason staff should review before proceeding.
145        reason: operations::operational::Observation,
146    },
147    /// No current follow-up is appropriate, usually because the lead is converted, lost, or waiting.
148    NoAction,
149}