Files
alla-allaos-fullstack/docs/adr/0018-lead-enquiry-domain-separation.md
phaichayon 9c75788ba7 task-d.5
task-d.5.1
2026-06-24 12:28:04 +07:00

118 lines
4.3 KiB
Markdown

# ADR 0018: Lead / Enquiry Domain Separation
## Status
Proposed
## Context
ADR-0011 froze the current CRM lifecycle around a single persisted entity:
- `crm_enquiries` stores both marketing-owned leads and sales-owned enquiries
- `pipeline_stage` acts as the discriminator
- navigation separation exists, but domain separation does not
That model was an intentional stabilization step for Tasks D.3 and D.3.1. It reduced UX ambiguity without forcing a schema split during the first production rollout.
Task D.5 introduces a stronger business requirement:
- Marketing owns `Lead` as a dedicated entity
- Sales owns `Enquiry` as a dedicated entity
- one lead may create many enquiries
- sales may also create enquiries directly without a lead
- marketing outcome must be derived from sales execution, not manually controlled
The current single-record model now creates structural ambiguity in at least these areas:
1. Assignment currently mutates one record from `lead -> enquiry`, which destroys the original lead as a stable marketing record.
2. A true `1 Lead -> N Enquiries` relationship cannot be represented cleanly while the lead itself is also the enquiry record.
3. Dashboard and report logic still infer lead analytics from `crm_enquiries.pipeline_stage`, which couples marketing and sales datasets.
4. Outcome synchronization for marketing is harder to reason about because the source marketing entity does not exist independently.
## Decision
We will replace the single-record lead/enquiry persistence model with a split domain model:
- `crm_leads` becomes the dedicated marketing-owned lead table
- `crm_enquiries` remains the dedicated sales-owned enquiry table
- `crm_enquiries.lead_id` becomes nullable to support:
- lead-origin enquiries
- direct sales enquiries with `lead_id = null`
### Lifecycle
The target business flow is:
```txt
Lead
-> Enquiry
-> Quotation
-> Won / Lost
```
### Relationship rules
- `crm_leads 1 -> N crm_enquiries`
- `crm_enquiries 1 -> N crm_quotations`
- `crm_quotations` remains the owning record for quotation revisions and child resources
### Ownership rules
- marketing owns lead creation and lead follow-up
- sales owns enquiry creation, enquiry follow-up, quotation generation, and won/lost execution
- managers and admins retain cross-workspace monitoring based on resolved CRM access
### Outcome rules
- lead outcome is derived, never manually updated
- when any linked enquiry becomes won, the lead outcome becomes `won`
- when all linked enquiries are lost, the lead outcome becomes `lost`
- otherwise the lead outcome remains `open`
### Sequence rules
- lead codes use a dedicated lead document sequence
- enquiry codes keep a separate enquiry document sequence
### Reporting and dashboard rules
- lead KPI and lead reports read from `crm_leads`
- enquiry KPI and enquiry reports read from `crm_enquiries`
- no report should continue to treat `pipeline_stage` as the marketing/sales entity boundary after migration
## Consequences
### Positive
- aligns persistence with the real marketing-to-sales handoff
- supports true `1 Lead -> N Enquiries`
- preserves lead identity after assignment
- simplifies marketing analytics and awareness-source reporting
- makes direct sales enquiries first-class without overloading lead semantics
### Tradeoffs
- supersedes a previously accepted ADR and requires broad migration across services, reports, dashboard, and permissions
- requires data migration from existing `crm_enquiries.pipeline_stage`
- increases temporary compatibility complexity during rollout
## Migration Strategy
The migration should be delivered in explicit phases:
1. Introduce ADR and governance freeze for split-domain direction.
2. Add schema and seed support for `crm_leads`, `lead_id`, and lead master options.
3. Introduce lead services and lead APIs without deleting enquiry flows.
4. Migrate dashboard and reports to separated datasets.
5. Remove old single-record assumptions from shared enquiry services and UI.
## Supersedes
This ADR is intended to supersede the following sections of ADR-0011 once implemented:
- `Single record model`
- `Pipeline stage model` as the lead/enquiry persistence boundary
- `Navigation Separation` as the primary separation mechanism
Until implementation is complete, ADR-0011 remains the description of current production behavior, while this ADR defines the approved target direction for Task D.5.