Status:
accepted

Context:
Task D.2 introduced separate `Billing Customer` and `Project Parties` data entry in CRM enquiries and quotations.
Task J.0 froze KPI definitions and confirmed that dashboard/reporting behavior must not drift without an explicit governance decision.
Task D.2.1 freezes how revenue attribution and relationship reporting work across dashboard, report center, exports, and future analytics features.

Decision:

- Freeze `Revenue Owner = End Customer`.
- Determine `Revenue Owner` from project-party role code `end_customer`.
- If a record has no `end_customer`, fallback to `billing_customer` for revenue-owner attribution only.
- Freeze `Billing Revenue` as quotation revenue grouped by project-party role `billing_customer`.
- Freeze `Contractor Revenue` as quotation revenue grouped by project-party role `contractor`.
- Freeze `Consultant Revenue` as quotation revenue grouped by project-party role `consultant`.
- Use project-party relationships as the reporting authority, not bare `crm_customers` references alone.
- Prefer quotation project parties for reporting. If quotation project parties are absent, fallback to enquiry project parties for the linked enquiry.
- When multiple parties share the same reporting role on one quotation, each party receives full quotation attribution.
- Do not prorate relationship analytics across multiple parties because this model is for CRM relationship reporting, not accounting allocation.
- Exclude cancelled quotations from revenue attribution by default unless an explicit reporting filter intentionally includes them.

Consequences:

- Dashboard KPI, report center, exports, and ad hoc analytics can share one attribution rule set.
- `Top End Customers`, `Top Contractors`, `Top Consultants`, and `Top Billing Customers` can be built from the same reusable service layer.
- A single quotation may contribute full value to more than one customer in relationship analytics when multiple parties share a role.
- Revenue attribution and accounting allocation remain intentionally separate concerns.
- Legacy or incomplete quotations without project-party rows may not attribute revenue until project-party data is synchronized or backfilled.

Future:

- add a unified reporting view or materialized projection if revenue analytics queries become heavy
- add explicit lifecycle timestamps for won/lost stage reporting precision
- decide whether approved snapshots should become the long-term reporting source for historically locked documents
- add backfill tooling if legacy quotations are found without authoritative project-party rows
