711 lines
6.1 KiB
Markdown
711 lines
6.1 KiB
Markdown
# Task D.4: Won / Lost Lifecycle Governance
|
|
|
|
## Objective
|
|
|
|
Formalize CRM opportunity outcomes by introducing production-grade:
|
|
|
|
* Closed Won lifecycle
|
|
* Closed Lost lifecycle
|
|
* PO tracking
|
|
* Lost reason governance
|
|
* Outcome analytics foundation
|
|
|
|
This task replaces temporary dashboard assumptions and becomes the official business outcome model for CRM.
|
|
|
|
---
|
|
|
|
# Background
|
|
|
|
Business Discovery 3.0 has frozen:
|
|
|
|
## Closed Won
|
|
|
|
Definition:
|
|
|
|
```txt
|
|
PO Received
|
|
```
|
|
|
|
Only a received Purchase Order can move an enquiry to:
|
|
|
|
```txt
|
|
closed_won
|
|
```
|
|
|
|
Quotation approval or quotation acceptance alone does not create a Won outcome.
|
|
|
|
---
|
|
|
|
## Closed Lost
|
|
|
|
Definition:
|
|
|
|
```txt
|
|
Sales opportunity permanently lost
|
|
```
|
|
|
|
Lost requires:
|
|
|
|
```txt
|
|
Lost Reason
|
|
```
|
|
|
|
Optional:
|
|
|
|
```txt
|
|
Lost Competitor
|
|
Lost Remark
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.1 Outcome Schema
|
|
|
|
Extend:
|
|
|
|
```txt
|
|
crm_enquiries
|
|
```
|
|
|
|
Add:
|
|
|
|
```txt
|
|
closedWonAt
|
|
closedLostAt
|
|
|
|
closedByUserId
|
|
|
|
poNumber
|
|
poDate
|
|
poAmount
|
|
poCurrency
|
|
|
|
lostReason
|
|
lostCompetitor
|
|
lostRemark
|
|
```
|
|
|
|
Rules:
|
|
|
|
```txt
|
|
Won
|
|
OR
|
|
Lost
|
|
```
|
|
|
|
never both.
|
|
|
|
---
|
|
|
|
# Scope D4.2 Lost Reason Master Data
|
|
|
|
Add master option category:
|
|
|
|
```txt
|
|
crm_lost_reason
|
|
```
|
|
|
|
Seed:
|
|
|
|
```txt
|
|
competitor_won
|
|
budget_not_approved
|
|
project_cancelled
|
|
customer_no_response
|
|
technical_requirement_mismatch
|
|
price_too_high
|
|
timeline_not_fit
|
|
other
|
|
```
|
|
|
|
Rules:
|
|
|
|
```txt
|
|
Lost Reason
|
|
```
|
|
|
|
required when closing lost.
|
|
|
|
---
|
|
|
|
# Scope D4.3 Outcome Service Layer
|
|
|
|
Create centralized lifecycle service.
|
|
|
|
Supported actions:
|
|
|
|
```txt
|
|
markWon()
|
|
markLost()
|
|
reopenOpportunity()
|
|
```
|
|
|
|
All outcome transitions must go through service layer.
|
|
|
|
No direct status updates.
|
|
|
|
---
|
|
|
|
# Scope D4.4 Mark Won Workflow
|
|
|
|
Action:
|
|
|
|
```txt
|
|
Mark Won
|
|
```
|
|
|
|
Available only when:
|
|
|
|
```txt
|
|
pipelineStage = enquiry
|
|
```
|
|
|
|
Required fields:
|
|
|
|
```txt
|
|
PO Number
|
|
PO Date
|
|
```
|
|
|
|
Optional:
|
|
|
|
```txt
|
|
PO Amount
|
|
PO Currency
|
|
PO Attachment
|
|
Remark
|
|
```
|
|
|
|
System behavior:
|
|
|
|
```txt
|
|
pipelineStage = closed_won
|
|
|
|
closedWonAt = now
|
|
closedByUserId = current user
|
|
```
|
|
|
|
Audit:
|
|
|
|
```txt
|
|
crm_enquiry
|
|
|
|
action = mark_won
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.5 PO Attachment
|
|
|
|
Add attachment support.
|
|
|
|
Allowed:
|
|
|
|
```txt
|
|
PDF
|
|
Image
|
|
Excel
|
|
```
|
|
|
|
Relationship:
|
|
|
|
```txt
|
|
crm_enquiry
|
|
```
|
|
|
|
Attachment category:
|
|
|
|
```txt
|
|
purchase_order
|
|
```
|
|
|
|
UI:
|
|
|
|
```txt
|
|
Upload PO
|
|
View PO
|
|
Download PO
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.6 Mark Lost Workflow
|
|
|
|
Action:
|
|
|
|
```txt
|
|
Mark Lost
|
|
```
|
|
|
|
Available only when:
|
|
|
|
```txt
|
|
pipelineStage = enquiry
|
|
```
|
|
|
|
Required:
|
|
|
|
```txt
|
|
Lost Reason
|
|
```
|
|
|
|
Optional:
|
|
|
|
```txt
|
|
Lost Competitor
|
|
Lost Remark
|
|
```
|
|
|
|
System behavior:
|
|
|
|
```txt
|
|
pipelineStage = closed_lost
|
|
|
|
closedLostAt = now
|
|
closedByUserId = current user
|
|
```
|
|
|
|
Audit:
|
|
|
|
```txt
|
|
crm_enquiry
|
|
|
|
action = mark_lost
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.7 Reopen Opportunity
|
|
|
|
Allow controlled reopen.
|
|
|
|
Available for:
|
|
|
|
```txt
|
|
closed_lost
|
|
```
|
|
|
|
Only.
|
|
|
|
Not allowed for:
|
|
|
|
```txt
|
|
closed_won
|
|
```
|
|
|
|
Reason:
|
|
|
|
```txt
|
|
Won must remain final once PO exists.
|
|
```
|
|
|
|
Required:
|
|
|
|
```txt
|
|
Reopen Reason
|
|
```
|
|
|
|
Audit:
|
|
|
|
```txt
|
|
action = reopen
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.8 UI Changes
|
|
|
|
Enquiry Detail
|
|
|
|
Add:
|
|
|
|
```txt
|
|
Outcome
|
|
```
|
|
|
|
Section.
|
|
|
|
Display:
|
|
|
|
```txt
|
|
Won
|
|
Lost
|
|
Open
|
|
```
|
|
|
|
Fields:
|
|
|
|
```txt
|
|
PO Information
|
|
Lost Information
|
|
Closed By
|
|
Closed Date
|
|
```
|
|
|
|
Actions:
|
|
|
|
```txt
|
|
Mark Won
|
|
Mark Lost
|
|
Reopen
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.9 Dashboard KPI Migration
|
|
|
|
Replace temporary logic.
|
|
|
|
Current:
|
|
|
|
```txt
|
|
quotation accepted
|
|
```
|
|
|
|
Proxy.
|
|
|
|
New:
|
|
|
|
```txt
|
|
pipelineStage = closed_won
|
|
```
|
|
|
|
Official.
|
|
|
|
---
|
|
|
|
Update:
|
|
|
|
## Won Count
|
|
|
|
```txt
|
|
closed_won
|
|
```
|
|
|
|
---
|
|
|
|
## Lost Count
|
|
|
|
```txt
|
|
closed_lost
|
|
```
|
|
|
|
---
|
|
|
|
## Win Rate
|
|
|
|
```txt
|
|
Won / (Won + Lost)
|
|
```
|
|
|
|
---
|
|
|
|
## Lost Analysis
|
|
|
|
```txt
|
|
Lost By Reason
|
|
Lost By Competitor
|
|
Lost By Sales
|
|
Lost By Product Type
|
|
Lost By Branch
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.10 Revenue Rules
|
|
|
|
Freeze:
|
|
|
|
## Won Revenue
|
|
|
|
Priority:
|
|
|
|
```txt
|
|
PO Amount
|
|
```
|
|
|
|
If available.
|
|
|
|
Fallback:
|
|
|
|
```txt
|
|
Quotation Total
|
|
```
|
|
|
|
if PO Amount is empty.
|
|
|
|
---
|
|
|
|
Lost Revenue:
|
|
|
|
```txt
|
|
Quotation Total
|
|
```
|
|
|
|
for reporting opportunity loss.
|
|
|
|
---
|
|
|
|
# Scope D4.11 Report Foundation
|
|
|
|
Prepare data for Task K.
|
|
|
|
Add reusable reporting helpers:
|
|
|
|
```txt
|
|
getWonRevenue()
|
|
getLostRevenue()
|
|
|
|
getLostByReason()
|
|
|
|
getLostByCompetitor()
|
|
|
|
getWinRate()
|
|
```
|
|
|
|
Organization scoped.
|
|
|
|
---
|
|
|
|
# Scope D4.12 Permissions
|
|
|
|
Add:
|
|
|
|
```txt
|
|
crm.enquiry.mark_won
|
|
crm.enquiry.mark_lost
|
|
crm.enquiry.reopen
|
|
```
|
|
|
|
Default:
|
|
|
|
```txt
|
|
sales
|
|
sales_manager
|
|
department_manager
|
|
crm_admin
|
|
```
|
|
|
|
Not granted:
|
|
|
|
```txt
|
|
marketing
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.13 Security
|
|
|
|
Marketing may see:
|
|
|
|
```txt
|
|
Won
|
|
Lost
|
|
Outcome Summary
|
|
```
|
|
|
|
Marketing may not see:
|
|
|
|
```txt
|
|
PO Amount
|
|
Revenue
|
|
Quotation Pricing
|
|
```
|
|
|
|
Enforce server-side.
|
|
|
|
---
|
|
|
|
# Scope D4.14 Audit
|
|
|
|
Entity:
|
|
|
|
```txt
|
|
crm_enquiry
|
|
```
|
|
|
|
Actions:
|
|
|
|
```txt
|
|
mark_won
|
|
mark_lost
|
|
reopen
|
|
upload_po
|
|
```
|
|
|
|
Payload:
|
|
|
|
```txt
|
|
poNumber
|
|
poAmount
|
|
|
|
lostReason
|
|
lostCompetitor
|
|
|
|
closedBy
|
|
closedAt
|
|
```
|
|
|
|
---
|
|
|
|
# Scope D4.15 Verification
|
|
|
|
Scenario 1
|
|
|
|
```txt
|
|
Enquiry
|
|
→ Mark Won
|
|
```
|
|
|
|
Expected:
|
|
|
|
```txt
|
|
closed_won
|
|
PO stored
|
|
audit created
|
|
```
|
|
|
|
---
|
|
|
|
Scenario 2
|
|
|
|
```txt
|
|
Enquiry
|
|
→ Mark Lost
|
|
```
|
|
|
|
Expected:
|
|
|
|
```txt
|
|
closed_lost
|
|
lost reason stored
|
|
audit created
|
|
```
|
|
|
|
---
|
|
|
|
Scenario 3
|
|
|
|
```txt
|
|
Lost
|
|
→ Reopen
|
|
```
|
|
|
|
Expected:
|
|
|
|
```txt
|
|
enquiry
|
|
reopen audit created
|
|
```
|
|
|
|
---
|
|
|
|
Scenario 4
|
|
|
|
```txt
|
|
Won
|
|
→ Reopen
|
|
```
|
|
|
|
Expected:
|
|
|
|
```txt
|
|
blocked
|
|
```
|
|
|
|
---
|
|
|
|
Scenario 5
|
|
|
|
Marketing User
|
|
|
|
Expected:
|
|
|
|
```txt
|
|
see outcome
|
|
cannot see PO amount
|
|
```
|
|
|
|
---
|
|
|
|
# Documentation
|
|
|
|
Create:
|
|
|
|
```txt
|
|
docs/adr/0016-won-lost-lifecycle-governance.md
|
|
docs/implementation/task-d4-won-lost-lifecycle-governance.md
|
|
```
|
|
|
|
Freeze:
|
|
|
|
```txt
|
|
PO = Won
|
|
Lost Reason required
|
|
Won cannot reopen
|
|
Lost can reopen
|
|
Revenue attribution rule
|
|
Win/Loss KPI rule
|
|
```
|
|
|
|
---
|
|
|
|
# Explicit Non-Scope
|
|
|
|
Do NOT implement:
|
|
|
|
```txt
|
|
Sales Order
|
|
Project Handover
|
|
Invoice
|
|
Delivery Note
|
|
ERP Integration
|
|
Forecasting
|
|
Probability Scoring
|
|
```
|
|
|
|
---
|
|
|
|
# Deliverables
|
|
|
|
1. Won Lifecycle
|
|
2. Lost Lifecycle
|
|
3. PO Tracking
|
|
4. Lost Reason Governance
|
|
5. Outcome Analytics Foundation
|
|
6. Dashboard KPI Migration
|
|
7. Security Rules
|
|
8. Audit Coverage
|
|
9. ADR 0016
|
|
|
|
---
|
|
|
|
# Definition of Done
|
|
|
|
Task D.4 is complete when:
|
|
|
|
* PO creates Closed Won
|
|
* Lost requires Lost Reason
|
|
* Won/Lost KPIs use pipelineStage
|
|
* Lost analytics exist
|
|
* Revenue rules are frozen
|
|
* Marketing visibility restrictions are enforced
|
|
* Audit logs exist
|
|
* ADR 0016 exists
|
|
|
|
Result:
|
|
|
|
```txt
|
|
Lead
|
|
→ Enquiry
|
|
→ Quotation
|
|
→ Closed Won (PO)
|
|
|
|
Lead
|
|
→ Enquiry
|
|
→ Quotation
|
|
→ Closed Lost
|
|
```
|
|
|
|
becomes the official CRM business outcome lifecycle.
|