Files
LynkedUpPro_CRM/docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md
T
2026-05-29 01:32:55 +05:30

125 lines
9.6 KiB
Markdown
Raw 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.
# Demo Data Coherence & Simulation Depth — Design Spec
**Date:** 2026-05-29
**Branch:** revamp
**Goal:** Turn the CRM's mock data into one coherent fake roofing company ("LynkedUp Pro Roofing") that works as both a **live sales demo** (believable, no empty/broken views, numbers that feel real) and an **investor pitch** (breadth, depth, analytics wow). Coherence end-to-end is the wow: drilling from any dashboard KPI lands on the exact records that compose it.
**Approach:** A — Canonical-company foundation, then layer up. Analytics are **computed** from the canonical data (with one curated exception: purely-visual long-range trend lines).
---
## 1. Canonical identity (foundation)
**Problem (from audit):** the same people exist under three incompatible ID schemes, so cross-module lookups silently fail; Owner #2 has two names; admins have placeholder names; subcontractor tasks reference non-existent ids (`owner_001`, `ADM01`).
**Decision:** unify on the `MOCK_USERS` scheme (already used by auth and `projects`):
- Owners: `own_001` (Justin Johnson), `own_002` (Diana Reeves)
- Admins: `a1` (Adam Admin), `a2` (Amanda Manager), `a3` (Arthur Director)
- Field agents / canvassers: `e1``e5` (Frank Agent, Fiona Field, Fred Flyer, Felicity Fast, Felix Fixer)
- Sales reps / personnel: `p1` (Jesus Gonzales), `p2` (Sarah Sales)
- Contractor: `con_001` (Mike Contractor); Subcontractors: `sub_001``sub_005`
**Changes:**
- Remap `orgMembers[].userId`: `owner_001→own_001`, `owner_002→own_002`, `FA00N→eN`, `ADM0N→aN`. Keep `orgMembers[].roleKey` as the org-role taxonomy (OWNER/ADMIN/SALES_REP/CANVASSER/SUBCONTRACTOR).
- Reconcile names/emails: `own_002` = **Diana Reeves** everywhere; admins = real names (not "Admin One/Two/Three"); Justin's email consistent (`justin@lynkeduppro.com`).
- Remap subcontractor-task references: `assignedBy`/`actorId`/`senderId` `owner_001→own_001`, `ADM01→a1`; correct the denormalized `*Name` strings to match.
- Add a `resolvePerson(id)` selector in the store (returns `{ id, name, email, role, avatar? }` from a single merged index) so every module resolves people the same way.
**Acceptance:** no reference to `owner_001`/`FA0*`/`ADM0*` as an *id* anywhere; every `userId`/`assignedBy`/`teamMembers[].userId`/`ownerId`/`contractorId`/`subcontractorIds[]` resolves via `resolvePerson`/the relevant collection; `own_002` shows one name across all screens.
---
## 2. Coherence fixes (the four approved tiers)
### 2a. Feature-breaking data
- **Leads List page:** seed the store's `leads` array (currently `useState([])`) with ~2835 records in the page's shape (`firstName/lastName`, `phones[]`, `urgency`, `status`, `leadSource`, `canvasserName`, `createdByName`, `createdAt`, `stormSource`). Source = the existing storm-attribution leads, expanded. Page must never show the empty state on load.
- **Subcontractor access:** add login user records for `sub_002``sub_005` (type `subcontractor`) so each subcontractor's tasks/notifications are reachable. Keep existing task ownership.
- **Task → project association:** every subcontractor task points to a project whose `address` matches the task `location` (residential roofing/electrical tasks → residential projects, not the commercial facade/hotel projects). Fix `STATUS_CONFIG`/`STATUS_STYLES` to include `On Hold`.
### 2b. Financial coherence
- **proj_008:** reduce paid invoices so paid ≤ `committedCost` (52,000) and ≤ `actualCost` (44,500).
- **proj_005:** set `committedCost` to the breakdown's real sum **28,850** (work was committed; stored total was stale); verify variance/margin recompute.
- **Completed projects (proj_002, proj_010):** paid invoices ≤ `actualCost` (no overpay vs spend).
- **proj_004:** fix the contingency line where `committed < actual`; keep it as the deliberate over-budget case.
- **Missing `budgetBreakdown`:** add coherent breakdowns to proj_006, 008, 009, 010, 011, 012 — `allocated` sums to budget, `committed` sums to `committedCost`, `actual` sums to `actualCost`, `committed ≥ actual` per line.
### 2c. Pipeline / Kanban
- Add a structured numeric `value` (estimate) to **every** kanban lead (not just signed+), so a pipeline $ total and weighted funnel can be computed.
- Fix Complete-stage leads (kl_034038): real `actualCost` and `completionPct: 100`.
- Re-anchor the hardcoded "today" (`KanbanCard.jsx:14`) — derive from a single `DEMO_TODAY` constant (= a fixed recent date) used app-wide, or `Date.now()`; dates stay ordered and not-future relative to it.
- Populate `stormSource: true` on storm-canvassed leads so the wired badge shows.
- kl_044 (Signed) gets a project record or moves to a pre-signed stage.
---
## 3. Fivesix fully-threaded scenario projects (real-world spread)
Instead of one hero, **6 projects are threaded end-to-end across modules**, each representing a distinct real-world case. Every thread shares consistent identities, addresses, and dates from lead → project → subcontractor task → invoices/payments → commission.
| # | Project | Scenario it demonstrates | Thread highlights |
|---|---------|--------------------------|-------------------|
| proj_001 | Roof Replacement (active, healthy) | **Storm-driven win, on track** | Storm lead (Frank/e1 canvasses) → Jesus/p1 closes → active project, Carlos/sub_001 electrical task → progress invoices → commission accrues |
| proj_004 | Interior Reno (over budget) | **Problem job / margin loss** | Scope-creep change orders → costs exceed budget → at-risk health → owner sees negative net profit |
| proj_007 | Commercial Roof (large, active) | **Big commercial, multi-phase** | Payment schedule by phase, multiple subs, larger commission |
| proj_008 | Foundation (88%, healthy) | **Near-complete, healthy** | Most milestones done, final invoices pending, payout imminent |
| proj_010 | Parking Lot (completed) | **Closed-won, full lifecycle** | Lead won months ago → completed → all invoices paid → commission paid out |
| proj_011 | Facade/Disputed | **Disputed / on-hold** | Dispute timeline, paused payments, low health score |
Each thread requires: a matching **lead** (pipeline stage consistent with project status; `stormSource` where relevant), at least one **subcontractor task** (address-matched), **invoices + paymentSchedule** that reconcile with `actualCost`, a **commission** config + (for completed) payout, and consistent **team/owner/dates**.
---
## 4. Deeper project detail tables
Every project carries the full coherent set so no tab is empty: `budgetBreakdown`, `changeOrders`, `rfis`, `riskLog`, `issueLog`, `activityTimeline`, `milestones`, `invoices`, `paymentSchedule`, `documents`, `teamMembers`. Thin/empty arrays get realistic content sized to the project's status and scenario.
---
## 5. Broader pipeline + leaderboard
- More leads spread realistically across stages with $ values and storm attribution.
- Canvasser leaderboard stats derive from the leads each agent sourced (knocks → leads → won), so the leaderboard ties to the pipeline.
---
## 6. Computed analytics (investor wow)
Add a `src/data/selectors.js` (pure functions over store arrays) deriving:
- **Pipeline:** total value, weighted value by stage, conversion funnel counts, win rate.
- **Revenue/profit:** total contract value, gross/net profit, margin — summed from projects (matching `OwnerProjectDetail`'s own formulas).
- **Commission:** total accrued/paid by rep, by project.
- **Subcontractor performance:** tasks by sub, on-time %, total paid.
- **Storm attribution:** leads/revenue traced to storm events.
Wire these into the owner/admin dashboards (`OwnerSnapshot`, `Dashboard`, leaderboard) replacing hardcoded figures, so KPIs tie out with detail screens. **Curated exception:** purely-visual long-range trend charts (e.g., 12-month revenue line) where no daily source data exists — these stay hand-authored and are labeled as illustrative.
**Acceptance:** the owner dashboard's headline revenue/profit/pipeline numbers equal the sums of the underlying project/lead records (verified by a quick selector unit check).
---
## Components / files touched
- `src/data/mockStore.jsx` — identity remap, leads seed, financial fixes, breakdowns, threaded scenarios, sub logins, deeper tables, pipeline values. **This file is large (~6,950 lines); changes are additive/surgical, not a rewrite.**
- `src/data/selectors.js`**new**, computed analytics.
- Dashboards/components consuming analytics: `src/pages/owner/OwnerSnapshot.jsx`, `src/pages/Dashboard.jsx`, leaderboard page, `src/components/kanban/KanbanCard.jsx` (date anchor), `SubcontractorTasksPage.jsx`/`TaskViewModal.jsx` (On Hold styling).
## Out of scope (YAGNI)
- No backend/persistence changes (mock store only).
- No new routes/pages beyond what exists.
- No visual redesign of components — data + selectors + minimal wiring only.
- The dormant `project.margin` field stays but is made honest; not wired into new UI.
## Build sequencing
1. Canonical identity + `resolvePerson` (everything depends on it).
2. Financial coherence + missing breakdowns (so projects reconcile).
3. Feature-breaking fixes (leads seed, sub logins, task↔project).
4. Threaded scenarios (lead↔project↔task↔invoice↔commission).
5. Pipeline breadth + leaderboard.
6. `selectors.js` + dashboard wiring.
7. Verify build + spot-check reconciliation.
## Verification
- `npm run build` clean after each major step.
- Reconciliation spot-checks: dashboard revenue == Σ project contract values; pipeline total == Σ lead values; a threaded scenario navigable lead→project→task→invoice→commission with consistent names/dates.
- Dev run: Leads page non-empty; each subcontractor login sees their tasks; no "Unknown"/empty owner labels.