From 2e481e13ad0f26340efd55bb25a31721ba76d0a7 Mon Sep 17 00:00:00 2001 From: Satyam Rastogi Date: Fri, 29 May 2026 01:32:55 +0530 Subject: [PATCH] docs: spec for demo data coherence & simulation depth --- .../2026-05-29-demo-data-coherence-design.md | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md diff --git a/docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md b/docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md new file mode 100644 index 0000000..a5d1881 --- /dev/null +++ b/docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md @@ -0,0 +1,124 @@ +# 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 ~28–35 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_034–038): 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. Five–six 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.