236 lines
13 KiB
Markdown
236 lines
13 KiB
Markdown
# 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.*
|