Files
LynkedUpPro_CRM/docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md

205 lines
17 KiB
Markdown
Raw Permalink 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 canonical data (one curated exception: purely-visual long-range trend lines).
**Sequencing decision:** Data coherence first (Phases 16), then the three interactive subsystems (Phases 79).
---
## 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` id scheme (auth + `projects` already use it), with **realistic Texan names**, a **unified `LUP-####` employee-ID scheme**, and a shared demo password (`password`). Canonical roster (single source of truth):
| id | Role | Name | empId | Login type | Login id | Password |
|----|------|------|-------|-----------|----------|----------|
| own_001 | OWNER | Justin Johnson | LUP-1001 | owner | justin | password |
| own_002 | OWNER | Diana Reeves | LUP-1002 | owner | diana | password |
| a1 | ADMIN | Wade Hollis | LUP-1010 | employee | LUP-1010 | password |
| a2 | ADMIN | Darlene Brooks | LUP-1011 | employee | LUP-1011 | password |
| a3 | ADMIN | Roy Schaefer | LUP-1012 | employee | LUP-1012 | password |
| p1 | SALES_REP | Jesus Gonzales | LUP-1030 | employee | LUP-1030 | password |
| p2 | SALES_REP | Sarah Calloway | LUP-1031 | employee | LUP-1031 | password |
| e1 | FIELD_AGENT | Cody Tatum | LUP-1040 | employee | LUP-1040 | password |
| e2 | FIELD_AGENT | Hannah Reyes | LUP-1041 | employee | LUP-1041 | password |
| e3 | FIELD_AGENT | Travis Boone | LUP-1042 | employee | LUP-1042 | password |
| e4 | FIELD_AGENT | Shelby Greer | LUP-1043 | employee | LUP-1043 | password |
| e5 | FIELD_AGENT | Dalton Pruitt | LUP-1044 | employee | LUP-1044 | password |
| con_001 | CONTRACTOR | Mike Brennan | LUP-3001 | contractor | mike | password |
| sub_001 | SUBCONTRACTOR | Carlos Mendoza | LUP-2001 | subcontractor | carlos | password |
| sub_002 | SUBCONTRACTOR | Maya Patel | LUP-2002 | subcontractor | maya | password |
| sub_003 | SUBCONTRACTOR | Dwayne Boudreaux | LUP-2003 | subcontractor | dwayne | password |
| sub_004 | SUBCONTRACTOR | Jennifer Castillo | LUP-2004 | subcontractor | jennifer | password |
| sub_005 | SUBCONTRACTOR | Greg Alston | LUP-2005 | subcontractor | greg | password |
Names are **denormalized** across the store (teamMembers, tasks, kanban activity, DISPATCH_REPS) and some components, so the rename is a **repo-wide string replace** of each old name → new (old names are distinctive), plus setting names/empIds on the source people records. `resolvePerson(id)` is the go-forward single source.
**Login page:** the "Quick Demo Access" row becomes a **per-role person picker** — clicking a role (Admin/Agent/Sub-Con) expands the list of people in that role; clicking a person auto-fills the correct login id + password (and can sign in). Single-person roles (Owner) stay one-click.
**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` (currently `useState([])`) with ~2835 records in the page's shape; never show the empty state.
- **Subcontractor access:** add login user records for `sub_002``sub_005` so each sub's tasks/notifications are reachable.
- **Task → project:** every subcontractor task points to a project whose `address` matches the task `location`; add `On Hold` to `STATUS_CONFIG`/`STATUS_STYLES`.
### 2b. Financial coherence
- proj_008: paid invoices ≤ committedCost (52,000) and ≤ actualCost (44,500).
- proj_005: set `committedCost` to 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 `budgetBreakdown` to 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_TODAY` constant (fixed recent date) used app-wide; dates ordered, not future relative to it.
- Populate `stormSource` on 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:
1. **Storm-driven win, on track** (healthy active).
2. **Insurance-backed up-scope → approved** — small self-report → inspection finds major damage → revised estimate → insurance supplement → approved (the hero discrepancy story).
3. **Up-scope → customer declines (lost)** — revised estimate too high; lead lost, reason "declined after inspection".
4. **Smaller/different than claimed** — over-stated; inspection down-scopes to a quick small job.
5. **Multiple revisions / negotiation** — several estimate versions before agreement (richest version history).
6. **Over-budget / margin loss** (proj_004 — scope creep).
7. **Large commercial, multi-phase** (proj_007).
8. **Near-complete, healthy** (proj_008).
9. **Completed, full lifecycle, all paid** (proj_010).
10. **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 (§78).
## 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)* | 4070% |
| Work Complete — Awaiting Inspection | 80% |
| Final Inspection (Scheduled → In Progress) | 8590% |
| 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`, and `issues[]` (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 25) 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-tasks` table 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.
## 10. Profiles, skill catalog & AI dispatch context
Every person (employee **and** subcontractor) gets a two-layer `profile`, surfaced through a self-service **User Details** page (all roles, including owners) and an owner-facing **Employee/Subcontractor Details** view.
**① Self section** (person edits; owner can view): preferred name, photo, phone, alt contact, address, emergency contact; **optional identity fields — nickname, pronouns, gender, sex (all optional)**; short bio, years of experience/since-date, languages; self-declared specialties + **equipment carried** (e.g., tarp, ladder rack, drone); availability/service areas. Subcontractors also: company name, license #, insurance/COI + expiry, W-9 status.
**② Company section** (owner/admin edits; **private to owner/admin — not shown to the person**): company bio / internal notes ("reliable in storms, keeps a tarp on the truck"); internal status/tags (preferred / probation / do-not-use); **skill scores** (see below); pay/commission terms; hire date; manager.
**③ Achievements & levels** (employees): read-only, pulled from ProCanvas gamification (level, XP, streak, badges, achievement tiers).
**Skill catalog (shared, org-level):** `skillCatalog[]` = `{ id, name, description }` defined by the owner. Each person carries `skillScores[]` = `{ skillId, score: 0100 | 'N/A' }`. Comparable across people; new skills added org-wide.
**AI dispatch context (coherence with LynkDispatch):** `DISPATCH_REPS` map to canonical people; each rep's profile (equipment + skill scores + notes) is the structured context the dispatch engine references. The pre-authored `DISPATCH_RECOMMENDATIONS` (`factors.skillMatch`, `reasons[]`, `aiInsight`) are written to **cite real profile facts** (e.g., *"Carlos — 92 Emergency Tarp · carries tarp on truck"*), so "the AI read their profile" is demonstrably true on screen.
**Pages/access:**
- **User Details / My Profile** (`/me/profile` or similar) — every logged-in role edits their self-section + sees their achievements.
- **Owner Employee/Subcontractor Details** — extends People/Vendor directories with a person detail view showing the full profile incl. company section + skill scores; owner edits company notes/scores and manages the skill catalog.
---
## 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.
- Profiles/skills/equipment → attached to canonical people; surfaced on User Details + owner Employee Details; cited by LynkDispatch recommendations; subcontractor profile visible in their own login.
## 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 + a `LIFECYCLE_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
1. Canonical identity + `resolvePerson`.
2. Financial coherence + missing breakdowns + variance signs.
3. Feature-breaking fixes (leads seed, sub logins, task↔project).
4. Ten threaded scenarios incl. discrepancy cases.
5. Pipeline breadth + leaderboard.
6. `selectors.js` + dashboard wiring.
7. Project lifecycle state machine + progress %.
8. Inspections (damage + final) + scope-variance badge + estimate versions.
9. Subcontractor task stage machine + UI.
10. Profiles + skill catalog + User Details page + owner Employee Details + dispatch AI-context wiring.
11. Verify build + reconciliation spot-checks at each major step.
## Verification
- `npm run build` clean 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.