TorbatYar/docs/crm-phase-6-2.md
Mortezakoohjani 064d67f099 Ship CRM Core Platform (phases 6.0–6.3) with docs and prod deploy.
Add the Sales CRM service through collaboration, sync architecture/registry docs, expose crm.torbatyar.ir, and include a production deploy script.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 20:32:00 +03:30

215 lines
7.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 6.2 — Enterprise Sales Process Engine
| Field | Value |
| --- | --- |
| Status | Complete |
| Module | crm |
| Version | 0.6.2.0 |
| Database | `crm_db` |
| Migration | `0003_phase_62_sales_engine` |
| Depends On | Phase 6.1 |
## Goal
Implement the Sales CRM **Enterprise Sales Process Engine** only: opportunities, pipelines, stages, playbooks, stage history, opportunity products/contacts/competitors, win/loss analysis, rule-based forecasts, goals, targets, and sales audit.
Out of scope: Workflow Platform, Automation, Customer360, Marketing, Communication, Helpdesk, Analytics, AI, Accounting / Restaurant / Marketplace integrations.
## Sales Architecture
```
API → Opportunity / Pipeline / Playbook / Forecast / Goal / Target / WinLoss / Audit Services
→ Validators (stage, pipeline, opportunity, playbook, forecast, goal, win/loss)
→ Repositories (tenant-scoped)
→ Models (independent aggregates, UUID refs)
→ Events (publish-only EventEnvelope)
```
- Unlimited pipelines per tenant (Retail, Enterprise, Restaurant, Marketplace, Government, Custom).
- Stage transitions validated (active pipeline/stage, stage∈pipeline).
- Closed opportunities immutable; won cannot reopen; lost requires reason.
- Forecasts are rule-based (pipeline / weighted / committed) — no ML.
- Products store `product_ref_id` only (`ProductServiceProvider` contract).
## Opportunity Model
| Field | Notes |
| --- | --- |
| opportunity_number | Unique per tenant |
| title / name | Synced on create/update |
| organization_id, contact_id, lead_id | UUID refs |
| pipeline_id, stage_id | Active + stage belongs to pipeline |
| expected_revenue, amount, currency_code | |
| probability, priority, owner_user_id | |
| expected_close_date, won_at, lost_at | |
| status | open / won / lost |
| Soft delete + actor audit | |
## Pipeline Model
| Field | Notes |
| --- | --- |
| name, code, description | code unique per tenant |
| sort_order, is_default, is_active, status | |
### Pipeline Stages
| Field | Notes |
| --- | --- |
| position, win_probability, color | |
| is_start_stage / is_won_stage / is_lost_stage / is_closed_stage | Only one start, one won, one lost |
| required_fields, exit_validation | JSON |
## Playbook Architecture
- `sales_playbooks` (versioned code+version unique)
- `sales_playbook_steps` (required/recommended/checklist/template)
- `sales_playbook_assignments` (pipeline or opportunity; completion tracking)
- Events: `crm.playbook.assigned`, `crm.playbook.completed`
## Forecast Model
Rule-based over open opportunities in period:
| Metric | Rule |
| --- | --- |
| pipeline_amount | Sum expected_revenue |
| weighted_amount | Sum revenue × probability/100 |
| committed_amount | Sum revenue where probability ≥ 80 |
Periods: monthly / quarterly / annual. Kinds: pipeline / weighted / committed.
## Goal Model
Scopes: individual / team / department. Metrics: revenue / opportunity_count.
## Target Model
Periods: monthly / quarterly / annual. Tracks `actual_value` and `achievement_percent`.
## Win/Loss Model
Immutable snapshot on close (`opportunity_win_loss.is_locked`):
- Categories + reasons (won/lost)
- Root cause, competitor, price/feature/timing/relationship/approval factors, custom reason
## ER Diagram
```mermaid
erDiagram
PIPELINE ||--o{ PIPELINE_STAGE : contains
PIPELINE ||--o{ OPPORTUNITY : routes
PIPELINE_STAGE ||--o{ OPPORTUNITY : current
OPPORTUNITY ||--o{ SALES_STAGE_HISTORY : history
OPPORTUNITY ||--o{ OPPORTUNITY_PRODUCT : lines
OPPORTUNITY ||--o{ OPPORTUNITY_CONTACT : roles
OPPORTUNITY ||--o{ OPPORTUNITY_COMPETITOR : rivals
OPPORTUNITY ||--o| OPPORTUNITY_WIN_LOSS : analysis
SALES_PLAYBOOK ||--o{ SALES_PLAYBOOK_STEP : steps
SALES_PLAYBOOK ||--o{ SALES_PLAYBOOK_ASSIGNMENT : assignments
OPPORTUNITY ||--o{ SALES_PLAYBOOK_ASSIGNMENT : assigned
WIN_LOSS_CATEGORY ||--o{ WIN_LOSS_REASON : categorizes
SALES_GOAL ||--o{ SALES_TARGET : measured
SALES_PROCESS }o--|| PIPELINE : optional
```
## Business Rules
1. Unique opportunity_number per tenant
2. Only active pipeline and active stage allowed
3. Stage must belong to selected pipeline
4. Only one start / won / lost stage per pipeline
5. Closed opportunities immutable
6. Won opportunities cannot reopen
7. Lost opportunities require reason_id or custom_reason
8. Win/Loss immutable after close (`is_locked`)
9. Playbook completion tracked; required steps supported
10. Forecast computed from open opportunities only
11. Everything tenant-aware and auditable (`sales_audit`)
## Validation Rules
| Validator | Covers |
| --- | --- |
| Opportunity | number, amount, currency, probability, mutability |
| Pipeline | active status, code uniqueness |
| Stage | flags mutual exclusion, duplicate start/won/lost |
| Playbook | version uniqueness, assignment target, step membership |
| Forecast | period dates, non-empty name |
| Goal / Target | non-negative values, achievement % |
| WinLoss | lost reason required, locked snapshot |
## Events
| Event | When |
| --- | --- |
| `crm.opportunity.created` | Opportunity created |
| `crm.opportunity.updated` | Opportunity updated |
| `crm.pipeline.changed` | Pipeline updated |
| `crm.stage.changed` | Opportunity stage changed |
| `crm.playbook.assigned` | Playbook assigned |
| `crm.playbook.completed` | Assignment 100% complete |
| `crm.opportunity.won` | Opportunity won |
| `crm.opportunity.lost` | Opportunity lost |
| `crm.forecast.updated` | Forecast computed |
## Permissions
- `crm.opportunities.*`
- `crm.pipelines.*`
- `crm.playbooks.*`
- `crm.forecasts.*`
- `crm.goals.*`
- `crm.targets.*`
## API Endpoints
| Method | Path |
| --- | --- |
| POST/GET/PATCH | `/api/v1/pipelines`, `/pipelines/{id}` |
| POST/GET/PATCH | `/api/v1/pipelines/stages`, `/pipelines/{id}/stages` |
| POST/GET/PATCH | `/api/v1/opportunities`, `/opportunities/{id}` |
| POST | `/api/v1/opportunities/{id}/stage` |
| GET | `/api/v1/opportunities/{id}/stage-history` |
| POST | `/api/v1/opportunities/{id}/win`, `/lose` |
| POST/GET | `/api/v1/sales-processes` |
| POST/GET | `/api/v1/playbooks`, steps, assignments, complete-step |
| POST/GET | `/api/v1/forecasts/compute`, `/forecasts` |
| POST/GET | `/api/v1/goals`, `/targets` |
| POST | `/api/v1/opportunity-products`, `opportunity-contacts`, `opportunity-competitors` |
| POST/GET | `/api/v1/win-loss/categories`, `reasons`, `opportunities/{id}` |
## Migration Summary
- Revision: `0003_phase_62_sales_engine` (down: `0002_phase_61_entities`)
- Creates sales engine tables via metadata `create_all`
- Opportunity / Pipeline / Stage columns expanded in models (greenfield / test recreate)
## Tests Executed
- Model / repository / service / API
- Pipeline & stage rules
- Playbook / forecast / win-loss / business rules
- Migration head `0003`
- Permissions / audit / tenant isolation / documentation
## Known Limitations
- Forecast is rule-based only (no predictive ML)
- Product lines reference Product Service by ID — no inventory sync
- Existing production DBs may need manual column alters if upgraded from pre-6.2 opportunity schema (phase migrations use additive `create_all`)
- Sales team / dashboard metadata deferred to later phase
## Next Phase
Phase 6.3 — Enterprise Sales Collaboration Platform.
## Related Documents
- [Progress](progress.md)
- [Phase 6.0](crm-phase-6-0.md)
- [Phase 6.1](crm-phase-6-1.md)
- [Phase 6.3](crm-phase-6-3.md)
- [Module Registry](module-registry.md#crm)