@@ -0,0 +1,235 @@
# Fusion Repairs — Status & Handoff
**Module: ** `fusion_repairs`
**Version: ** `19.0.2.2.4` (as of 2026-05-27)
**Design spec: ** [`docs/superpowers/specs/2026-05-20-fusion-repairs-design.md` ](../docs/superpowers/specs/2026-05-20-fusion-repairs-design.md )
**Owner context: ** Medical equipment repair intake (beds, wheelchairs, stairlifts, porch lifts, lift chairs, etc.) for Westin Healthcare / Fusion Central.
This file is the **living status tracker ** for what shipped in local dev vs what the original four-phase spec still defers. Update it whenever a bundle lands or production deploys.
---
## Deployment status
| Environment | Status | Notes |
|-------------|--------|--------|
| **Local OrbStack ** (`odoo-modsdev-app` , DB `fusion-dev` or `modsdev` ) | **Installed & upgraded ** | Primary dev target. URL typically `http://localhost:8082` . Upgrade: `docker exec odoo-modsdev-app odoo -d fusion-dev -u fusion_repairs --stop-after-init` |
| **Production (odoo-westin / erp.westinhealthcare.ca) ** | **Not deployed ** | Do not upgrade remotely without explicit sign-off after local E2E. |
| **Automated unit tests ** | **None in repo ** | E2E was done via ad-hoc shell scripts during development; add `tests/` before production. |
After JS/SCSS changes: bump `__manifest__.py` version, upgrade module, flush `/web/assets/%` attachments if the browser serves stale bundles, hard-refresh.
---
## Implementation bundles (shipped in code)
Work was delivered in **11 bundles ** on top of the approved design spec. All of the following exist in the `fusion_repairs/` tree unless marked * partial * .
| Bundle | Theme | Highlights |
|--------|--------|------------|
| **1 ** | CS MVP + permissions | Backend intake wizard, intake templates/questions, `fusion.repair.intake.service` , `repair.order` extensions, RO-`YYYYMM` -`NN` sequence, activities, emails, kanban/menus, admin/office ACLs |
| **2 ** | Portals + weekend safety | Public `/repair` , sales rep `/my/repair/*` , AI self-check + rules fallback, on-call paging + ack route, honeypot + rate limits |
| **3 ** | Reminders + maintenance | Maintenance contracts + booking token portal, day-before / NPS / loaner crons, `x_fc_done_at` , dashboard OWL hub |
| **4 ** | Compliance certs | `fusion.repair.inspection.certificate` , PDF report, expiry cron, visit-report “issue cert” |
| **5 ** | Service catalog + pricing | `fusion.repair.service.catalog` , variance / requote on visit report |
| **6 ** | Rush / emergency | `fusion.repair.emergency.charge` , rush fields on intake + repair, squeeze-into-today scheduling |
| **7 ** | Parts pipeline (basic) | `fusion.repair.part.order` , awaiting-parts emails, visit-report parts-needed path |
| **8 ** | Mobile tech UX | Maps button, signature pad, found-another-issue, timer on task, Poynt collect on repair |
| **9 ** | Repair warranty + plans | `fusion.repair.warranty.coverage` , service plan subscriptions from SO confirm |
| **10 ** | Westin rate card | Callout rates (standard vs lift & elevating), delivery charges, **store labor warranty ** , waive labor (manager/sales rep only), in-shop flag |
| **11 ** | CS flowcharts + vendor PO | Symptom classes, Drawflow designer + OWL runner, demo stairlift chart, draft PO from part order, Wysiwyg node content (`markup()` for HTML) |
---
## Shipped by feature ID (design spec catalogue)
Legend: **Done ** = usable in backend/portal; **Partial ** = model or cron exists but UX/integration incomplete; **Not started ** = no meaningful code.
### CS / call intake
| ID | Feature | Status |
|----|---------|--------|
| C1 | Duplicate-call detection | **Done ** — wizard banners + link to open repair |
| C2 | Client history sidebar in wizard | **Partial ** — `res.partner` prefs + repair count; **no ** lazy sidebar UI (last 3 repairs, maintenance, loaner, ADP) |
| C3 | SMS reply from wizard | **Not started ** — needs `fusion_ringcentral` |
| C4 | Canned scripts per issue | **Not started ** — no `fusion.repair.script.template` |
| C5 | Outstanding-balance warning | **Done ** |
| C6 | Quote-only mode | **Done ** |
### Dispatcher
| ID | Feature | Status |
|----|---------|--------|
| D1 | Map view of open repairs by zone | **Not started ** |
| D2 | Tech skills matrix | **Done ** — `res.users.x_fc_repair_skills` ; dispatch prefers matching category |
| D3 | Parts pre-pull checklist | **Not started ** — no nightly picklist cron/email |
| D4 | Reschedule with client SMS approval | **Not started ** — needs RingCentral two-way SMS |
### Technician (mobile / in-field)
| ID | Feature | Status |
|----|---------|--------|
| T1 | Open in Maps | **Done ** |
| T2 | AI pre-visit brief | **Partial ** — `x_fc_ai_summary` on repair; not a dedicated mobile “brief” panel |
| T3 | Labour timer via fusion_clock | **Partial ** — local Start/Stop timer on `fusion.technician.task` ; **not ** wired to `fusion_clock` |
| T4 | Client signature | **Done ** — visit report wizard |
| T5 | Found another issue | **Done ** |
| T6 | Parts replaced — serial capture | **Done ** — visit report text field |
| T7 | No-show photo proof | **Done ** |
| T8 | Poynt on visit report | **Done ** — `action_collect_payment` on repair |
### Client experience
| ID | Feature | Status |
|----|---------|--------|
| X1 | “Tech is X min away” SMS | **Not started ** |
| X2 | Day-before reminder | **Done ** (email cron); SMS portion **not started ** |
| X3 | Self-reschedule link | **Not started ** — email copy mentions “reply to reschedule” only |
| X4 | Post-visit NPS | **Done ** (email cron) |
| X5 | Logged-in equipment portal `/my/equipment` | **Not started ** |
### Back-office & management
| ID | Feature | Status |
|----|---------|--------|
| M1 | Inspection certificates | **Done ** |
| M2 | ADP/funder bridge to `fusion_claims` | **Not started ** |
| M3 | Loaner auto-offer | **Partial ** — cron + activity + button; **soft ** depends on `fusion_loaners_management` (no hard dep) |
| M4 | Mail-in / shop repairs workflow | **Not started ** |
| M5 | Pre-paid service plans | **Done ** — subscriptions + burn-down on maintenance/visit |
| M6 | Repair warranty (30/90 day re-do) | **Done ** — `fusion.repair.warranty.coverage` + intake check |
| M7 | Failure rate analytics | **Partial ** — dashboard tiles by product/symptom (90-day); not full FCR-by-tech report |
| M8 | OEM warranty claim filing | **Not started ** — serial capture only |
| M9 | Margin per repair | **Partial ** — dashboard margin summary; fields on repair depend on revenue/cost population |
### Client self-service portal
| ID | Feature | Status |
|----|---------|--------|
| CL1 | Public `/repair` landing | **Done ** |
| CL2 | Phone-first lookup | **Done ** — PII-safe jsonrpc |
| CL3 | QR `?sn=` pre-fill | **Done ** |
| CL4 | Guided questions (shared service) | **Partial ** — backend/sales rep use templates; public form is lighter (category + summary) |
| CL5 | Photo upload | **Done ** |
| CL6– CL8 | AI self-check + guardrails + resolved branch | **Done ** |
| CL9 | Upsell engine (rules model) | **Partial ** — deterministic rules + AI; **no ** `fusion.repair.upsell.suggestion` admin UI |
| CL10 | Direct-buy parts/plans | **Not started ** — thanks-page cards only, no shop checkout |
| CL11 | Save & resume tokenized link | **Not started ** |
| CL12 | Smart SMS verify for unknown phones | **Not started ** |
| CL13 | reCAPTCHA v3 | **Partial ** — honeypot + rate limit; **no ** reCAPTCHA |
| CL14 | Privacy / PHI consent | **Done ** — checkbox on form |
| CL15 | After-hours + on-call paging | **Done ** |
| CL16 | Voicemail RC integration | **Not started ** |
| CL17 | QR sticker generator | **Done ** — wizard + PDF report |
| CL18– CL19 | Knowledge base videos / voice input | **Not started ** |
| CL20 | Resolution survey + Google review | **Partial ** — NPS email after visit; not wired to “resolved on self-check” path |
### Sales rep portal
| ID | Feature | Status |
|----|---------|--------|
| S1 | `/my/repair/new` intake | **Done ** |
| S2 | Dashboard tile on sales rep home | **Not started ** — no change in `fusion_authorizer_portal` dashboard |
| S3 | `/my/repairs` list | **Done ** |
| S4 | `/my/repair/<id>` detail | **Done ** (read-only) |
| S5 | Add note from portal | **Not started ** |
| S6 | Mobile photo upload | **Done ** |
| S7 | Book maintenance for client | **Not started ** |
| S8 | Client history sidebar in portal | **Not started ** |
| S9 | Quote-only from portal | **Not started ** |
| S10 | State-change notifications to rep | **Not started ** |
| S11– S12 | Warranty signature / commission view | **Not started ** |
### Bundle 11 — CS troubleshooting flowcharts (post-spec)
| Item | Status |
|------|--------|
| `fusion.repair.symptom.class` + seed data (stairlift-heavy) | **Done ** |
| `fusion.repair.flowchart` + nodes/edges + Drawflow designer | **Done ** |
| OWL runner (card mode + “show whole tree”) | **Done ** |
| Outcomes: resolved / escalate / order_part | **Done ** — transcript → chatter + `internal_notes` |
| Demo chart “Stairlift - Not Moving” | **Done ** (one chart; other categories need admin-built charts) |
| Rich text (Wysiwyg) + HTML source toggle in designer | **Done ** |
| Part order → vendor, OEM #, cost, ETA, factory refs, draft PO | **Done ** |
| Client email on order (ETA only, no cost) | **Done ** |
| Office activity on ETA | **Done ** |
| “Start Troubleshooting” on `repair.order` | **Done ** |
| Troubleshooting **during ** intake wizard (before RO exists) | **Not started ** — run starts after repair created |
| Tech mobile “what CS tried” panel | **Partial ** — via `internal_notes` / chatter, not dedicated task UI |
| Flowcharts for all product categories | **Not started ** — content/ops task |
---
## Key models & entry points
| Model / surface | Purpose |
|-----------------|--------|
| `fusion.repair.intake.service` | Single write path for backend wizard, sales rep portal, client portal |
| `fusion.repair.intake.wizard` | CS “New Service Call” |
| `repair.order` | Core record; Fusion fields prefixed `x_fc_*` |
| `fusion.technician.task` | Dispatch (via `fusion_tasks` ) |
| `fusion.repair.flowchart` (+ run/step) | Guided CS troubleshooting |
| `fusion.repair.part.order` | Parts + draft `purchase.order` |
| `fusion.repair.callout.rate` / `labor.warranty` / `delivery.charge` | Westin pricing |
| OWL `fusion_repairs.dashboard` | App home KPIs |
| Public routes | `/repair` , `/repair/new` , `/repair/self_check` , `/repair/on-call/ack/<token>` |
| Maintenance | `/repairs/maintenance/book/<token>` |
**Dependencies: ** `repair` , `sale_management` , `stock` , `purchase` , `maintenance` , `portal` , `website` , `html_editor` , `fusion_tasks` , `fusion_poynt` , `fusion_authorizer_portal` .
**Soft / optional (not in manifest): ** `fusion_ringcentral` , `fusion_schedule` , `fusion_loaners_management` , `fusion_claims` , `fusion_shipping` , `fusion_canada_post` , `fusion.api.service` (OpenAI).
---
## Crons that exist vs config-only
| Cron | Status |
|------|--------|
| Maintenance due reminders (30/7/1 d) | **Done ** |
| On-call escalate unacknowledged pages | **Done ** |
| Day-before visit reminder (email) | **Done ** |
| Post-visit NPS email | **Done ** |
| Inspection certificate expiry | **Done ** |
| Loaner offer for long repairs | **Done ** |
| Office follow-ups (maintenance unbooked, no tech, overdue visit, unpaid invoice) | **Not started ** — `ir.config_parameter` toggles exist in `data/ir_config_parameter_data.xml` but **no ** `ir.cron` or Python methods |
---
## Known gaps & ops follow-ups
1. **Content: ** Build and publish flowcharts per (equipment category × symptom), not only the seeded stairlift demo.
2. **C2 / S8: ** Add lazy RPC + sidebar UI for last repairs, maintenance status, balance, loaner flag.
3. **RingCentral: ** C3, X1, X2 SMS, D4, CL12, CL16 all blocked on `fusion_ringcentral` .
4. **Tests: ** Add `fusion_repairs/tests/` TransactionCase coverage before production.
5. **Production deploy: ** Copy addon to Westin host, `-u fusion_repairs` , verify rate card numbers against live printed card, train CS on flowchart designer.
6. **Manifest description: ** Still listed “Phase 2– 4 roadmap” in `__manifest__.py` — updated in same commit as this file to reflect shipped scope.
---
## Local dev commands
``` bash
# Upgrade module
docker exec odoo-modsdev-app odoo -d fusion-dev -u fusion_repairs --stop-after-init
# Run tests (when tests/ exists) — ephemeral ports required
docker exec odoo-modsdev-app odoo -d fusion-dev --test-enable --test-tags /fusion_repairs \
-u fusion_repairs --stop-after-init --http-port= 0 --gevent-port= 0 2>& 1 | tail -60
# Force asset rebundle after JS/CSS change (if hash stuck)
docker exec odoo-modsdev-app psql -U odoo -d fusion-dev -c \
"DELETE FROM ir_attachment WHERE url LIKE '/web/assets/%';"
```
---
## Change log (handoff notes)
| Date | Note |
|------|------|
| 2026-05-27 | Created `cloud.md` . Bundles 1– 11 in repo at `19.0.2.2.4` . Local OrbStack verified; production not deployed. Fixed prior session gap: file had been planned but never written. |
| 2026-05-27 | Backend blank page fixes: `fusion_clock` missing table (separate module); flowchart designer OWL hooks inside `setup()` ; Wysiwyg content requires `markup()` . |
---
* When you ship to production or close a spec item, update the tables above and bump the version line at the top. *