12 KiB
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 canonical data (one curated exception: purely-visual long-range trend lines).
Sequencing decision: Data coherence first (Phases 1–6), then the three interactive subsystems (Phases 7–9).
1. Canonical identity (foundation)
Problem (audit): the same people exist under three incompatible ID schemes; 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 (auth + projects already use it):
- Owners
own_001(Justin Johnson),own_002(Diana Reeves); Adminsa1(Adam Admin),a2(Amanda Manager),a3(Arthur Director); Field agentse1–e5; Sales/personnelp1(Jesus Gonzales),p2(Sarah Sales); Contractorcon_001; Subcontractorssub_001–sub_005.
Changes: remap orgMembers[].userId and all subcontractor-task references (assignedBy/actorId/senderId) to canonical ids; reconcile names/emails (Owner #2 = Diana Reeves everywhere; real admin names; consistent Justin email); add a resolvePerson(id) selector returning { id, name, email, role } from a single merged index.
Acceptance: no owner_001/FA0*/ADM0* used as an id; every person reference resolves; own_002 shows one name everywhere.
2. Coherence fixes (four approved tiers)
2a. Feature-breaking data
- Leads List page: seed
leads(currentlyuseState([])) with ~28–35 records in the page's shape; never show the empty state. - Subcontractor access: add login user records for
sub_002–sub_005so each sub's tasks/notifications are reachable. - Task → project: every subcontractor task points to a project whose
addressmatches the tasklocation; addOn HoldtoSTATUS_CONFIG/STATUS_STYLES.
2b. Financial coherence
- proj_008: paid invoices ≤ committedCost (52,000) and ≤ actualCost (44,500).
- proj_005: set
committedCostto the breakdown's real sum 28,850. - Completed projects (proj_002, proj_010): paid invoices ≤ actualCost.
- proj_004: fix contingency line
committed < actual; keep as the over-budget case. - Add coherent
budgetBreakdownto projects missing it (allocated→budget, committed→committedCost, actual→actualCost, committed≥actual per line). - Variance correctness:
variancePercent = (actualCost − budget)/budget × 100, displayed with explicit+(over) /−(under) and correct color everywhere it renders.
2c. Pipeline / Kanban
- Structured numeric
value(estimate) on every kanban lead → enables pipeline $ total + weighted funnel. - Fix Complete-stage leads: real
actualCost,completionPct: 100. - Single
DEMO_TODAYconstant (fixed recent date) used app-wide; dates ordered, not future relative to it. - Populate
stormSourceon storm-canvassed leads; kl_044 (Signed) gets a project record or a pre-signed stage.
3. Ten demo-case projects (threaded end-to-end)
~10 projects, each a distinct real-world case, each threaded across modules with consistent identities/addresses/dates: lead → project → subcontractor task(s) → invoices/payments → commission. Each requires a matching lead (pipeline stage consistent with project status), ≥1 subcontractor task (address-matched), invoices + paymentSchedule reconciling with actualCost, a commission config (+ payout for completed), and consistent team/owner/dates.
Case matrix to cover:
- Storm-driven win, on track (healthy active).
- Insurance-backed up-scope → approved — small self-report → inspection finds major damage → revised estimate → insurance supplement → approved (the hero discrepancy story).
- Up-scope → customer declines (lost) — revised estimate too high; lead lost, reason "declined after inspection".
- Smaller/different than claimed — over-stated; inspection down-scopes to a quick small job.
- Multiple revisions / negotiation — several estimate versions before agreement (richest version history).
- Over-budget / margin loss (proj_004 — scope creep).
- Large commercial, multi-phase (proj_007).
- Near-complete, healthy (proj_008).
- Completed, full lifecycle, all paid (proj_010).
- Disputed / on-hold (proj_011).
(Existing proj_001/003/005/006/009/012 are folded in / reused where they fit a case; net target ≈10 fully-threaded.)
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, plus the new lifecycle/inspection/estimate data (§7–8).
5. Broader pipeline + leaderboard
More leads across stages with $ values + storm attribution; canvasser leaderboard stats derive from the leads each agent sourced.
6. Computed analytics (investor wow)
New src/data/selectors.js (pure functions over store arrays): pipeline value/funnel/win-rate; revenue/gross/net profit/margin (matching OwnerProjectDetail formulas); commission by rep/project; subcontractor performance; storm attribution. Wire into owner/admin dashboards so KPIs tie out with detail screens. Curated exception: long-range visual trend lines (labeled illustrative).
Acceptance: dashboard headline revenue/profit/pipeline == sums of underlying records.
7. Project execution lifecycle (interactive state machine)
A lifecycleStage field per project drives a state machine; the coarse kanban stage (In Progress/Complete) derives from it. Each stage maps to a project progress %:
| Stage | Progress |
|---|---|
| Lead (customer's reported claim) | 5% |
| Damage Inspection Scheduled | 10% |
| Damage Verified (real scope captured) | 20% |
| Scope Approved | 30% |
| Contract Signed | 40% |
| Work In Progress (milestone-driven) | 40–70% |
| Work Complete — Awaiting Inspection | 80% |
| Final Inspection (Scheduled → In Progress) | 85–90% |
| Rework In Progress (issues found; regresses) | re-inspects |
| Project Completed | 95% |
| Final Payment Received — Closed | 100% |
(Stage names: proposed; user is tweaking a few — see Open Items.)
Interactivity: owner/admin advances stages (each transition may carry an optional note + timestamp + actor). Fully interactive; photo/note uploads persist for the session (client-side object URLs), with seeded starting data; placeholder thumbnails acceptable where no real file.
Inspections (two project-level touchpoints, each records who did it):
- Damage Verification (pre-sale): performed by a field agent or sales rep — inspector recorded per project (name + role), with findings + photos.
- Final Inspection (post-work): an external examiner brought by the customer — no login/role; we store
inspectorName,inspectorContact(phone + email, so they can be re-contacted),inspectionDate,result(pass/fail),feedbackNote, andissues[](each{ description, note, photos[], status: open|fixed }). Re-inspection after rework creates a new round; all rounds visible.
Claimed-vs-verified discrepancy model:
- Lead stores
reportedScope(customer's claim: description + rough size/cost/duration guess). - Damage Verification produces
verifiedScope(findings, photos, measurements, severity, recommended work, real cost/duration). - When verified materially differs, project carries a scope-variance flag; visible alert/badge on project detail (e.g., "Reported ~$200 / 1 day → Verified $15,400 / 5 days") + a flag in the pipeline.
- Drives estimate versioning (§8): v1 rough quote from claim → v2 verified → signed = verified.
- Decision branch at Damage Verified → Scope Approved: approved (often insurance-supplement) or declined (lead lost). All four outcomes from §3 (cases 2–5) represented across the 10 projects.
8. Estimate versions (tied to the project)
Each project carries estimateVersions[]: { version, date, total, note, status: sent|revised|signed, lineItems/templateRef }. List shows date/note/total + a Signed badge; clicking a version opens the full rendered estimate document (reusing existing estimate/template rendering). Visible on owner project detail and pipeline lead-project page. v1 reflects the customer claim; later versions reflect verified scope.
9. Subcontractor task stage machine
Status set (replaces flat Assigned/In Progress/…), each transition carries an optional note + timestamp + actor: Not Assigned → Assigned → Pre-Work Inspection → Work In Progress → (On Hold ↔) → Post-Work Review → ↳ Pass → Completed / ↳ Fail → Rework Needed (issue: what's wrong + note + photo) → back to Work In Progress → re-review.
- Inspector attribution: Pre-Work Inspection and Post-Work Review each record who performed them.
- Owner
/owner/subcontractor-taskstable gains columns Task Category and Assigned Date. - Task detail modal: richer progress — stage timeline, current stage + who/when, review results, issues list with photos.
- Same task + stage visible in the subcontractor's own login; sub can advance self-stages / log rework issues.
Coherency map (everything ties to a real project)
- Subcontractor task → real project → visible in sub login + owner project Team/Tasks tab + subcontractor-tasks page.
- Estimate versions → the project's signed estimate is the deal (matches lead's Estimate Sent/Signed pipeline stage).
- Lifecycle/inspection/issues/scope-variance → live on the project; surfaced on owner detail, pipeline lead-project view, and dashboard counts.
Components / files touched
src/data/mockStore.jsx— identity remap, leads seed, financial fixes, breakdowns, 10 threaded scenarios, sub logins, deeper tables, pipeline values, lifecycle/inspection/estimate/scope data, sub-task stage data. (Large file; surgical/additive edits.)src/data/selectors.js— new, computed analytics + aLIFECYCLE_STAGES/progress map.- Dashboards/components:
OwnerSnapshot.jsx,Dashboard.jsx, leaderboard,OwnerProjectDetail.jsx(lifecycle/inspection/estimate UI + scope badge),LeadProjectPage.jsx(same surfaced for pipeline projects),KanbanCard.jsx(date anchor),SubcontractorTasksPage.jsx/TaskViewModal.jsx/SubcontractorTaskDetailPage.jsx(stage machine, On Hold, columns, richer modal).
Out of scope (YAGNI)
- No backend/persistence (mock store only); uploads are session-only.
- No Inspector login/role (external inspector stored as contact data).
- No visual redesign beyond what these features require.
Build sequencing
- Canonical identity +
resolvePerson. - Financial coherence + missing breakdowns + variance signs.
- Feature-breaking fixes (leads seed, sub logins, task↔project).
- Ten threaded scenarios incl. discrepancy cases.
- Pipeline breadth + leaderboard.
selectors.js+ dashboard wiring.- Project lifecycle state machine + progress %.
- Inspections (damage + final) + scope-variance badge + estimate versions.
- Subcontractor task stage machine + UI.
- Verify build + reconciliation spot-checks at each major step.
Verification
npm run buildclean after each major step.- Reconciliation: dashboard revenue == Σ project contract values; pipeline total == Σ lead values; a threaded scenario navigable lead→project→task→invoice→commission with consistent names/dates; a discrepancy project shows reported vs verified + revised estimate versions.
- Dev run: Leads page non-empty; each subcontractor login sees their tasks; no "Unknown" labels; project progress % matches lifecycle stage.
Open items (pending user input)
- Stage-name tweaks: user chose "mostly good, I'll tweak a few" for both the project lifecycle and subcontractor stage names — specific renames TBD before implementation.