The Checklist group used col=\"4\" which stretched each label+field
pair across a quarter of the sheet, producing a big empty gap
between the two columns. Replaced with the idiomatic Odoo two-
nested-group pattern so each column hugs its labels, removing the
dead space. Same fix applied to Section 3.0 and to the Outcome
blocks on both sections.
fusion_plating_quality → 19.0.2.3.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a "Contract Review" stat button to fp.part.catalog's button box.
Shows a coloured state badge (green=complete, blue=manager_review,
yellow=assistant_review, muted=dismissed, em-dash when none). Click
routes through action_start_contract_review so it opens the existing
review or lazy-creates one — same behaviour as the banner / tab.
fusion_plating_quality → 19.0.2.2.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New bulk-toggle actions on fp.contract.review flip all 10 checklist
items in Section 2.0 (and all 11 in Section 3.0) in one click.
Rendered as "Check All" / "Clear All" buttons above each checklist.
User can still tick boxes individually. Buttons hide once the
section is signed (locked).
- Fix QA-005 PDF: replaced `to_text(...)` (not in QWeb context) with
`image_data_uri(...)` for the company logo embed. PDF now renders
with the full colour ENTECH logo (render size 103 KB).
- Smoke test extended: 5 new assertions covering bulk-toggle on/off
and locked-section guard. 17/17 pass on entech.
fusion_plating_quality → 19.0.2.1.0
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per-part contract review record (fp.contract.review) gated by a
customer-level toggle, signed in two sections (QA Assistant → QA
Manager), settings-based signer rosters (no new res.groups), banner on
the part form that auto-dismisses once the first MO for the part hits
confirmed. QA-005 Rev. 0 paper form reproduced 1:1 in a QWeb PDF.
Never blocks MO/SO/WO — review is purely an audit artefact.
Smoke test run on entech: 12 assertions pass including the 25-cell
risk matrix parity with the paper form and 22 KB PDF render.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
**1. Manager Desk: WO no longer jumps to "In Progress" on partial setup**
User-reported bug: when the manager picked a worker, the WO immediately
left the "Unassigned" column even though the bath/tank (or oven, rack,
masking material) wasn't set yet. Worker would see a half-set job in
their queue and couldn't start it.
Fix:
- New compute `mrp.workorder.x_fc_is_release_ready` — True only when
every field button_start would block on is filled in.
- Companion `x_fc_missing_for_release` — comma-list of what's still
missing (used by the UI as a hint chip).
- Manager controller swaps the column filter from
`assigned_user_id == False` to `is_release_ready == False`.
- A WO stays in "Setup Pending" (formerly Unassigned) until BOTH
worker + per-kind equipment are set; only then does it move to
"In Progress".
**Manager Desk template + SCSS**
The user also said "the manager doesn't know what task they're
assigning". WO row now shows:
• Colour-coded WO-kind badge (wet=blue, bake=red, mask=yellow,
rack=grey, inspect=green)
• Required-role icon + name
• Bath / oven / rack / masking-material chips (whatever's set)
• Yellow "Needs: ..." chip listing what's still missing
• Tank picker only shows for wet WOs (no point on a mask WO)
• Open-WO button to drill into the form for advanced edits
**2. Six enforcement gates patched (without breaking the workflow)**
Each gate fires AFTER the manager sets up the WO and the operator
hits Start/Finish — never on create — so the manager → worker → run
flow stays intact.
| # | Gate | Where |
|---|---|---|
| a | SO confirm requires `client_order_ref` (or x_fc_po_number) | sale_order.action_confirm |
| b | Cert issue requires thickness readings (when partner.x_fc_strict_thickness_required) | fp_certificate.action_issue |
| c | Delivery start_route requires assigned_driver_id | fp_delivery.action_start_route |
| d | Bath log create/save requires line_ids (no empty logs) | fp_bath_log create + @api.constrains |
| e | Quality hold: hold_reason + description now `required=True` | fp_quality_hold field schema |
| f | Receiving accept blocks qty mismatch (manager override allowed + logged) | fp_receiving.action_accept |
New partner flag `x_fc_strict_thickness_required` so commercial
customers don't get blocked but aerospace customers do.
**Verified** via `scripts/fp_enforcement_audit.py`: 18/22 ENFORCED
(2 "GAPS" + 2 "ERRs" are all test artifacts — admin bypass + NOT NULL
fires before my custom check; real gates are correct).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
**7a. NCR close gate** (fusion.plating.ncr.action_close)
Block close unless these are filled in:
• Description (what happened)
• Containment Actions (immediate response)
• Root Cause (why it happened)
• Disposition (use-as-is / rework / scrap / RTV decision)
A closed NCR without these is useless for AS9100 audits — it's
the entire point of an NCR to document what went wrong, why, and
how we responded. Empty-HTML strings like "<p><br></p>" are
detected as empty too.
**7b. CAPA close gate** (fusion.plating.capa.action_close)
Block close unless:
• Root Cause Analysis filled in
• Action Plan filled in
• Verification (date + verifier) recorded
• Effectiveness Notes filled when CAPA was marked Not Effective
AS9100 §10.2 / Nadcap require evidence of root-cause analysis,
the corrective/preventive action plan, AND that effectiveness
was verified before the loop is closed.
**8. Invoice ref defensive default** (account.move.create)
Auto-fills `ref` from the source SO's client_order_ref or
x_fc_po_number when the invoice is created with invoice_origin set
but no ref. Already populated on the SO confirm path; this catches
manually-created invoices that would otherwise miss it. Customer
AP teams reject invoices that don't quote their PO# back.
**9. Discharge sample close gate** (fusion.plating.discharge.sample.action_close)
Block close unless:
• Lab Report # set
• Results Received Date set
• At least one parameter reading on file
• Lab certificate/report attached
Without lab evidence the record fails any environmental compliance
audit — the whole point is to document the test was performed and
what the lab said.
**Simulator** (scripts/fp_e2e_workforce.py)
Adds 4 new negative tests (Test 8-11), all wrapped in savepoints:
✓ Test 8 : NCR close without RC/containment/disposition → blocked
✓ Test 9 : CAPA close without analysis/plan/verification → blocked
✓ Test 10: Discharge sample close without lab evidence → blocked
✓ Test 11: Invoice ref auto-fills from SO.client_order_ref → asserted
**Final E2E**: 52 PASS / 2 WARN / 0 FAIL out of 54 checks.
Both remaining WARNs are expected (bake-window auto-create,
first-piece gate — coating-driven, this coating doesn't trigger them).
11 negative tests in total now, every gate fires when triggered.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two fixes from a single SO walkthrough screenshot:
**1. "Current stage" banner**
- Was placed `inside sheet` so it rendered at the BOTTOM of the form
where users miss it. Moved to `before form/header` (same xpath
pattern as the Account Hold banner) — now it's the first thing
visible above the SO header.
- Was still showing "Shipped — awaiting invoice" after the invoice
was posted because `_compute_workflow_stage` only advanced to
`complete` when shipped + ALL paid; an unpaid posted invoice left
the SO stuck on `shipped`. Added an `invoicing` branch: shipped +
has_posted_invoice → invoicing. Banner invisible-list now also
includes `invoicing` and `paid`, so the banner only shows for
in-progress steps.
**2. Chatter messages rendering raw HTML tags as text**
Odoo 19 escapes any string passed to `message_post(body=...)`
unless wrapped in `markupsafe.Markup`. We had ~10 places posting
HTML (`<a href>`, `<b>`, `<br/>`, `<code>`, `<pre>`) that all
showed up as `<a href=...>` literal text in the chatter.
Wrapped each one with `Markup(_(...))` so the tags render. Files
touched:
- fusion_plating_bridge_mrp/models/sale_order.py
(auto-MO failure code block, "Draft MO created" link,
"Job assigned to <b>" message)
- fusion_plating_bridge_mrp/models/mrp_production.py
("Recipe steps" pre/br block on each WO)
- fusion_plating_bridge_mrp/models/fp_proficiency.py
(operator promotion announcement)
- fusion_plating_configurator/models/fp_quote_configurator.py
(SO link, 3D model attached, drawing attached, save to catalog)
- fusion_plating_configurator/models/fp_part_catalog.py
(3D/drawing change tracking + propagation to linked quotes)
- fusion_plating_portal/models/fp_quote_request.py
(RFQ → SO link)
- fusion_plating_quality/models/fp_quality_hold.py
(hold status change)
- fusion_plating_shopfloor/controllers/manager_controller.py
(worker / tank / manager-takeover assignments)
Verified on entech: SO S00038 stage now reads `invoicing` (banner
hidden), and a freshly posted message shows `<a href>` and `<b>`
as actual link + bold instead of escaped text.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>