Files
alla-allaos-fullstack/plans/task-d.5.2.md
2026-06-24 13:39:25 +07:00

6.6 KiB

Task D.5.2: Lead Domain Service & API Foundation

Status

Planned

Objective

Build the production Lead service layer and API foundation on top of the existing D.5.1 Lead Foundation.

This task introduces Lead as a first-class CRM domain without changing assignment workflows, dashboard datasets, reports, or legacy enquiry behavior.

The objective is to:

  • establish Lead service architecture
  • establish Lead API contracts
  • establish Lead security boundaries
  • establish Lead follow-up lifecycle handling
  • prepare D.5.3 Lead Assignment → Create Enquiry

Mandatory Review

Review before implementation:

  • AGENTS.md
  • docs/standards/project-foundations.md
  • docs/standards/task-catalog.md
  • docs/adr/0018-lead-enquiry-domain-separation.md
  • docs/implementation/task-d5-lead-enquiry-domain-separation.md
  • docs/implementation/task-d51-lead-foundation-stabilization-output-completion.md
  • Customer Ownership Foundation
  • Authorization Foundation
  • Audit Foundation
  • Master Option Foundation
  • Document Sequence Foundation

Foundation Rules

The following already exist and must be reused:

crm_leads
crm_enquiries.lead_id

crm_lead_awareness
crm_lead_status
crm_lead_followup_status
crm_lead_lost_reason

crm_lead document sequence
crm_enquiry document sequence

Do not recreate:

tables
migrations
seed categories
document sequence configuration

Scope D5.2.1 Lead Service Layer

Create:

src/features/crm/leads/server/service.ts

Required operations:

listLeads()
getLeadById()
createLead()
updateLead()
deleteLead()

Rules:

  • Use crm_leads as the Lead source of truth
  • No direct DB access from route handlers
  • Keep legacy enquiry behavior unchanged
  • Do not create enquiry from lead in this task

Reuse:

Customer Foundation
Audit Foundation
Authorization Foundation
Document Sequence Foundation
Master Option Foundation

Scope D5.2.2 Lead DTO Contracts

Create:

src/features/crm/leads/types.ts

Request contracts:

CreateLeadInput
UpdateLeadInput
LeadListFilters
CreateLeadFollowupInput

Response contracts:

LeadSummary
LeadDetail
LeadListResponse
LeadFollowupSummary

Lead Detail must include:

suggestedSalesOwnerId

when customer owner exists.

Important:

Do not auto assign.
Do not create enquiry.
This is suggestion only.

Scope D5.2.3 Lead Code Generation

Use existing document sequence foundation.

Document type:

crm_lead

Expected format:

LD2606-001

No custom numbering logic allowed.


Scope D5.2.4 Lead API Routes

Create:

GET    /api/crm/leads
POST   /api/crm/leads

GET    /api/crm/leads/[id]
PATCH  /api/crm/leads/[id]
DELETE /api/crm/leads/[id]

Routes must call:

Lead Service Layer

Route handlers must not query Drizzle directly.


Scope D5.2.5 Lead Follow-up Foundation

Create:

GET  /api/crm/leads/[id]/followups
POST /api/crm/leads/[id]/followups

Rules:

  • Reuse existing CRM follow-up pattern
  • Do not create a second follow-up architecture
  • Use lead follow-up status from master options
  • Keep follow-up scoped to organization and CRM access

Scope D5.2.6 Lead Security

Reuse:

resolveCrmMembershipAccess()

Visibility:

Marketing:

own leads

Managers:

team scope

Admins:

organization scope

Rules:

  • Do not check role strings directly
  • Use resolved CRM access
  • Enforce security in service layer
  • UI visibility alone is not enough

Scope D5.2.7 Customer Ownership Integration

When customer owner exists:

customer.ownerUserId

Return:

suggestedSalesOwnerId

in Lead Detail.

Important:

  • Do not auto assign
  • Do not create enquiry
  • Do not update crm_enquiries
  • This is suggestion only

Scope D5.2.8 Master Option Integration

Lead APIs must expose options through existing master-option infrastructure:

awareness
status
followupStatus
lostReason

Use categories:

crm_lead_awareness
crm_lead_status
crm_lead_followup_status
crm_lead_lost_reason

Rules:

  • No hardcoded labels
  • Option values must come from foundation master options
  • Keep inactive options hidden from normal API responses unless explicitly requested

Scope D5.2.9 Audit Logging

Reuse:

auditCreate()
auditUpdate()
auditDelete()
auditAction()

Required audit actions:

create_lead
update_lead
delete_lead
view_lead
create_lead_followup

Rules:

  • Audit every mutation
  • Audit lead detail view if existing audit convention supports view logging
  • Do not introduce a separate audit pattern

Scope D5.2.10 Legacy Compatibility

Keep current system operational.

Current legacy behavior:

crm_enquiries.pipeline_stage

must remain untouched.

Do not:

change enquiry services
change assignment flow
change dashboard
change reports
change won/lost synchronization

Those belong to later D.5 phases.


Deliverables

New:

src/features/crm/leads/**

New APIs:

/api/crm/leads
/api/crm/leads/[id]
/api/crm/leads/[id]/followups

Documentation:

docs/implementation/task-d52-lead-domain-service-api-foundation.md

Expected Outputs

Lead Service:

CRUD operational

Lead API:

CRUD operational

Lead Follow-up:

API operational

Security:

resolved CRM access enforced

Audit:

lead actions recorded

Legacy CRM:

unchanged

Explicit Non-Scope

Do not:

  • create Lead UI
  • create Lead assignment flow
  • create Lead → Enquiry conversion
  • create Enquiry from Lead
  • update dashboard
  • update reports
  • migrate legacy data
  • remove pipeline_stage
  • change existing enquiry APIs
  • change quotation conversion behavior

These belong to:

D.5.3+

Verification

Run:

npm exec tsc --noEmit

Verify:

Create Lead
Update Lead
Delete Lead
View Lead
List Lead
Lead code generation
Lead follow-up creation
Lead follow-up listing
Audit logging
Current Enquiry APIs still function
Current Dashboard still functions
Current Reports still function

Definition of Done

Task is complete when:

  • Lead service layer exists
  • Lead CRUD APIs exist
  • Lead follow-up APIs exist
  • Lead security uses resolved CRM access
  • Lead code generation uses sequence foundation
  • Lead master options use foundation categories
  • Audit logging exists
  • Existing CRM functionality remains unchanged

Result:

Lead Domain Service = Established
Lead API Foundation = Established
Ready for D.5.3 Lead Assignment → Create Enquiry