7.7 KiB
Task D.5: Lead / Enquiry Domain Separation
Objective
Refactor CRM pipeline architecture by separating Lead and Enquiry into dedicated business entities.
Replace the current shared crm_enquiries + pipelineStage model with a true business flow:
Lead
→ Enquiry
→ Quotation
→ Won / Lost
The new model must support:
1 Lead
→ N Enquiries
1 Enquiry
→ N Quotations
1 Quotation
→ N Options
and remove the ambiguity caused by stage-based mutation.
Business Discovery 3.1 (Frozen)
Marketing Flow
Marketing
↓
Create Lead
↓
Follow Up
↓
Assign Sales
↓
Create Enquiry
Marketing owns Leads.
Sales Flow
Sales
↓
Create Enquiry Directly
Sales can create Enquiries without a Lead.
Sales Execution Flow
Enquiry
↓
Quotation
↓
PO Received
↓
Won
or
Enquiry
↓
Lost
Mandatory Review
Before implementation review:
- AGENTS.md
- Project Foundations Registry
- Task Catalog
- ADR 0011 Lead / Enquiry Ownership Model
- ADR 0016 Won / Lost Lifecycle Governance
- Customer Ownership Foundation
- Reporting Foundation
- Authorization Foundation
- Dashboard Foundation
Required Skills
Governance
- AGENTS.md
- Task Contract Template
- Architecture Rules
- Task Review Checklist
CRM
- Lead / Enquiry Governance
- Won / Lost Governance
- Customer Ownership Governance
- Revenue Attribution Governance
Security
- CRM Authorization Foundation
- Scope Enforcement Foundation
Scope D5.1 Lead Table
Create:
crm_leads
Lead becomes a dedicated entity.
Core fields:
id
organizationId
branchId
code
customerId
contactId
projectName
projectLocation
awarenessId
status
followupStatus
lostReason
outcome
ownerMarketingUserId
createdBy
createdAt
updatedAt
deletedAt
Scope D5.2 Lead Awareness
Master option category:
crm_lead_awareness
Seed:
Google Search / Website
Social Media
Email Marketing
Visit
Exhibition / Event
Brochure / Catalog
Word of Mouth
Corporate Car
Product Label
Re-purchasing
Introducing
BCI
Purpose:
ลูกค้ารู้จักเราจากช่องทางใด
Used in:
- Lead Form
- Lead Dashboard
- Lead Reports
- Marketing Analytics
Scope D5.3 Lead Status
Master option:
crm_lead_status
Values:
new_job
follow_up
closed_lost
cancel
Display:
New Job
Follow Up
Closed Lost
Cancel
Scope D5.4 Lead Follow-up Status
Master option:
crm_lead_followup_status
Values:
budget_pending
project_under_review
spec_clarification
site_survey_waiting
drawing_followup
quotation_preparation
waiting_po
Display:
รองบประมาณ
ระหว่างพิจารณาโครงการ
เคลียร์สเปค
รอสำรวจหน้างาน
ติดตามแบบงาน
ระหว่างการเสนอราคา
รอลูกค้าออก PO
Visible only when:
Lead Status = Follow Up
Scope D5.5 Lead Lost Reason
Master option:
crm_lead_lost_reason
Values:
price
delivery_time
sales_person
service
customer
product_quality
other
transfer
Display:
ราคา
ระยะเวลาจัดส่ง
พนักงานขาย
การบริการ
ลูกค้า
คุณภาพสินค้า
อื่นๆ
Transfer
Visible only when:
Lead Status = Closed Lost
or
Lead Status = Cancel
Scope D5.6 Lead Outcome
Add:
crm_leads.outcome
Values:
open
won
lost
Purpose:
Marketing KPI and reporting.
Marketing must not update manually.
Scope D5.7 Enquiry Refactor
Refactor:
crm_enquiries
to become a pure Sales entity.
Remove Lead lifecycle responsibilities.
Add:
leadId nullable
Relationship:
crm_leads 1
→ N crm_enquiries
Scope D5.8 Lead Assignment
Replace:
pipelineStage change
with:
Create Enquiry
Flow:
Lead
↓
Assign Sales
↓
Create Enquiry
Lead remains.
Enquiry is created.
Scope D5.9 Direct Sales Enquiry
Support:
Sales
↓
Create Enquiry Directly
Business Rule:
leadId = null
Allowed.
Examples:
Existing Customer
Walk-in Customer
Direct Referral
Sales Prospecting
Scope D5.10 Multiple Product Types
Support:
1 Lead
→ N Enquiries
Example:
Lead LD2606-001
├─ EN2606-001 Crane
├─ EN2606-002 Dock Door
└─ EN2606-003 Solar
Each enquiry has:
productTypeId
salesmanId
assignedToUserId
independently.
Scope D5.11 Outcome Synchronization
Marketing should never update outcomes manually.
When:
Enquiry = Won
Update:
Lead Outcome = Won
Automatically.
When:
All Enquiries linked to Lead = Lost
Update:
Lead Outcome = Lost
Automatically.
Lead Outcome is derived from Enquiry outcomes.
Scope D5.12 Document Sequences
Create dedicated sequences.
Lead:
LD2606-001
Enquiry:
EN2606-001
Separate document types.
Separate counters.
Scope D5.13 Dashboard Refactor
Lead KPI Source:
crm_leads
Enquiry KPI Source:
crm_enquiries
No stage filtering.
Scope D5.14 Reporting Refactor
Update:
- Lead Pipeline
- Lead Aging
- Lead Conversion
- Enquiry Pipeline
- Enquiry Aging
- Funnel Reports
Reuse:
Reporting Foundation
No parallel reporting implementation.
Scope D5.15 Security Refactor
Lead visibility:
Marketing
Managers
Admins
Enquiry visibility:
Assigned Sales
Managers
Admins
Use:
resolveCrmMembershipAccess()
No direct role checks.
Scope D5.16 Data Migration
Migrate existing records.
Rules:
pipelineStage = lead
→ crm_leads
pipelineStage = enquiry
→ crm_enquiries
pipelineStage = closed_won
→ crm_enquiries
pipelineStage = closed_lost
→ crm_enquiries
Preserve:
- follow-ups
- customers
- attachments
- ownership
- audit history
Deliverables
New Tables
- crm_leads
Modified Tables
- crm_enquiries
New Master Options
- crm_lead_awareness
- crm_lead_status
- crm_lead_followup_status
- crm_lead_lost_reason
New APIs
/api/crm/leads/api/crm/leads/[id]/api/crm/leads/[id]/assign/api/crm/leads/[id]/followups
Updated APIs
/api/crm/enquiries/api/crm/dashboard/api/crm/reports
Documentation
Create:
docs/adr/0018-lead-enquiry-domain-separation.md
docs/implementation/task-d5-lead-enquiry-domain-separation.md
Explicit Non-Scope
Do NOT:
- redesign quotation workflow
- redesign approval workflow
- redesign PDF workflow
- redesign role model
Reuse existing foundations.
Verification
Verify:
1 Lead
→ N Enquiries
Verify:
1 Enquiry
→ N Quotations
Verify:
Sales Direct Enquiry
(leadId = null)
Verify:
Lead Outcome Auto Sync
Verify:
Lead Sequence
Enquiry Sequence
Verify:
Dashboard
Reports
Security
continue functioning.
Run:
npm exec tsc --noEmit
Definition of Done
Task is complete when:
- Lead and Enquiry are separate entities
- Sales can create Enquiries directly
- Marketing can create Leads
- 1 Lead → N Enquiries works
- 1 Enquiry → N Quotations works
- Lead outcomes are automatically derived from Enquiry outcomes
- Lead and Enquiry document sequences are independent
- Dashboard and Reports use separated datasets
- Security follows existing CRM authorization foundation
Result:
Lead Domain = Established
Enquiry Domain = Established
Marketing Pipeline = Clear
Sales Pipeline = Clear