docs(fusion_maintenance): record Step 0 live-grounding results from Westin prod
Ran Step 0 against Westin prod (westin-v19 on odoo-westin). Resolved the APP/DB placeholders (DO boxes dead; migrated on-prem to odoo-dev-app), added a dated STEP 0 RESULTS section, and corrected the open questions the live inspection disproved: no stair/porch lifts in Westin ADP data; Enterprise appointment already ships native token booking; fusion_repairs contract engine not deployed; device_type is the ADP billing-code catalog taxonomy, not the install base. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -70,7 +70,15 @@ door payment via existing `fusion_poynt`.
|
||||
> from memory — read the real Enterprise `appointment` source before building the booking layer.
|
||||
|
||||
```bash
|
||||
APP=<westin_app_container> ; DB=<westin_db>
|
||||
# RESOLVED 2026-06-02 — Westin Odoo prod migrated OFF Digital Ocean onto the on-prem Proxmox
|
||||
# cluster. Old DO IPs (152.42.146.204 / 178.128.229.92) are DEAD (:22 timeout). Live box:
|
||||
# host `odoo-westin` = 192.168.1.40 via the `supabase-prod` Tailscale jump (Windows OpenSSH
|
||||
# ProxyCommand → run `ssh odoo-westin ...` from PowerShell). App container `odoo-dev-app`
|
||||
# (odoo:19, Enterprise); DB container `odoo-dev-db`; DB `westin-v19`; user `odoo` (local-socket
|
||||
# trust inside odoo-dev-db). Enterprise addons → /mnt/enterprise-addons, custom → /mnt/extra-addons.
|
||||
# SQL: ssh odoo-westin 'docker exec odoo-dev-db psql -U odoo -d westin-v19 -c "..."'
|
||||
# FS read: ssh odoo-westin 'docker exec odoo-dev-app sed -n 1,160p /mnt/enterprise-addons/...'
|
||||
APP=odoo-dev-app ; DB=westin-v19 ; DBC=odoo-dev-db
|
||||
|
||||
# 1) Install matrix — confirm same-DB + Enterprise appointment present + versions
|
||||
docker exec "$APP" psql -U odoo -d "$DB" -c \
|
||||
@@ -95,15 +103,61 @@ docker exec "$APP" psql -U odoo -d "$DB" -c \
|
||||
"SELECT state, count(*) FROM fusion_repair_maintenance_contract GROUP BY state;"
|
||||
```
|
||||
|
||||
## STEP 0 — RESULTS (ran 2026-06-02 against Westin prod `westin-v19`)
|
||||
> Grounding facts only — **no design decisions made**. These correct several assumptions above.
|
||||
|
||||
**Connection (resolved):** host `odoo-westin` (192.168.1.40) via the `supabase-prod` Tailscale jump.
|
||||
App container `odoo-dev-app` (odoo:19, Enterprise), DB container `odoo-dev-db`, DB `westin-v19`,
|
||||
user `odoo`. Old Digital Ocean boxes are DEAD — Westin migrated on-prem.
|
||||
|
||||
**1) Install matrix** — `appointment` **19.0.1.3 installed** (+ `appointment_account_payment`,
|
||||
`_crm`, `_hr`, `_microsoft_calendar`, `_sms`). All deps present: `calendar`, `maintenance`, `repair`,
|
||||
`sale_management`, `portal`, `website`, `resource`, `phone_validation`, `web_gantt`. `fusion_claims`
|
||||
**19.0.9.2.0 installed**. `fusion_repairs` and `fusion_maintenance` are **absent entirely** (no
|
||||
records). → a module depending on `appointment` installs cleanly; "reuse the fusion_repairs engine"
|
||||
means *deploy fusion_repairs to Westin first* (heavy) **or** own a lean contract model here. Note
|
||||
Odoo's native `maintenance` (CMMS) is installed — an under-considered third reuse option.
|
||||
|
||||
**2) device_type** — 119 distinct values, but `fusion.adp.device.code` is the ADP billing-code
|
||||
**CATALOG** (`_order='device_type, device_code'`), so counts are catalog codes per type, **NOT units
|
||||
installed**. Top entries are seating COMPONENTS (Seat Cushion 564, Back Support 375, Headrest 193).
|
||||
The maintainable **equipment classes** ≈ wheelchairs (manual + power tilt), power bases, power
|
||||
scooters, wheeled walkers / walking frames, paediatric standing frames, specialty strollers (~6-8
|
||||
clean categories). → `device_type` can't be a 1:1 policy key (119 values, mostly parts); needs a
|
||||
grouping/whitelist. **Real install base must be sized on `sale.order.line`** (`x_fc_adp_device_type`
|
||||
[computed from product's `x_fc_adp_device_code_id.device_type`], `x_fc_serial_number`,
|
||||
`x_fc_adp_approved`; delivery dates `x_fc_adp_delivery_date` / `x_fc_service_start_date`) — **NOT yet
|
||||
run; this is the next grounding step.**
|
||||
|
||||
**3) + 4) Enterprise appointment source** — `/mnt/enterprise-addons/appointment`. The no-login token
|
||||
slot-picker is **mostly NATIVE — don't hand-roll it**: public booking (`auth="public"`), invite
|
||||
tokens (`appointment.invite`, `/appointment/<id>?…invite_token`), live availability
|
||||
(`/appointment/<id>/update_available_slots`, jsonrpc/public), slot submit → real `calendar.event`
|
||||
(`/appointment/<id>/submit`), auto/manual staff+resource assignment, capacity, booked/cancelled mail
|
||||
templates. Model `appointment.type`; controller `controllers/appointment.py`. → the module mainly
|
||||
needs to: seed an `appointment.type` per category, drop a partner-bound invite link into the reminder
|
||||
email, and hook `calendar.event` create → spawn the service task + advance the contract.
|
||||
`appointment_account_payment` is installed → native pay-to-book is on the table for the revenue mechanic.
|
||||
|
||||
**5) Maintenance-contract state** — `relation "fusion_repair_maintenance_contract" does not exist`
|
||||
→ confirms the fusion_repairs maintenance engine is **not** on Westin.
|
||||
|
||||
**Headline correction:** Westin's ADP data has **zero** stair lifts / porch lifts / ramps / hospital
|
||||
beds — those belong to the fusion_repairs / EN-Tech (mobility) domain. Westin's recurring-revenue
|
||||
play is **wheelchairs / power bases / scooters / walkers / seating**. Open questions updated below.
|
||||
|
||||
## Open questions to resolve with the user (in the connected session)
|
||||
- **MVP cut**: reminders+booking for which device categories first (e.g. stair/porch lifts — the
|
||||
compliance-heavy, highest recurring-revenue ones)?
|
||||
- **MVP cut**: reminders+booking for which device categories first? (Step 0 update: stair/porch lifts
|
||||
do NOT exist in Westin's ADP data. Candidates are the powered units most likely to need recurring
|
||||
service — power wheelchairs, power bases, power scooters — then manual wheelchairs / walkers.)
|
||||
- **Revenue mechanic**: auto-draft a priced SO/invoice per booking, vs. pre-paid annual plan, vs.
|
||||
pay-at-door via Poynt — which is the default?
|
||||
- **Technician assignment**: auto-assign by skill+zone at booking time, or leave dispatch manual
|
||||
(fusion_tasks) and only reserve the calendar slot?
|
||||
- **Booking-portal strategy**: enhance the existing `/repairs/maintenance/book/<token>` in place
|
||||
(fusion_repairs isn't production-deployed yet) vs. add a new `/maintenance/book/<token>` route.
|
||||
- **Booking-portal strategy**: Step 0 shows Enterprise `appointment` already ships public,
|
||||
token-based real-time booking (`appointment.invite` + `/appointment/<id>/...`, `auth="public"`).
|
||||
Ride on that (generate an invite per reminder, partner pre-bound, no login) vs. a custom
|
||||
`/maintenance/book/<token>` route? (The `/repairs/...` route is moot — fusion_repairs isn't on Westin.)
|
||||
|
||||
## Applicable CLAUDE.md rules (don't relearn the hard way)
|
||||
- Rule #1: read reference files from the running instance before coding (esp. the appointment source).
|
||||
|
||||
Reference in New Issue
Block a user