From 17d21bffb57902685bb84748db06964f6e65d4c5 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Tue, 2 Jun 2026 01:21:08 -0400 Subject: [PATCH] docs(fusion_maintenance): correct backfill for lifts (no serials) after live sizing Live sizing on Westin: stair lifts ~254 customers / porch-VPL ~30 / lift chairs ~41, but lift serial coverage ~0 (12/416 stairlift lines). The serial-as-unit-key approach (valid for ADP wheelchairs) fails for lifts. Backfill now splits into two regimes: serial dedup for wheelchairs; partner+base-product+sale-line dedup for lifts with accessory-line exclusion via the per-product maintainable flag. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-06-02-fusion-maintenance-design.md | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/superpowers/specs/2026-06-02-fusion-maintenance-design.md b/docs/superpowers/specs/2026-06-02-fusion-maintenance-design.md index 53f5e09a..f9f9da67 100644 --- a/docs/superpowers/specs/2026-06-02-fusion-maintenance-design.md +++ b/docs/superpowers/specs/2026-06-02-fusion-maintenance-design.md @@ -81,8 +81,13 @@ Source: [`fusion_repairs/models/maintenance_contract.py`](../../../fusion_repair - ADP‑side base ≈ **138 serial‑tracked units / ~136 customers** (walkers 68, wheelchairs 45, power bases 7, scooters 4, +14 no‑device‑type). Funders: adp 109, direct_private 13, adp_odsp 10, march_of_dimes 7. Deliveries 2022‑10 → 2026‑05. -- **Lifts are NOT in the ADP data** (private‑pay) — their count must be sized from lift‑category - sale lines at implementation time (see §15). +- **Lifts (sized 2026‑06‑02; name‑based, approximate)** — a LARGE base in Westin's Odoo: stair lifts + ~254 customers (416 lines incl. accessories), porch/VPL ~30 customers (75 lines), lift chairs ~41 + customers (47 lines) — real products (Access BDD, Handicare, Serenity VPL, Pride VivaLift). **But lift + serial coverage is ~0** (12/416 stairlift lines, 0 VPL, 2 lift‑chair). So the serial‑as‑unit‑key + approach that works for ADP wheelchairs **does NOT work for lifts** — lifts must be keyed by + (partner + base‑unit product + sale line), excluding accessory lines (curves, rails, remotes, charging + stations, rentals). This splits the backfill into two regimes (§6.2). - Two backfill data gaps: 14 units have no device_type (need product/manual category); non‑ADP units lack `x_fc_adp_delivery_date` (need an invoice/order‑date fallback anchor). @@ -152,12 +157,14 @@ method; fix + wire it). For each confirmed line whose product/category has ### 6.2 Path B — backfill existing install base (one‑time wizard, idempotent) `fusion.repair.maintenance.backfill.wizard`: -- **Scan** historical `sale.order.line` for products whose category is maintenance‑enabled **and** - that have a serial **and** were delivered. Two sources: - - **Lifts / repairs‑side** equipment — lift categories (`lift_elevating` etc.). - - **Wheelchairs / power chairs** — via the `fusion_claims` serial/`device_type` data (soft dep, - guarded). Map ADP `device_type` → maintenance category. -- **Dedup** strictly by serial (one active contract per unit). +- **Scan** historical `sale.order.line` for products whose category/product is maintenance‑enabled and + were delivered. **Two unit‑identity regimes**, because lifts carry no serials (§3.3): + - **Serial‑tracked** (ADP wheelchairs/power chairs, via the `fusion_claims` serial/`device_type` data + — soft dep, guarded; map ADP `device_type` → maintenance category): require a serial, **dedup by serial**. + - **Non‑serial** (lifts — stair/porch/VPL/lift‑chair): do **NOT** require a serial. One contract per + **base‑unit line**, **dedup by (partner + maintainable product + source sale line)**. The per‑product + `x_fc_maintenance_enabled` flag is what includes base units and **excludes accessory lines** (curves, + rails, remotes, charging stations, rentals) — only the lift itself gets a contract, not its add‑ons. - **Stagger** the first `next_due_date` across a configurable window (e.g. spread overdue units over N weeks) so years of equipment don't all email on day one. - **Dry‑run first**: produce a report (counts by category, # new vs already‑enrolled, # skipped for @@ -249,7 +256,7 @@ old link stays valid across cycles). Old token → friendly "link expired" page. `fusion_tasks` over Enterprise `appointment` — the **entire feature is Community‑testable** on `odoo-modsdev`. `TransactionCase` coverage: - Contract spawn on `sale.order` confirm (enabled vs disabled category; quantity; idempotency). -- Backfill wizard: dedup by serial, stagger, dry‑run produces no records, anchor fallback. +- Backfill wizard: **two‑regime dedup** (serial for wheelchairs; partner+product+line for lifts), accessory‑line exclusion, stagger, dry‑run produces no records, anchor fallback. - Booking: slot list comes from real gaps; confirm creates task+repair+visit; **double‑book guard**; no‑slot fallback. - Roll‑forward on completion: dates advance, band reset, **token regenerated**, visit → done. @@ -274,8 +281,10 @@ old link stays valid across cycles). Old token → friendly "link expired" page. hours source) and whether they already account for travel windows. - The visit‑report wizard's current fields/flow before extending it with the checklist. - The inspection‑certificate issue API (how M1 creates a certificate) for the lift link. -- **Size the lift install base** on Westin (lift‑category sale lines with serials) — not yet counted; - needed to set expectations and the backfill stagger window. +- **Lift base sized** (§3.3): ~254 stairlift + ~30 porch/VPL + ~41 lift‑chair customers, but ~0 serials. + Still to verify: which exact products are **base units vs accessories** (so `x_fc_maintenance_enabled` + lands on base units only), plus the lift interval/fee per category. Lift products aren't yet tagged + with `fusion_repairs` categories on Westin (module not deployed there) — categorization is a deploy step. - `fusion_claims` device_type → maintenance‑category mapping table for the wheelchair backfill. ## 16. Build sequence (for the implementation plan)