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}