Files
alla-allaos-fullstack/docs/implementation/task-d3-lead-enquiry-ownership-refinement.md
phaichayon c0cc880be2 lead menu
nquiry menu
2026-06-19 10:39:11 +07:00

4.2 KiB

Task D.3: Lead / Enquiry Ownership Refinement

1. Files Added

  • drizzle/0012_odd_fat_cobra.sql
  • docs/adr/0011-lead-enquiry-ownership-model.md
  • docs/implementation/task-d3-lead-enquiry-ownership-refinement.md

2. Files Modified

  • src/db/schema.ts
  • src/lib/auth/rbac.ts
  • src/features/users/components/user-form-sheet.tsx
  • src/features/crm/enquiries/api/types.ts
  • src/features/crm/enquiries/server/service.ts
  • src/features/crm/quotations/server/service.ts
  • src/app/api/crm/enquiries/route.ts
  • src/app/api/crm/enquiries/[id]/route.ts
  • src/app/api/crm/enquiries/[id]/assign/route.ts
  • src/app/api/crm/enquiries/[id]/reassign/route.ts
  • src/app/api/crm/enquiries/[id]/customers/route.ts
  • src/app/api/crm/enquiries/[id]/followups/route.ts
  • src/app/api/crm/enquiries/[id]/followups/[followupId]/route.ts
  • src/app/api/crm/dashboard/route.ts
  • src/app/api/crm/dashboard/export/route.ts
  • src/app/dashboard/crm/enquiries/page.tsx
  • src/app/dashboard/crm/enquiries/[id]/page.tsx
  • src/config/nav-config.ts
  • src/features/crm/enquiries/components/enquiry-form-sheet.tsx
  • src/features/crm/enquiries/components/enquiry-assignment-dialog.tsx
  • src/features/crm/enquiries/components/enquiry-columns.tsx
  • src/features/crm/enquiries/components/enquiry-detail.tsx
  • src/features/crm/enquiries/components/enquiry-cell-action.tsx
  • src/features/crm/dashboard/api/types.ts
  • src/features/crm/dashboard/server/service.ts
  • src/features/crm/dashboard/components/crm-dashboard.tsx
  • src/features/crm/dashboard/components/dashboard-summary-cards.tsx
  • src/features/crm/dashboard/components/dashboard-funnel.tsx
  • src/features/crm/dashboard/components/dashboard-sales-ranking.tsx
  • src/features/crm/dashboard/components/dashboard-followups.tsx
  • src/features/crm/dashboard/components/dashboard-hot-projects.tsx

3. Pipeline Changes

  • Added crm_enquiries.pipeline_stage
  • Allowed values:
    • lead
    • enquiry
    • closed_won
    • closed_lost
  • Backfilled legacy enquiry rows:
    • assigned rows -> enquiry
    • unassigned rows -> lead
    • closed-lost/cancelled status rows -> closed_lost
  • Assign flow now converts lead -> enquiry
  • Quotation accepted/lost/rejected outcomes can synchronize linked enquiry lifecycle to won/lost stages

4. Ownership Changes

  • Added business role marketing
  • Marketing-created records default to lead
  • Sales-created records default to enquiry
  • sales and sales_support now use server-enforced own-or-assigned enquiry visibility
  • managers, admins, and marketing retain broader monitoring visibility

5. Visibility Rules Added

  • Marketing can read CRM lead/enquiry monitoring surfaces
  • Marketing cannot see quotation pricing or approval analytics
  • Enquiry detail hides related quotation links when the user lacks quotation read access
  • CRM dashboard hides quotation, revenue, hot-enquiry, sales-ranking, and approval sections when the user lacks those permissions

6. KPI Changes

  • Dashboard summary now uses pipelineStage for:
    • lead count
    • enquiry count
    • won count
    • lost count
  • User-facing KPI language changed from Opportunity to Enquiry
  • Funnel wording now follows lead -> enquiry -> quotation flow
  • Follow-up and ownership labels now use Enquiry Owner

7. ADR Added

  • Added docs/adr/0011-lead-enquiry-ownership-model.md
  • This freezes:
    • lead ownership
    • enquiry ownership
    • assignment conversion behavior
    • marketing visibility restriction boundaries
    • won/lost lifecycle naming

8. Migration Notes

  • Apply drizzle/0012_odd_fat_cobra.sql
  • Existing crm_enquiries rows are backfilled in-place; no new lead table is introduced
  • Existing forms and APIs remain shared across lead and enquiry flows
  • Existing quotation routes remain intact; only linked enquiry lifecycle sync was added

9. Remaining Risks

  • closed_won still has no dedicated timestamp field; lifecycle timing remains coarse
  • dashboard/export visibility now follows permission boundaries, but any future custom report endpoints must preserve the same commercial-data guardrails
  • quotation-to-enquiry lifecycle sync currently depends on quotation status transitions and does not yet model reopen scenarios explicitly

Verification

  • npx tsc --noEmit