docs(master): add data dictionary, concrete scenarios, component map, demo clickstreams, naming conventions, QA appendices
This commit is contained in:
@@ -27,6 +27,12 @@
|
|||||||
18. Open decisions & deferred work
|
18. Open decisions & deferred work
|
||||||
19. Glossary
|
19. Glossary
|
||||||
20. Document index
|
20. Document index
|
||||||
|
- Appendix A — Data dictionary (entity schemas)
|
||||||
|
- Appendix B — The 10 scenarios, concrete data
|
||||||
|
- Appendix C — Component & file map
|
||||||
|
- Appendix D — Demo walkthrough clickstreams (sales + investor)
|
||||||
|
- Appendix E — Naming conventions
|
||||||
|
- Appendix F — Verification & QA detail
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -309,4 +315,158 @@ Role-specific **dashboards/landing stay distinct**: `/owner`, `/admin`, `/agent`
|
|||||||
- **Execution protocol:** `docs/superpowers/plans/2026-05-29-execution-protocol.md`
|
- **Execution protocol:** `docs/superpowers/plans/2026-05-29-execution-protocol.md`
|
||||||
- **Plan 1 — Data Foundation (done):** `docs/superpowers/plans/2026-05-29-demo-data-foundation.md`
|
- **Plan 1 — Data Foundation (done):** `docs/superpowers/plans/2026-05-29-demo-data-foundation.md`
|
||||||
- **Plan 2 — Unify + Routing (written):** `docs/superpowers/plans/2026-05-29-plan2-unify-routing.md`
|
- **Plan 2 — Unify + Routing (written):** `docs/superpowers/plans/2026-05-29-plan2-unify-routing.md`
|
||||||
- **Plans 3–7:** authored from this master doc as each prior plan lands.
|
- **Plans 3–8:** authored from this master doc as each prior plan lands.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix A — Data dictionary (entity schemas)
|
||||||
|
|
||||||
|
Field-level reference for the core entities. "Phase" = where the field is introduced/populated. Types are illustrative (mock data, no DB).
|
||||||
|
|
||||||
|
### A.1 Project (unified job) — `projects[]`, id `PRJ-2026-###`
|
||||||
|
| Field | Type | Notes / Phase |
|
||||||
|
|-------|------|---------------|
|
||||||
|
| `id` | string | `PRJ-2026-###` (Phase 2) |
|
||||||
|
| `sourceLeadId` | string? | `kl_###` if converted from a won lead (Phase 2) |
|
||||||
|
| `ownerId` | string | → owner (own_001/own_002) |
|
||||||
|
| `customer` | object | `{ name, phone, email, address }` |
|
||||||
|
| `address`, `propertyId` | string | site address |
|
||||||
|
| `projectType` | string | Roof Replacement, HVAC, Siding, … |
|
||||||
|
| `status` | enum | active / completed / on_hold / disputed |
|
||||||
|
| `lifecycleStage` | enum | the §9 state machine (Phase 4) |
|
||||||
|
| `phase` | string | Structural / MEP / Finishing / Handover |
|
||||||
|
| `completionPercentage` | number | tied to `lifecycleStage` (Phase 4) |
|
||||||
|
| `healthScore` | number | 0–100 |
|
||||||
|
| `budget` / `approvedBudget` | number | contract value |
|
||||||
|
| `committedCost`, `actualCost`, `spent` | number | `spent == actualCost`; `committed ≥ actual` |
|
||||||
|
| `variancePercent` | number | `round((actualCost−budget)/budget×100,1)` |
|
||||||
|
| `margin` | number | gross margin |
|
||||||
|
| `commissionType` / `commissionRate` / `commission` | — | flat / percent_gross / percent_net / custom |
|
||||||
|
| `budgetBreakdown[]` | array | `{ name, category, allocated, committed, actual }` — Σ each column ties to totals |
|
||||||
|
| `milestones[]` | array | `{ id, name, dueDate, status, assignedTo }` |
|
||||||
|
| `invoices[]` | array | `{ id, amount, submittedBy, status, dueDate, datePaid }` — Σpaid ≤ actualCost |
|
||||||
|
| `paymentSchedule[]` | array | `{ id, milestone, amount, dueDate, status }` |
|
||||||
|
| `changeOrders[]` | array | `{ id, title, amount, status, dateSubmitted, description }` |
|
||||||
|
| `rfis[]` | array | `{ id, subject, status, submittedBy, dateOpened, dateClosed }` |
|
||||||
|
| `riskLog[]` / `issueLog[]` | array | risk & issue tracking |
|
||||||
|
| `activityTimeline[]` | array | `{ date, action, user, details }` |
|
||||||
|
| `documents[]` | array | `{ id, name, uploadedBy, uploadedDate, size, notes }` |
|
||||||
|
| `teamMembers[]` | array | `{ id, userId, name, orgRole, jobRole, status, commissionEnabled, jobCommission }` |
|
||||||
|
| `contractorId`, `subcontractorIds[]` | FK | → con_001 / sub_### |
|
||||||
|
| `estimateVersions[]` | array | Phase 4 — `{ version, date, total, note, status, lineItems/templateRef }` |
|
||||||
|
| `reportedScope` / `verifiedScope` | object | Phase 4 — claimed vs verified |
|
||||||
|
| `scopeVariance` | object? | Phase 4 — `{ reported, verified, flagged }` |
|
||||||
|
| `inspections[]` | array | Phase 4 — see A.5 |
|
||||||
|
| `openRFIs`, `changeOrderCount`, `pendingInvoiceCount` | number | computed counts |
|
||||||
|
|
||||||
|
### A.2 Pre-sale lead — `kanbanLeads[]` (`KANBAN_LEADS_INITIAL`), id `kl_###`
|
||||||
|
`{ id, name, address, phone, email, jobType, insuranceType, value, stormSource?, assignedAgentId, assignedAgentName, columnId, bucketId?, projectId?(if won), notes, createdDate, activity[{from,to,by,date,note}] }`. Stages via `columnId` (kc_new…kc_complete) + buckets (kc_stuck/kc_followup).
|
||||||
|
|
||||||
|
### A.3 Person & Profile — `users`/`personnel`/`owners`/`subcontractors`; profile (Phase 7)
|
||||||
|
- **Person (login/identity):** `{ id, name, email, empId(LUP-####), username, password, role, type, companyName?, tradeType?, phone? }`.
|
||||||
|
- **Profile.self (Phase 7):** `{ preferredName, photo, phone, altContact, address, emergencyContact, nickname?, pronouns?, gender?, sex?, bio, yearsExperience, languages[], specialties[], equipment[], availability, serviceAreas[], (sub:) license, insurance{coi,expiry}, w9Status }`.
|
||||||
|
- **Profile.company (owner-only, Phase 7):** `{ internalNotes, statusTags[], skillScores[{skillId,score|'N/A'}], payTerms, hireDate, managerId }`.
|
||||||
|
- **Achievements (employees, read-only):** from ProCanvas gamification — `{ level, xp, streak, badges[], achievementTiers[] }`.
|
||||||
|
- **Skill catalog (org, Phase 7):** `skillCatalog[] = { id, name, description }`.
|
||||||
|
|
||||||
|
### A.4 Subcontractor task — `MOCK_SUBCONTRACTOR_TASKS[]`, id `sct_###`
|
||||||
|
`{ id, projectId(→PRJ after Phase 2), subcontractorId, assignedBy, assignedByName, title, category(Phase 5 column), location, description, status(§10 machine), priority, dueDate, assignedDate(Phase 5 column), photos[], statusHistory[], thread[{senderId,senderName,...}], activities[], expenses[], fees[], paymentStatus, paidAt?, stageNotes[](Phase 5) }`. Notifications: `MOCK_NOTIFICATIONS[] = { id, recipientUserId, taskId, type, message, read, timestamp }`.
|
||||||
|
|
||||||
|
### A.5 Inspection record (Phase 4) — `project.inspections[]`
|
||||||
|
`{ id, kind: 'damage'|'final', round, inspectorName, inspectorRole?(damage), inspectorContact?{phone,email}(final/external), inspectionDate, result: 'pass'|'fail', feedbackNote, issues[{ id, description, note, photos[], status:'open'|'fixed' }] }`.
|
||||||
|
|
||||||
|
### A.6 Estimate version (Phase 4) — `project.estimateVersions[]`
|
||||||
|
`{ version, date, total, note, status:'sent'|'revised'|'signed', templateId?, lineItems[] }`. Renders via the existing estimate/template view.
|
||||||
|
|
||||||
|
### A.7 Dispatch (LynkDispatch)
|
||||||
|
- **`DISPATCH_REPS[]`** (map to canonical people in Phase 7): `{ id, repId→personId, initials, name, status:'available'|'en_route'|'busy', rating, closeRate, todayAppointments, maxDaily, performanceScore }`.
|
||||||
|
- **`DISPATCH_RECOMMENDATIONS[leadId][]`:** `{ repId, score, factors{proximity,driveTime,calendarFit,weather,skillMatch}, reasons[], stormReasons[], aiInsight, distanceMi, slotStart, slotEnd, conflictFlag }`. Phase 7 authors `skillMatch`/`reasons`/`aiInsight` to cite real profile facts.
|
||||||
|
|
||||||
|
### A.8 Access control — Org Settings
|
||||||
|
- `orgPermissions[moduleKey][roleKey] = [actions]` (role defaults).
|
||||||
|
- `userPermissionOverrides[] = { userId, moduleKey, action, effect:'grant'|'deny' }` (per-person wins over role default).
|
||||||
|
- `PERMISSION_MODULES[moduleKey] = { label, actions[] }` — expanded in Phase 8 to cover every gated route.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix B — The 10 scenarios, concrete data
|
||||||
|
|
||||||
|
Each is a full thread (lead → project → subcontractor task → invoices → commission) with consistent roster identities. Addresses are Plano/DFW. (Existing `proj_001…012` migrate to `PRJ-2026-001…012`; converted won-leads become `PRJ-2026-013…028` — the table below assigns each scenario a representative id; exact figures are authored to satisfy the financial invariants.)
|
||||||
|
|
||||||
|
| # | Scenario | Project | Customer / Address | Type · Value | Owner · Rep · Sub | Lifecycle stage | The beat |
|
||||||
|
|---|----------|---------|--------------------|--------------|-------------------|-----------------|----------|
|
||||||
|
| 1 | Storm-driven win, on track | PRJ-2026-001 | Marcus & Tara Whitfield · 2604 Dunwick Dr | Roof Replacement · $45k | Justin Johnson · Jesus Gonzales · Carlos Mendoza | Work In Progress (42%) | Cody Tatum canvassed after the hail event → signed → Carlos on electrical |
|
||||||
|
| 2 | Insurance-backed up-scope → approved | PRJ-2026-013 | Brenda Ochoa · 3917 Arizona Pl | Roof Replacement · $200→$15.4k | Diana Reeves · Sarah Calloway · Maya Patel | Contract Signed | "Small leak" self-report → inspection finds major hail damage → supplement → approved |
|
||||||
|
| 3 | Up-scope → declined (lost) | (lead, lost) | Greg Lindfors · 6601 Phoenix Pl | Roof · quoted $18k | — · Jesus Gonzales · — | Lead (lost) | Revised estimate too high; lead marked "declined after inspection" |
|
||||||
|
| 4 | Smaller/different than claimed | PRJ-2026-014 | Nadia Okafor · 2516 Dunwick Dr | Gutter Repair · $1.9k | Justin Johnson · Sarah Calloway · — | Completed | Claimed full replacement; inspection down-scopes to a quick repair |
|
||||||
|
| 5 | Multiple revisions / negotiation | PRJ-2026-015 | The Bauer Trust · 7224 Independence Pkwy | Window Replacement · $42k | Diana Reeves · Jesus Gonzales · Greg Alston | Scope Approved | v1→v2→v3 estimate history before agreement |
|
||||||
|
| 6 | Over-budget / margin loss | PRJ-2026-004 | Hollis Property Group · 2612 Dunwick Dr | Interior Reno · $55k (over) | Justin Johnson · Sarah Calloway · Carlos Mendoza | Work In Progress (78%) | Scope-creep change orders push committed > budget; negative margin |
|
||||||
|
| 7 | Large commercial, multi-phase | PRJ-2026-007 | Custer Rd Retail LLC · 6909 Custer Rd | Commercial Roof · $125k | Diana Reeves · Jesus Gonzales · Maya Patel + Carlos | Work In Progress (32%) | Phased payment schedule, multiple subs, big commission |
|
||||||
|
| 8 | Near-complete, healthy | PRJ-2026-008 | Winslow Family · 2112 Winslow Dr | Foundation · $75k | Diana Reeves · Sarah Calloway · Jennifer Castillo | Work Complete — Awaiting Inspection (88%) | Most milestones done; final invoices pending |
|
||||||
|
| 9 | Completed, full lifecycle, paid | PRJ-2026-010 | Legacy Plaza HOA · 2100 Legacy Dr | Parking Lot Resurface · $35k | Diana Reeves · Jesus Gonzales · — | Final Payment Received (100%) | Closed-won; all invoices paid; commission paid out |
|
||||||
|
| 10 | Disputed / on-hold | PRJ-2026-011 | Cedar Ridge Owners · Legacy Town Center | Facade Restoration · $95k | Diana Reeves · Sarah Calloway · Dwayne Boudreaux | On Hold | Dispute timeline, paused payments, health score ~30 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix C — Component & file map
|
||||||
|
|
||||||
|
| File | Responsibility |
|
||||||
|
|------|----------------|
|
||||||
|
| `src/data/mockStore.jsx` | The entire mock data store + mutators + `resolvePerson` + (Phase 3) selectors hook-ins. ~7,000 lines. The hot file — most data tasks touch it (edit sequentially). |
|
||||||
|
| `src/data/selectors.js` *(new, Phase 3)* | Pure functions deriving analytics (pipeline value/funnel, revenue/profit, commission, sub performance, storm attribution) from the store arrays. |
|
||||||
|
| `src/App.jsx` | Route table + `ProtectedRoute`. Phase 8 rewrites this to unified routes + the permission-aware guard. |
|
||||||
|
| `src/pages/owner/OwnerProjectDetail.jsx` | The rich project detail page (10 tabs, commission/profit engine). Becomes the single job page (Phase 2); gains lifecycle/inspection/estimate UI (Phase 4). |
|
||||||
|
| `src/pages/LeadProjectPage.jsx` | Pre-sale lead detail (lighter). Won leads stop using it after Phase 2. |
|
||||||
|
| `src/pages/KanbanPage.jsx` + `src/components/kanban/KanbanCard.jsx`, `LeadInfoDrawer.jsx` | Pipeline board, cards, side drawer. Drawer "More Details" routes won leads → project page (Phase 2). |
|
||||||
|
| `src/pages/owner/OwnerProjectList.jsx` | Lists projects + pipeline leads; links both (relinked Phase 2). |
|
||||||
|
| `src/pages/Maps.jsx` | Territory map; owners can create entries (fixed). |
|
||||||
|
| `src/components/Layout.jsx` | Sidebar/nav; Phase 8 hides items a person can't `view`. |
|
||||||
|
| `src/hooks/usePermissions.js`, `src/components/PermissionGate.jsx`, `src/utils/permissions.js` | RBAC core (`can`, role resolution, component gating). Phase 8 adds the route guard + Access Restricted page. |
|
||||||
|
| `src/pages/owner/OrgSettings.jsx` | Edits roles, permissions, per-user overrides, commission. |
|
||||||
|
| `src/components/dispatch/DispatchRecommendationDrawer.jsx` | LynkDispatch recommendation UI. Phase 7 wires profile-cited rationale. |
|
||||||
|
| `src/pages/ProCanvas.jsx` + `components/ProCanvas/gamification/*` | Gamified canvassing (XP/levels/badges) — source of profile achievements. |
|
||||||
|
| `src/pages/Login.jsx`, `src/context/AuthContext.jsx` | Per-role login picker (done); auth matching by empId/username. |
|
||||||
|
| `src/pages/subcontractor/*`, `src/components/subcontractor/*` | Subcontractor portal + task modals (Phases 5–6). |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix D — Demo walkthrough clickstreams
|
||||||
|
|
||||||
|
**Sales demo (the continuous story):**
|
||||||
|
1. Log in as **Justin Johnson (Owner)** → Owner dashboard: pipeline value, revenue, profit KPIs.
|
||||||
|
2. **Storm Intel** → a recent Plano hail event; **ProCanvas/leaderboard** → Cody Tatum's door-knocks that day.
|
||||||
|
3. **Pipeline** → the storm-sourced lead (Scenario 2); open it → reported scope "small leak ~$200".
|
||||||
|
4. Project detail → **Damage Verified** with inspection photos; **scope-variance badge** ("$200 → $15.4k"); **estimate versions** (v1 claim → v2 verified, signed); insurance supplement.
|
||||||
|
5. **Lifecycle** advances → Work In Progress; **Team** tab shows Carlos Mendoza's subcontractor task; open **Subcontractor Tasks** → his stage timeline.
|
||||||
|
6. **Invoices/Budget** reconcile; **commission** for Sarah Calloway computed. Close as **Scenario 9** (completed, paid).
|
||||||
|
|
||||||
|
**Investor demo (breadth + sophistication):**
|
||||||
|
1. Owner dashboard → computed KPIs; drill a KPI into the exact projects that compose it (coherence proof).
|
||||||
|
2. **LynkDispatch** → assign an incoming lead; the AI cites real profile facts ("Carlos — 92 Emergency Tarp · carries a tarp").
|
||||||
|
3. **Leaderboard** → animated podium; **ProCanvas** → gamification depth.
|
||||||
|
4. **Org Settings** → roles, granular per-person permissions (configure "deny one admin a feature" live); navigate as that admin → **Access Restricted**.
|
||||||
|
5. **Profiles / skill catalog** → the structured context behind the AI.
|
||||||
|
6. Breadth tour: 28 projects across 10 scenario types, storm attribution, subcontractor performance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix E — Naming conventions
|
||||||
|
|
||||||
|
- **Person ids:** owners `own_00#`, admins `a#`, sales reps/personnel `p#`, field agents `e#`, contractor `con_00#`, subcontractors `sub_00#`. Employee id (login + display): `LUP-####` (1xxx employees/owners, 2xxx subs, 3xxx contractor).
|
||||||
|
- **Job ids:** projects `PRJ-2026-###`; pre-sale leads `kl_###`; subcontractor tasks `sct_###`.
|
||||||
|
- **Routes:** kebab-case feature routes, no role prefix (`/territory-map`, `/pipeline`, `/projects/:id`); role landings `/owner`, `/admin`, `/agent`, `/contractor`, `/vendor`, `/subcontractor`.
|
||||||
|
- **Dates:** all relative to `DEMO_TODAY` (2026-05-29); never future-dated.
|
||||||
|
- **Commits:** conventional prefixes (`feat`/`fix`/`chore`/`docs`/`refactor`); **no AI/Claude attribution**; author Satyam Rastogi.
|
||||||
|
- **Files:** pages in `src/pages/**`, shared UI in `src/components/**`, hooks in `src/hooks/**`, pure logic in `src/utils/**`, data/selectors in `src/data/**`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix F — Verification & QA detail
|
||||||
|
|
||||||
|
No unit-test framework exists, so verification is layered:
|
||||||
|
1. **Build gate:** `npm run build` must end `✓ built` with zero errors after every task — this catches import errors, duplicate declarations, and broken references (it caught both a merge duplicate-declaration bug and a Phase-1 copy-paste bug).
|
||||||
|
2. **Grep/invariant checks per task:** e.g. `git grep` for stale ids/names returns none; project financial invariants (Appendix A.1) hold; every FK resolves.
|
||||||
|
3. **Reconciliation review:** for data-heavy tasks, an independent read-only reviewer re-sums breakdowns/invoices and confirms dashboard KPIs equal the underlying records.
|
||||||
|
4. **Cross-login coherence:** the same job viewed as owner vs subcontractor agrees (Phase 6); no "Unknown" person labels.
|
||||||
|
5. **Dev-run spot checks:** Leads page non-empty; each role login lands correctly; denied routes show Access Restricted (Phase 8); lifecycle progress % matches stage (Phase 4).
|
||||||
|
6. **Final whole-implementation review** per plan, then `superpowers:finishing-a-development-branch`.
|
||||||
|
|||||||
Reference in New Issue
Block a user