refactor(fusion_portal): rename from fusion_authorizer_portal + modern photo cards on accessibility selector
Rename module fusion_authorizer_portal -> fusion_portal everywhere: manifest/assets, controllers, models, views, JS (odoo.define + asset URLs), migration MODULE constants; plus cross-module refs in fusion_schedule, fusion_repairs, fusion_quotations (depends + inherit_id) and the pdf_filler import in fusion_claims. Add rename_module.sql for the one-time in-place DB rename (ir_module_module, ir_model_data, ir_ui_view.key, ir_module_module_dependency) required on installed envs before -u fusion_portal. Document the rename gotcha as rule 16 in CLAUDE.md. Redesign the Accessibility Assessment selector: replace Font Awesome icon tiles with photo-banner cards using 7 optimized images (1000x750 PNG -> 800x600 JPEG, ~8MB -> 488KB), per-type colour accent bar + centered pill button, hover lift/zoom. Images ship as module static files so they deploy/sync with the module. Drop the regenerable graphify-out cache from the module. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -109,7 +109,7 @@ Every feature below has been accepted for inclusion (full scope). Phase assignme
|
||||
| T1 | **Open in Maps button on task** | 2 | `geo:` / Apple Maps URL; one-tap |
|
||||
| T2 | **AI pre-visit brief on mobile form** | 2 | Surfaces `x_fc_ai_summary` prominently; "What to bring" + safety flags |
|
||||
| T3 | Labour timer via fusion_clock | 3 | Tap Start/Pause; final time pre-fills visit report |
|
||||
| T4 | **Client signature on completion** | 2 | OWL signature pad on visit report wizard; attached to repair (pattern from [`fusion_authorizer_portal`](fusion_authorizer_portal)) |
|
||||
| T4 | **Client signature on completion** | 2 | OWL signature pad on visit report wizard; attached to repair (pattern from [`fusion_portal`](fusion_portal)) |
|
||||
| T5 | "Found another issue" button | 2 | Spawn new repair from current visit, same partner, different equipment |
|
||||
| T6 | Parts replaced — serial capture | 3 | Scan/type replaced part serials; stores for OEM warranty + traceability |
|
||||
| T7 | No-show photo proof | 3 | "Client not home" → camera → photo attached → repair flagged + service-call fee added |
|
||||
@@ -164,11 +164,11 @@ Every feature below has been accepted for inclusion (full scope). Phase assignme
|
||||
| CL19 | **Voice input → AI transcription** | 4 | Client speaks the problem into mic, AI transcribes + classifies |
|
||||
| CL20 | **Resolution survey + Google review** | 2 | After "resolved" outcome, ask "save you time today?" + Google review CTA |
|
||||
|
||||
### Sales rep portal (mirrors fusion_authorizer_portal pattern)
|
||||
### Sales rep portal (mirrors fusion_portal pattern)
|
||||
|
||||
| ID | Feature | Phase | Notes |
|
||||
|----|---------|-------|-------|
|
||||
| S1 | **Sales rep web intake form** | 1 | `/my/repair/new` — same question flow as backend wizard, mobile-friendly. Reuses `is_sales_rep_portal` flag on `res.partner` from [`fusion_authorizer_portal/security/portal_security.xml`](fusion_authorizer_portal/security/portal_security.xml) line 11 |
|
||||
| S1 | **Sales rep web intake form** | 1 | `/my/repair/new` — same question flow as backend wizard, mobile-friendly. Reuses `is_sales_rep_portal` flag on `res.partner` from [`fusion_portal/security/portal_security.xml`](fusion_portal/security/portal_security.xml) line 11 |
|
||||
| S2 | Sales rep dashboard tile | 1 | Add "Service Calls" tile to `/my/sales-rep/dashboard` showing count of repairs they logged + recent 5 |
|
||||
| S3 | **My Service Calls** list page | 1 | `/my/repairs` — sales rep sees their submitted repairs, status, assigned tech, scheduled date |
|
||||
| S4 | View repair status from portal | 1 | `/my/repair/<id>` — read-only timeline, chatter for non-internal messages, ability to add a comment |
|
||||
@@ -183,7 +183,7 @@ Every feature below has been accepted for inclusion (full scope). Phase assignme
|
||||
|
||||
**Routing namespace:** `/my/repair/*` (intake + my list) and a `/my/sales-rep/repairs` summary route added to the existing sales rep dashboard.
|
||||
|
||||
**Record rule** (mirrors [`fusion_authorizer_portal/security/portal_security.xml`](fusion_authorizer_portal/security/portal_security.xml) line 129 pattern):
|
||||
**Record rule** (mirrors [`fusion_portal/security/portal_security.xml`](fusion_portal/security/portal_security.xml) line 129 pattern):
|
||||
|
||||
```xml
|
||||
<record id="rule_repair_order_sales_rep_portal" model="ir.rule">
|
||||
@@ -236,7 +236,7 @@ Every feature below has been accepted for inclusion (full scope). Phase assignme
|
||||
'website', # QWeb portal templates
|
||||
'fusion_tasks', # technician tasks + fusion.email.builder.mixin
|
||||
'fusion_poynt', # payment collection
|
||||
'fusion_authorizer_portal', # sales rep portal flag + group + dashboard scaffold
|
||||
'fusion_portal', # sales rep portal flag + group + dashboard scaffold
|
||||
]
|
||||
# Phase 3 soft-add: 'appointment', 'fusion_schedule' for client self-booking
|
||||
# Phase 3 soft-add: 'fusion_clock' for tech labour timer (T3)
|
||||
@@ -245,7 +245,7 @@ Every feature below has been accepted for inclusion (full scope). Phase assignme
|
||||
# Phase 3 soft-add: 'fusion_ringcentral' for SMS verify (CL12) + voicemail greeting (CL16) + caller-ID launch (Phase 4)
|
||||
# Phase 4 soft-add: 'fusion_shipping', 'fusion_canada_post' for mail-in repairs (M4)
|
||||
# Soft-call (no depend) at runtime: 'fusion.api.service' via try/except per fusion-api-integration rule
|
||||
# NOTE: fusion_authorizer_portal transitively pulls fusion_claims — accepted for portal reuse
|
||||
# NOTE: fusion_portal transitively pulls fusion_claims — accepted for portal reuse
|
||||
```
|
||||
|
||||
Before coding any Odoo 19 view/JS, read reference files from local OrbStack Docker per project rules.
|
||||
@@ -712,7 +712,7 @@ Themes adapt via project SCSS rules — no hardcoded colours per CLAUDE.md.
|
||||
|
||||
---
|
||||
|
||||
## Sales rep portal (Phase 1 — mirrors fusion_authorizer_portal)
|
||||
## Sales rep portal (Phase 1 — mirrors fusion_portal)
|
||||
|
||||
**Goal:** A sales rep on the road takes a client call and submits a repair request from their phone — same intake flow as backend CS wizard, no Odoo login screen.
|
||||
|
||||
@@ -720,10 +720,10 @@ Themes adapt via project SCSS rules — no hardcoded colours per CLAUDE.md.
|
||||
|
||||
| Option | Recommendation |
|
||||
|--------|----------------|
|
||||
| **Hard depend on `fusion_authorizer_portal`** | RECOMMENDED — reuses the existing `is_sales_rep_portal` flag, `group_sales_rep_portal`, sales rep dashboard scaffolding. Transitively pulls fusion_claims (already core in your stack). |
|
||||
| **Hard depend on `fusion_portal`** | RECOMMENDED — reuses the existing `is_sales_rep_portal` flag, `group_sales_rep_portal`, sales rep dashboard scaffolding. Transitively pulls fusion_claims (already core in your stack). |
|
||||
| Soft depend (try/except + own fallback flag) | Possible but doubles the code: own `is_sales_rep_portal` mirror + own group. Only worth it if you ever want fusion_repairs standalone. |
|
||||
|
||||
We go with hard depend. Add `fusion_authorizer_portal` to the manifest `depends` list.
|
||||
We go with hard depend. Add `fusion_portal` to the manifest `depends` list.
|
||||
|
||||
### Architecture
|
||||
|
||||
@@ -740,7 +740,7 @@ flowchart LR
|
||||
|
||||
### Controller layout ([`controllers/portal_sales_rep_repair.py`](fusion_repairs/controllers/portal_sales_rep_repair.py))
|
||||
|
||||
Routes scoped to `is_sales_rep_portal` users (gate at controller top, pattern from [`fusion_authorizer_portal/controllers/portal_assessment.py`](fusion_authorizer_portal/controllers/portal_assessment.py) line 25):
|
||||
Routes scoped to `is_sales_rep_portal` users (gate at controller top, pattern from [`fusion_portal/controllers/portal_assessment.py`](fusion_portal/controllers/portal_assessment.py) line 25):
|
||||
|
||||
| Route | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
@@ -767,14 +767,14 @@ Avoids the trap of two intake flows drifting out of sync.
|
||||
|
||||
### Templates ([`views/portal_sales_rep_templates.xml`](fusion_repairs/views/portal_sales_rep_templates.xml))
|
||||
|
||||
QWeb templates following [`fusion_authorizer_portal/views/portal_assessment_express.xml`](fusion_authorizer_portal/views/portal_assessment_express.xml) style:
|
||||
QWeb templates following [`fusion_portal/views/portal_assessment_express.xml`](fusion_portal/views/portal_assessment_express.xml) style:
|
||||
|
||||
- `portal_repair_intake_form` — multi-step (accordion or stepper) with same 5 sections as backend wizard
|
||||
- `portal_repair_list` — card list with status badge, scheduled date, tech name
|
||||
- `portal_repair_detail` — timeline + chatter
|
||||
- `portal_repair_intake_thanks` — confirmation page with "Submit Another" button (common on multi-call days)
|
||||
|
||||
Reuses portal gradient/header style via `portal_gradient` template variable already set by [`portal_main.home()`](fusion_authorizer_portal/controllers/portal_main.py) line 85.
|
||||
Reuses portal gradient/header style via `portal_gradient` template variable already set by [`portal_main.home()`](fusion_portal/controllers/portal_main.py) line 85.
|
||||
|
||||
### JS ([`static/src/js/portal_repair_intake.js`](fusion_repairs/static/src/js/portal_repair_intake.js))
|
||||
|
||||
@@ -860,7 +860,7 @@ Extend repair order form view with Intake tab (answers), Maintenance tab, and st
|
||||
|
||||
**Reused (do NOT recreate):**
|
||||
- [`fusion_tasks.group_field_technician`](fusion_tasks/security/security.xml) — for technician access to `repair.order` (parallel to existing tech task rules). Same domain `('technician_id', '=', user.id)` adapted as `('x_fc_technician_task_ids.technician_id', '=', user.id)` on repair orders
|
||||
- [`fusion_authorizer_portal.group_sales_rep_portal`](fusion_authorizer_portal/security/portal_security.xml) — for sales rep portal access (see Sales rep portal section)
|
||||
- [`fusion_portal.group_sales_rep_portal`](fusion_portal/security/portal_security.xml) — for sales rep portal access (see Sales rep portal section)
|
||||
|
||||
**New groups specific to fusion_repairs:**
|
||||
- `group_fusion_repairs_user` — CS intake, view repairs (implied by `base.group_user`)
|
||||
@@ -896,7 +896,7 @@ Extend repair order form view with Intake tab (answers), Maintenance tab, and st
|
||||
|
||||
**Sales rep portal (S1-S4, S6, S8):**
|
||||
- Portal controllers `/my/repair/new`, `/my/repairs`, `/my/repair/<id>`
|
||||
- Mobile-friendly QWeb templates following [`fusion_authorizer_portal/views/portal_assessment_express.xml`](fusion_authorizer_portal/views/portal_assessment_express.xml) style
|
||||
- Mobile-friendly QWeb templates following [`fusion_portal/views/portal_assessment_express.xml`](fusion_portal/views/portal_assessment_express.xml) style
|
||||
- Same intake question flow as backend (via shared service layer)
|
||||
- Mobile photo / camera capture
|
||||
- Client history sidebar exposed in portal form
|
||||
@@ -1137,7 +1137,7 @@ After implementation, test on local dev only:
|
||||
| Backend wizard and sales rep portal drift apart | Both call the same `fusion.repair.intake.service.create_repair_orders(payload)` AbstractModel method; no duplicate business logic |
|
||||
| Sales rep accidentally sees other reps' repairs | Record rule `('x_fc_intake_user_id', '=', user.id)` scoped to `base.group_portal`; integration test asserts cross-rep isolation |
|
||||
| Portal form abandoned mid-flow on call drop | Save partial state to `localStorage` keyed by partner + timestamp; "Resume" prompt on `/my/repair/new` if recent draft exists |
|
||||
| fusion_authorizer_portal install becomes mandatory | Documented in module description; if a deployment doesn't want fusion_authorizer_portal, fall back to a `fusion_repairs_portal_lite` companion module that recreates only the `is_sales_rep_portal` flag |
|
||||
| fusion_portal install becomes mandatory | Documented in module description; if a deployment doesn't want fusion_portal, fall back to a `fusion_repairs_portal_lite` companion module that recreates only the `is_sales_rep_portal` flag |
|
||||
| **Public form spam / abuse** | reCAPTCHA v3 + honeypot + per-IP rate limit + per-phone rate limit + SMS verify before submit (Phase 2). Block ASN ranges via Odoo's `ir.rule` if needed |
|
||||
| **AI giving unsafe medical advice** | Strict system prompt + JSON schema validation + keyword filter (rejects "diagnose", "you have", "stop using"); falls back to deterministic rules on any malformed/unsafe output; legal disclaimer "this is not medical advice" shown on every AI step |
|
||||
| **AI cost runaway from public traffic** | Hard daily/monthly budget cap via `fusion.api.service`; CAPTCHA gates AI calls; cache results for identical symptom-category pairs; deterministic fallback never costs anything |
|
||||
|
||||
Reference in New Issue
Block a user