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

9.6 KiB
Raw Blame History

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: e1e5 (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_001sub_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_002sub_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.jsnew, 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.