3.5 KiB
ADR 0011: Lead and Enquiry Ownership Model
Status
Accepted
Context
The CRM module originally used a mixed terminology model where:
Leadmeant an unassigned enquiryOpportunitymeant an assigned enquiry
That model no longer matched the business process. The business now distinguishes ownership by function:
Leadis marketing-ownedEnquiryis sales-owned
The system must preserve the single-source-of-truth table crm_enquiries while refining lifecycle, permissions, monitoring visibility, and KPI semantics.
Decision
1. Single record model
crm_enquiriesremains the single source of truth- no
crm_leadstable is introduced - no split lead form or split enquiry API is introduced
2. Pipeline stage model
crm_enquiries.pipeline_stage is the lifecycle discriminator with allowed values:
leadenquiryclosed_wonclosed_lost
3. Ownership model
leadis marketing-ownedenquiryis sales-owned- assignment converts a lead into an enquiry
4. Assignment behavior
On assign:
assignedToUserIdis setassignedAtis setassignedByis setpipelineStagebecomesenquiry
On reassign:
- assignee metadata is updated
pipelineStageremainsenquiry
5. Create behavior
- marketing-created records default to
pipelineStage = lead - sales-created records default to
pipelineStage = enquiry
6. Closure behavior
- lost or cancelled enquiry status resolves to
pipelineStage = closed_lost - accepted or lost/rejected quotation outcomes may synchronize the linked enquiry to:
closed_wonclosed_lost
7. Visibility policy
Marketing can monitor:
- leads
- enquiries
- follow-ups
- status
- pipeline stage
- enquiry owner
- won/lost result
Marketing cannot access:
- quotation pricing
- quotation items
- cost, discount, or margin views
- approval analytics or approval workflow data
Sales scope remains ownership-based:
salesandsales_supportare limited server-side to enquiries they created or are assigned to- managers and admins retain wider organization visibility
8. KPI terminology
User-facing dashboard terminology replaces Opportunity with Enquiry.
Count definitions:
Lead Count=pipelineStage = leadEnquiry Count=pipelineStage = enquiryWon Count=pipelineStage = closed_wonLost Count=pipelineStage = closed_lost
9. Navigation Separation
LeadandEnquiryare separate UX workspacesLeadandEnquiryare not separate domain entities- both workspaces continue to use the same
crm_enquiriesrecords pipelineStagedetermines whether a record appears in the Leads or Enquiries workspace- the navigation split reduces user confusion without duplicating schema, API, or service layers
Consequences
Positive
- matches the real business handoff from marketing to sales
- keeps backward-compatible storage in
crm_enquiries - removes ambiguous
opportunitywording from user-facing CRM surfaces - gives marketing monitoring visibility without exposing commercial data
- enforces own-or-assigned visibility server-side for sales roles
Tradeoffs
- lifecycle still depends partly on status mapping and quotation outcome synchronization
- the model does not yet include dedicated timestamps such as
closedWonAtorclosedLostAt - reporting still relies on current-state lifecycle fields rather than effective-dated snapshots
Supersedes
This ADR supersedes the opportunity terminology frozen in docs/implementation/task-j0-kpi-definition-freeze.md for user-facing CRM ownership and KPI language.