# 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: ```txt Lead → Enquiry → Quotation → Won / Lost ``` The new model must support: ```txt 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 ```txt Marketing ↓ Create Lead ↓ Follow Up ↓ Assign Sales ↓ Create Enquiry ``` Marketing owns Leads. --- ## Sales Flow ```txt Sales ↓ Create Enquiry Directly ``` Sales can create Enquiries without a Lead. --- ## Sales Execution Flow ```txt Enquiry ↓ Quotation ↓ PO Received ↓ Won ``` or ```txt 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: ```txt crm_leads ``` Lead becomes a dedicated entity. Core fields: ```txt 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: ```txt crm_lead_awareness ``` Seed: ```txt Google Search / Website Social Media Email Marketing Visit Exhibition / Event Brochure / Catalog Word of Mouth Corporate Car Product Label Re-purchasing Introducing BCI ``` Purpose: ```txt ลูกค้ารู้จักเราจากช่องทางใด ``` Used in: * Lead Form * Lead Dashboard * Lead Reports * Marketing Analytics --- # Scope D5.3 Lead Status Master option: ```txt crm_lead_status ``` Values: ```txt new_job follow_up closed_lost cancel ``` Display: ```txt New Job Follow Up Closed Lost Cancel ``` --- # Scope D5.4 Lead Follow-up Status Master option: ```txt crm_lead_followup_status ``` Values: ```txt budget_pending project_under_review spec_clarification site_survey_waiting drawing_followup quotation_preparation waiting_po ``` Display: ```txt รองบประมาณ ระหว่างพิจารณาโครงการ เคลียร์สเปค รอสำรวจหน้างาน ติดตามแบบงาน ระหว่างการเสนอราคา รอลูกค้าออก PO ``` Visible only when: ```txt Lead Status = Follow Up ``` --- # Scope D5.5 Lead Lost Reason Master option: ```txt crm_lead_lost_reason ``` Values: ```txt price delivery_time sales_person service customer product_quality other transfer ``` Display: ```txt ราคา ระยะเวลาจัดส่ง พนักงานขาย การบริการ ลูกค้า คุณภาพสินค้า อื่นๆ Transfer ``` Visible only when: ```txt Lead Status = Closed Lost or Lead Status = Cancel ``` --- # Scope D5.6 Lead Outcome Add: ```txt crm_leads.outcome ``` Values: ```txt open won lost ``` Purpose: Marketing KPI and reporting. Marketing must not update manually. --- # Scope D5.7 Enquiry Refactor Refactor: ```txt crm_enquiries ``` to become a pure Sales entity. Remove Lead lifecycle responsibilities. Add: ```txt leadId nullable ``` Relationship: ```txt crm_leads 1 → N crm_enquiries ``` --- # Scope D5.8 Lead Assignment Replace: ```txt pipelineStage change ``` with: ```txt Create Enquiry ``` Flow: ```txt Lead ↓ Assign Sales ↓ Create Enquiry ``` Lead remains. Enquiry is created. --- # Scope D5.9 Direct Sales Enquiry Support: ```txt Sales ↓ Create Enquiry Directly ``` Business Rule: ```txt leadId = null ``` Allowed. Examples: ```txt Existing Customer Walk-in Customer Direct Referral Sales Prospecting ``` --- # Scope D5.10 Multiple Product Types Support: ```txt 1 Lead → N Enquiries ``` Example: ```txt Lead LD2606-001 ├─ EN2606-001 Crane ├─ EN2606-002 Dock Door └─ EN2606-003 Solar ``` Each enquiry has: ```txt productTypeId salesmanId assignedToUserId ``` independently. --- # Scope D5.11 Outcome Synchronization Marketing should never update outcomes manually. When: ```txt Enquiry = Won ``` Update: ```txt Lead Outcome = Won ``` Automatically. --- When: ```txt All Enquiries linked to Lead = Lost ``` Update: ```txt Lead Outcome = Lost ``` Automatically. --- Lead Outcome is derived from Enquiry outcomes. --- # Scope D5.12 Document Sequences Create dedicated sequences. Lead: ```txt LD2606-001 ``` Enquiry: ```txt EN2606-001 ``` Separate document types. Separate counters. --- # Scope D5.13 Dashboard Refactor Lead KPI Source: ```txt crm_leads ``` Enquiry KPI Source: ```txt crm_enquiries ``` No stage filtering. --- # Scope D5.14 Reporting Refactor Update: * Lead Pipeline * Lead Aging * Lead Conversion * Enquiry Pipeline * Enquiry Aging * Funnel Reports Reuse: ```txt Reporting Foundation ``` No parallel reporting implementation. --- # Scope D5.15 Security Refactor Lead visibility: ```txt Marketing Managers Admins ``` Enquiry visibility: ```txt Assigned Sales Managers Admins ``` Use: ```txt resolveCrmMembershipAccess() ``` No direct role checks. --- # Scope D5.16 Data Migration Migrate existing records. Rules: ```txt 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: ```txt 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: ```txt 1 Lead → N Enquiries ``` Verify: ```txt 1 Enquiry → N Quotations ``` Verify: ```txt Sales Direct Enquiry (leadId = null) ``` Verify: ```txt Lead Outcome Auto Sync ``` Verify: ```txt Lead Sequence Enquiry Sequence ``` Verify: ```txt Dashboard Reports Security ``` continue functioning. Run: ```txt 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