59 lines
1.7 KiB
Markdown
59 lines
1.7 KiB
Markdown
# ADR 0016: Won / Lost Lifecycle Governance
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
CRM dashboard and reporting previously treated quotation acceptance and rejection as proxies for opportunity outcomes. That made business outcome data unstable because:
|
|
|
|
- quotation approval/acceptance does not equal PO received
|
|
- lost opportunities could be inferred without a required lost reason
|
|
- reopen rules were undefined
|
|
- revenue and win/loss KPI logic depended on quotation status instead of the enquiry lifecycle
|
|
|
|
Business Discovery 3.0 froze the production rule set:
|
|
|
|
- `closed_won` means PO received
|
|
- `closed_lost` requires a lost reason
|
|
- won cannot reopen
|
|
- lost can reopen with audit
|
|
- won revenue prefers PO amount and falls back to quotation total
|
|
- lost revenue uses quotation total
|
|
|
|
## Decision
|
|
|
|
We use `crm_enquiries` as the official business outcome record.
|
|
|
|
We add outcome fields on `crm_enquiries`:
|
|
|
|
- `closed_won_at`
|
|
- `closed_lost_at`
|
|
- `closed_by_user_id`
|
|
- `po_number`
|
|
- `po_date`
|
|
- `po_amount`
|
|
- `po_currency`
|
|
- `lost_reason`
|
|
- `lost_competitor`
|
|
- `lost_remark`
|
|
|
|
We add `crm_enquiry_attachments` for purchase order files with category `purchase_order`.
|
|
|
|
All lifecycle transitions must go through the enquiry outcome service layer:
|
|
|
|
- `markEnquiryAsWon()`
|
|
- `markEnquiryAsLost()`
|
|
- `reopenLostEnquiry()`
|
|
|
|
Quotation status is no longer allowed to mutate enquiry outcome automatically.
|
|
|
|
## Consequences
|
|
|
|
- dashboard won/lost KPI must read enquiry `pipeline_stage`
|
|
- marketing can see outcome state but PO amount remains server-side restricted
|
|
- PO attachment access follows commercial-data visibility rules
|
|
- audit coverage expands to `mark_won`, `mark_lost`, `reopen`, and `upload_po`
|
|
- downstream reporting can reuse a stable outcome model for Task K
|