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:
@@ -33,14 +33,14 @@ fusion_ringcentral, fusion_tasks
|
||||
|
||||
`wizard/odsp_submit_to_odsp_wizard.py` calls into `fusion_faxes.send.fax.wizard` (the fax composer) and reads `partner.x_ff_fax_number` — **but `fusion_faxes` is NOT in `__manifest__.py.depends`**. The fax actions are guarded by `hasattr` checks so the wizard still loads if `fusion_faxes` is missing, but the "Send Fax" / "Send Email + Fax" buttons will fail at click-time. If you're moving this module to a new database, install `fusion_faxes` alongside it.
|
||||
|
||||
### ⚠ Reverse-dependency: `fusion_authorizer_portal` always installed alongside
|
||||
### ⚠ Reverse-dependency: `fusion_portal` always installed alongside
|
||||
|
||||
The dependency direction is **`fusion_authorizer_portal` → `fusion_claims`** (hard, declared in fusion_authorizer_portal's manifest), but fusion_claims uses APIs that only exist when fusion_authorizer_portal is installed:
|
||||
The dependency direction is **`fusion_portal` → `fusion_claims`** (hard, declared in fusion_portal's manifest), but fusion_claims uses APIs that only exist when fusion_portal is installed:
|
||||
|
||||
- `sale.order._apply_pod_signature_to_approval_form` imports `PDFTemplateFiller` from `odoo.addons.fusion_authorizer_portal.utils.pdf_filler` — `ImportError` if missing.
|
||||
- `fusion.page11.sign.request` renders PDFs using `fusion.pdf.template` records — that **model lives in fusion_authorizer_portal**, not here.
|
||||
- The `/page11/sign/<token>` URL that the Page 11 wizard generates is handled by `fusion_authorizer_portal.controllers.portal_page11_sign` — without it the public signing flow is dead.
|
||||
- `page11_sign_request._generate_signed_pdf` references `fusion.assessment` records — that model also lives in fusion_authorizer_portal.
|
||||
- `sale.order._apply_pod_signature_to_approval_form` imports `PDFTemplateFiller` from `odoo.addons.fusion_portal.utils.pdf_filler` — `ImportError` if missing.
|
||||
- `fusion.page11.sign.request` renders PDFs using `fusion.pdf.template` records — that **model lives in fusion_portal**, not here.
|
||||
- The `/page11/sign/<token>` URL that the Page 11 wizard generates is handled by `fusion_portal.controllers.portal_page11_sign` — without it the public signing flow is dead.
|
||||
- `page11_sign_request._generate_signed_pdf` references `fusion.assessment` records — that model also lives in fusion_portal.
|
||||
|
||||
In practice both modules are always installed together. See §29 for the full integration map.
|
||||
|
||||
@@ -861,7 +861,7 @@ Mirrors the MOD on_hold pattern. `x_fc_odsp_previous_status_before_hold` saves t
|
||||
| Method | Used when | Mechanism |
|
||||
|---|---|---|
|
||||
| `action_sign_sa_mobility_form` | Client signs the SA Mobility form directly (Page 2 client consent) | **Hard-coded coordinates**: writes printed name at `(180, h-180)` and `(72, h-560)`, date at `(350, h-560)`, signature image at `(72, h-540, 200×50px)`. Uses `reportlab.pdfgen.canvas` + `odoo.tools.pdf.PdfFileReader/Writer`. **Brittle** — if the gov PDF layout changes, the coordinates must be re-measured. |
|
||||
| `_apply_pod_signature_to_approval_form` | POD signature collected (auto-fired by `write` override when `x_fc_pod_signature` is set) | **PDFTemplateFiller** from `fusion_authorizer_portal` — reads field positions from the active `fusion.pdf.template` (category=`odsp`), uses per-case `x_fc_sa_signature_page`. Configurable via drag-and-drop visual editor, not code. Bypass via `skip_pod_signature_hook=True` context. |
|
||||
| `_apply_pod_signature_to_approval_form` | POD signature collected (auto-fired by `write` override when `x_fc_pod_signature` is set) | **PDFTemplateFiller** from `fusion_portal` — reads field positions from the active `fusion.pdf.template` (category=`odsp`), uses per-case `x_fc_sa_signature_page`. Configurable via drag-and-drop visual editor, not code. Bypass via `skip_pod_signature_hook=True` context. |
|
||||
|
||||
The PDFTemplateFiller approach is the preferred path going forward — it survives gov form revisions because positions live in the database, not in Python code.
|
||||
|
||||
@@ -1588,7 +1588,7 @@ All user-facing text is **Canadian English** (per repo CLAUDE.md). All monetary
|
||||
|
||||
74. **`odsp_sa_mobility_wizard._get_template_path()` uses raw `os.path`** instead of Odoo's `tools.misc.file_path`. If the module is ever deployed as a zip (rare in Odoo deployments but possible), this will fail. Migrate to `file_path('fusion_claims/static/src/pdf/sa_mobility_form_template.pdf')` if you ship this for multi-tenant.
|
||||
|
||||
75. **PDF template field positions for ODSP signing live in `fusion.pdf.template` (category=odsp)** — managed via a drag-and-drop editor that lives in `fusion_authorizer_portal`. The OWL editor reads field positions per-page; `_apply_pod_signature_to_approval_form` consumes them. If the gov SA form layout changes, edit the template via the visual editor, not by changing Python coordinates.
|
||||
75. **PDF template field positions for ODSP signing live in `fusion.pdf.template` (category=odsp)** — managed via a drag-and-drop editor that lives in `fusion_portal`. The OWL editor reads field positions per-page; `_apply_pod_signature_to_approval_form` consumes them. If the gov SA form layout changes, edit the template via the visual editor, not by changing Python coordinates.
|
||||
|
||||
76. **SA Mobility wizard limits rows**: 6 parts, 5 labour, 4 fees. The gov PDF only has that many slots. If the SO has more lines, the rest are silently dropped from the form fill (but still appear in the invoice). The wizard truncates via slicing in `default_get`.
|
||||
|
||||
@@ -1862,11 +1862,11 @@ This module is the **lower-level engine**. Two sibling modules layer on top of i
|
||||
|
||||
The whole technician task → sale order coupling lives in `fusion_claims/models/technician_task.py:674` — and the calendar / map / scheduling logic stays in the base `fusion.technician.task` model in fusion_tasks.
|
||||
|
||||
### 29.2 `fusion_authorizer_portal` (portal layer — undeclared but co-installed)
|
||||
### 29.2 `fusion_portal` (portal layer — undeclared but co-installed)
|
||||
|
||||
fusion_authorizer_portal manifest declares `fusion_claims` + `fusion_tasks` + `fusion_loaners_management` as hard deps. fusion_claims uses APIs that only exist when fusion_authorizer_portal is installed — see the dependency note at the top of §2.
|
||||
fusion_portal manifest declares `fusion_claims` + `fusion_tasks` + `fusion_loaners_management` as hard deps. fusion_claims uses APIs that only exist when fusion_portal is installed — see the dependency note at the top of §2.
|
||||
|
||||
| Provided by fusion_authorizer_portal | Used by fusion_claims |
|
||||
| Provided by fusion_portal | Used by fusion_claims |
|
||||
|---|---|
|
||||
| `PDFTemplateFiller` class (`utils/pdf_filler.py`) | `sale.order._apply_pod_signature_to_approval_form` imports it. Same pattern as Odoo Enterprise Sign module — overlays text/checkmarks/signatures via reportlab Canvas + `mergePage()`. |
|
||||
| `fusion.pdf.template` model + `fusion.pdf.template.field` + `fusion.pdf.template.preview` | Drag-and-drop visual editor for placing fields on PDF preview images. Categories: `adp`, `mod`, `odsp`, `hardship`, `other`. fusion_claims searches for `(category='odsp', state='active')` for SA Mobility / OW signature overlays. The Page 11 wizard searches for `name ilike 'adp_page_11'` or `'page 11'`. |
|
||||
@@ -1888,7 +1888,7 @@ fusion_authorizer_portal manifest declares `fusion_claims` + `fusion_tasks` + `f
|
||||
- Renaming a field on `sale.order` likely affects portal templates (`portal_templates.xml`, `portal_assessment_express.xml`, `portal_accessibility_*.xml`) that reference it via QWeb.
|
||||
- Adding a new `x_fc_adp_application_status` value may need a portal-side handler in `portal_main.py` to render the new state.
|
||||
- The `fusion.pdf.template` schema (page-positioned fields) is the ground truth for ODSP signature placement — DON'T hard-code coordinates in fusion_claims when you could create a template field instead.
|
||||
- The `_reactivate_views` post-init hook on fusion_authorizer_portal exists specifically because the inheritance from this module's views is fragile — if you rename a field referenced by an xpath in fusion_authorizer_portal, that view goes dead and stays dead.
|
||||
- The `_reactivate_views` post-init hook on fusion_portal exists specifically because the inheritance from this module's views is fragile — if you rename a field referenced by an xpath in fusion_portal, that view goes dead and stays dead.
|
||||
|
||||
### 29.3 Other co-installed Nexa modules
|
||||
|
||||
@@ -1896,7 +1896,7 @@ fusion_authorizer_portal manifest declares `fusion_claims` + `fusion_tasks` + `f
|
||||
|---|---|---|
|
||||
| `fusion_ringcentral` | RingCentral softphone, click-to-dial widget, fax composer | Click-to-dial works on any phone field — no direct API calls from this module |
|
||||
| `fusion_faxes` | `fusion_faxes.send.fax.wizard` + `partner.x_ff_fax_number` | Hard-soft-dep: `odsp_submit_to_odsp_wizard` calls the fax wizard for ODSP submissions |
|
||||
| `fusion_loaners_management` | Loaner equipment lending | fusion_authorizer_portal depends on this; fusion_claims doesn't touch it directly |
|
||||
| `fusion_loaners_management` | Loaner equipment lending | fusion_portal depends on this; fusion_claims doesn't touch it directly |
|
||||
| `fusion_pdf_preview` | PDF preview client action + report intercept | Project CLAUDE.md says prefer this over `act_url`+`target=new` for attachments. fusion_claims still has legacy attachment buttons using the old pattern — see gotcha #12 |
|
||||
|
||||
## 30. Per-funder workflow state machines
|
||||
@@ -2323,7 +2323,7 @@ Creates a `fusion.technician.location` record on the remote with `source='sync'`
|
||||
- `context['skip_travel_recalc']` — prevents the pull from triggering local recalculations.
|
||||
- Terminal-state tasks (`completed`, `cancelled`) — push side does write, but pull side does NOT update existing shadow records that are already terminal (defensive against late race conditions).
|
||||
|
||||
## 33. `fusion.assessment` (OT assessment model — lives in `fusion_authorizer_portal`)
|
||||
## 33. `fusion.assessment` (OT assessment model — lives in `fusion_portal`)
|
||||
|
||||
The 1,636-line model that captures an OT's assessment of a client + their equipment needs, then generates the draft sale order.
|
||||
|
||||
@@ -2395,7 +2395,7 @@ The model has `signature_page_11` + `signature_page_12` binary fields. `signatur
|
||||
|
||||
`action_complete_express()` skips step 3 (signatures) entirely — used for the "express" assessment route from the sales-rep portal where the rep just needs to spec a wheelchair without doing the full ADP assessment.
|
||||
|
||||
## 34. `fusion.accessibility.assessment` (MOD/accessibility assessment — lives in `fusion_authorizer_portal`)
|
||||
## 34. `fusion.accessibility.assessment` (MOD/accessibility assessment — lives in `fusion_portal`)
|
||||
|
||||
The 966-line sibling for accessibility modifications (not ADP).
|
||||
|
||||
@@ -2466,7 +2466,7 @@ The model has hundreds of measurement fields, only some of which are visible per
|
||||
|
||||
`stairlift_curved`, `vpl`, `ceiling_lift`, `ramp`, `bathroom`, `tub_cutout` each have their own set of fields.
|
||||
|
||||
## 35. `fusion_authorizer_portal` controller routes — detailed
|
||||
## 35. `fusion_portal` controller routes — detailed
|
||||
|
||||
Full per-route inventory from `portal_main.py` (2,827 lines), `portal_assessment.py` (1,238), `portal_page11_sign.py` (206), `pdf_editor.py` (218).
|
||||
|
||||
@@ -2816,7 +2816,7 @@ All filtered to `move_type in ['out_invoice', 'out_refund']` (customer invoices
|
||||
|
||||
ACSD (Assistance to Children with Severe Disabilities) is a CLIENT TYPE, not a sale type. The menu has a dedicated ACSD entry that catches any sale type but with `client_type='ACS'`.
|
||||
|
||||
## 40. `fusion_authorizer_portal.sale_order` extensions (266 lines)
|
||||
## 40. `fusion_portal.sale_order` extensions (266 lines)
|
||||
|
||||
Adds 6 fields to `sale.order` + 5 methods:
|
||||
|
||||
@@ -2843,7 +2843,7 @@ JSON-RPC methods (called from portal JS):
|
||||
`_get_partner_address_display()` — formatted address string.
|
||||
`_get_product_lines_for_portal()` — product lines minus internal-only data.
|
||||
|
||||
## 41. `fusion_authorizer_portal.res_partner` extensions (767 lines)
|
||||
## 41. `fusion_portal.res_partner` extensions (767 lines)
|
||||
|
||||
Adds geolocation + portal access management:
|
||||
|
||||
@@ -3019,7 +3019,7 @@ ssh odoo-westin "docker exec odoo-dev-app odoo -d westin-v19 -u fusion_claims --
|
||||
ssh odoo-mobility "docker exec odoo-mobility-app odoo -d mobility -u fusion_claims --stop-after-init && docker restart odoo-mobility-app"
|
||||
```
|
||||
|
||||
For multiple modules: `-u fusion_claims,fusion_tasks,fusion_authorizer_portal`.
|
||||
For multiple modules: `-u fusion_claims,fusion_tasks,fusion_portal`.
|
||||
|
||||
### 46.3 Database probes
|
||||
|
||||
@@ -3077,7 +3077,7 @@ After 9 rounds of deep diving, here's what CLAUDE.md covers vs the codebase:
|
||||
- Every cron job with cadence + logic
|
||||
- Every constraint method with regex + rule
|
||||
- Every special-character/edge-case behaviour I encountered
|
||||
- Every cross-module integration point with both sibling modules (fusion_tasks, fusion_authorizer_portal)
|
||||
- Every cross-module integration point with both sibling modules (fusion_tasks, fusion_portal)
|
||||
- Every PDF report's conditional sections + business logic
|
||||
- Every ICP setting (~60+)
|
||||
- Every gotcha (~83)
|
||||
@@ -3103,4 +3103,4 @@ After 9 rounds of deep diving, here's what CLAUDE.md covers vs the codebase:
|
||||
- Build new reports following the established color/header/footer conventions
|
||||
- Add new gotchas in the right format
|
||||
- Understand the soft-dep on `fusion_faxes` + `fusion_pdf_preview`
|
||||
- Know the deployment fact that fusion_authorizer_portal is always co-installed
|
||||
- Know the deployment fact that fusion_portal is always co-installed
|
||||
|
||||
@@ -1709,7 +1709,7 @@ class SaleOrder(models.Model):
|
||||
return
|
||||
|
||||
import base64
|
||||
from odoo.addons.fusion_authorizer_portal.utils.pdf_filler import PDFTemplateFiller
|
||||
from odoo.addons.fusion_portal.utils.pdf_filler import PDFTemplateFiller
|
||||
|
||||
tpl = self.env['fusion.pdf.template'].search([
|
||||
('category', '=', 'odsp'), ('state', '=', 'active'),
|
||||
|
||||
Reference in New Issue
Block a user