109 lines
3.4 KiB
Markdown
109 lines
3.4 KiB
Markdown
# Task D.5.3: Lead Assignment -> Create Enquiry Foundation
|
|
|
|
## Objective
|
|
|
|
Establish the first production lead-assignment flow that preserves `crm_leads` as the
|
|
marketing-owned source record while creating or reusing a linked `crm_enquiries` record for the
|
|
sales execution workspace.
|
|
|
|
## Review Completed
|
|
|
|
- `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-d52-lead-domain-service-api-foundation.md`
|
|
- `docs/security/crm-authorization-boundaries.md`
|
|
- `src/features/crm/leads/server/service.ts`
|
|
- `src/features/crm/enquiries/server/service.ts`
|
|
- `src/features/crm/customers/server/service.ts`
|
|
- `src/features/foundation/audit-log/service.ts`
|
|
- `src/features/foundation/document-sequence/service.ts`
|
|
|
|
## What Changed
|
|
|
|
- Added lead bootstrap and assignment fields to `crm_leads`:
|
|
- `description`
|
|
- `product_type`
|
|
- `priority`
|
|
- `estimated_value`
|
|
- `assigned_sales_owner_id`
|
|
- `assigned_at`
|
|
- `assigned_by`
|
|
- `assignment_remark`
|
|
- Added [assignment.service.ts](C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/crm/leads/server/assignment.service.ts)
|
|
with:
|
|
- `assignLead()`
|
|
- internal `createEnquiryFromLead()`
|
|
- Added [route.ts](C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/crm/leads/[id]/assign/route.ts)
|
|
for `POST /api/crm/leads/[id]/assign`
|
|
- Extended lead DTOs and schemas so new lead records can carry the data needed to bootstrap an
|
|
enquiry
|
|
- Added `assigned` to seeded `crm_lead_status`
|
|
- Tightened enquiry-owner validation so assignees must be sales-assignable members, not merely any
|
|
organization member
|
|
|
|
## Assignment Behavior
|
|
|
|
- route permission is `crm.lead.assign`
|
|
- service validates:
|
|
- lead exists and is active
|
|
- actor can access the lead through resolved CRM scope
|
|
- assignee belongs to the same organization and is a sales-assignable member
|
|
- if an active enquiry already exists for the lead:
|
|
- no second enquiry is created
|
|
- the existing enquiry is returned
|
|
- lead assignment metadata is synchronized
|
|
- if no active enquiry exists:
|
|
- enquiry code generation reuses `generateNextDocumentCode()` with `documentType = crm_enquiry`
|
|
- enquiry is created with `lead_id = crm_leads.id`
|
|
- enquiry owner compatibility fields use the existing enquiry model:
|
|
- `assigned_to_user_id`
|
|
- `assigned_at`
|
|
- `assigned_by`
|
|
- `assignment_remark`
|
|
|
|
## Lead -> Enquiry Bootstrap Mapping
|
|
|
|
When creating the enquiry from a lead, the flow copies:
|
|
|
|
- `customerId`
|
|
- `contactId`
|
|
- `description`
|
|
- `projectName`
|
|
- `projectLocation`
|
|
- `productType`
|
|
- `estimatedValue`
|
|
- `priority`
|
|
|
|
The enquiry title is derived from `lead.projectName` and falls back to `Lead <code>` when the
|
|
project name is empty.
|
|
|
|
## Audit Actions
|
|
|
|
This task records:
|
|
|
|
- `assign_lead` on `crm_lead`
|
|
- `create_enquiry_from_lead` on `crm_enquiry`
|
|
|
|
Captured linkage includes:
|
|
|
|
- `leadId`
|
|
- `enquiryId`
|
|
- `salesOwnerId`
|
|
|
|
## Compatibility Notes
|
|
|
|
This task intentionally does not change:
|
|
|
|
- quotation flows
|
|
- approval flows
|
|
- dashboard datasets
|
|
- reporting datasets
|
|
- won/lost lifecycle flows
|
|
- legacy enquiry list/detail APIs outside the stricter assignee validation
|
|
|
|
`crm_enquiries.pipeline_stage` remains in place for compatibility, but lead assignment now creates a
|
|
dedicated enquiry record instead of mutating a lead record in place.
|