1.9 KiB
1.9 KiB
Task D.5.6 Opportunity Lifecycle / Won-Lost Alignment
Summary
- Added explicit opportunity outcome fields in
crm_opportunities:outcomeStatusclosedAtlostDetailcancelReasonnoQuotationReason
- Preserved legacy compatibility fields:
pipelineStageclosedWonAtclosedLostAt
Lifecycle Model
- Working stage continues to use
crm_opportunities.statusfor now. - UI/API now expose
stageas an alias ofstatus. - Final result is tracked with
outcomeStatus.
Closed outcomes
wonlostcancelledno_quotation
Reopen behavior
- Reopen clears final outcome data.
- Reopen returns the opportunity to:
status = quotation_createdoutcomeStatus = openpipelineStage = opportunity
Master Options
- Added/seeded:
crm_opportunity_stagecrm_opportunity_outcome_statuscrm_opportunity_lost_reasoncrm_opportunity_cancel_reasoncrm_opportunity_no_quotation_reason
- Kept legacy compatibility categories:
crm_opportunity_statuscrm_lost_reason
API Routes
POST /api/crm/opportunities/[id]/mark-wonPOST /api/crm/opportunities/[id]/mark-lostPOST /api/crm/opportunities/[id]/mark-cancelledPOST /api/crm/opportunities/[id]/mark-no-quotationPOST /api/crm/opportunities/[id]/reopen
Quotation Alignment
- Quotation creation is blocked when linked opportunity has a closed
outcomeStatus. - Quotation creation keeps outcome as
open. - Opportunity stage sync remains compatibility-first and moves to
quotation_created.
Audit Actions
mark_opportunity_wonmark_opportunity_lostmark_opportunity_cancelledmark_opportunity_no_quotationreopen_opportunity
Encoding Guard
- Verified repository text encoding with
npm run verify:encoding. - Repaired mojibake on CRM dashboard components in the sales ranking, follow-up, and hot-project sections.