Per client direction: every order is a thickness RANGE (e.g. "0.0005-0.0008 mils" or "5-10 mils"), never a single value. The old picker model (fp.recipe.thickness with a single 'value' Float) was modelling the wrong concept and overcrowding the order entry UI. Replaced with one free-text Char field that auto-fills from last-used or part default. DELETED entirely: - fp.recipe.thickness model (file + view + ACL + manifest entry) - recipe.thickness_option_ids One2many (the picker source) - "Thickness Options" inline list on the recipe form - sale.order.line.x_fc_thickness_id (M2O picker) - account.move.line.x_fc_thickness_id - fp.delivery.x_fc_thickness_id - fp.direct.order.line.thickness_id ADDED: - sale.order.line.x_fc_thickness_range (Char) — operator types range - account.move.line.x_fc_thickness_range — for invoice rendering - fp.delivery.x_fc_thickness_range — for packing slip - fp.direct.order.line.thickness_range — for the wizard - fp.part.catalog.x_fc_default_thickness_range — part default AUTO-FILL CHAIN (sale.order.line + wizard line): 1. Operator already typed → keep 2. Most recent SO line for (this part, this customer) with a non-empty thickness_range → copy that 3. part.x_fc_default_thickness_range → copy 4. Blank — operator types Implemented as both an @api.onchange (interactive) AND a create() override (programmatic — wizard, sale_mrp bridge, imports). Same logic in both paths. WIZARD push-to-defaults: when "Save as Default" toggle is ticked on a wizard line, persist the line's thickness_range to part.x_fc_default_thickness_range so future first-customer orders get a sensible starting point. REPORTS: customer_line_header.xml + report_fp_wo_sticker.xml now print the Char range as-typed (no display_name lookup needed). KEPT (admin documentation only — doesn't affect order entry): - recipe.thickness_min, thickness_max, thickness_uom on the recipe root: documents the recipe's CAPABILITY range. No UI gate; just for spec authors to record what the chemistry can produce. JOB GROUPING: fp.job auto-create groups SO lines by (recipe, part, spec, thickness, serial). Updated to key on the thickness_range Char (stripped) instead of the deleted thickness_id integer. DB cleanup: --update=base ran on the upgrade, dropping the fp_recipe_thickness table + the four x_fc_thickness_id columns. Existing data was already nulled in earlier dev work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fusion Plating
Core module of the Fusion Plating product family. A configurable, multi-tenant capable ERP for plating and metal-finishing shops, built for Odoo 19 Community and Enterprise.
Copyright © 2026 Nexa Systems Inc. License: OPL-1 (Odoo Proprietary License v1.0)
What this module is
fusion_plating is the process-agnostic foundation that every plating or
metal-finishing shop needs, regardless of size, jurisdiction, process mix, or
industry. It provides:
- Facility — physical sites with their own tanks, operators, capabilities
- Process Type — extensible taxonomy (filled in by process packs)
- Work Center — lines and stations inside a facility
- Tank — physical vessel with QR code, state, bath history
- Bath — the chemistry currently in a tank, with its own lifecycle
- Bath Parameter — schema for chemistry readings
- Bath Log — daily/per-shift chemistry readings with pass/warn/fail rollup
- Security — Operator / Supervisor / Manager / Administrator roles
- Theme-aware UI — respects Odoo light/dark mode with zero duplication
What this module is not
This core intentionally ships with:
- No process chemistry — install
fusion_plating_process_en,_chrome,_anodize,_black_oxideetc. to get actual process types and their bath parameter schemas. - No regulatory data — install
fusion_plating_compliance_<region>to get jurisdiction-specific limits, forms, and reporting workflows. - No industry specialisations — install
fusion_plating_aerospace,_nuclear,_cgpetc. for industry-specific QMS overlays. - No client-specific strings — everything is data-driven.
Product family
| Module | Purpose | Status |
|---|---|---|
fusion_plating |
Core (this module) | MVP |
fusion_plating_quality |
QMS: NCR, CAPA, doc control, calibration, CoC | planned |
fusion_plating_compliance |
Generic compliance framework | planned |
fusion_plating_compliance_on |
Ontario regulatory pack | planned |
fusion_plating_compliance_tor |
Toronto Ch. 681 municipal pack | planned |
fusion_plating_safety |
SDS, WHMIS/TDG, JHSC, exposure | planned |
fusion_plating_shopfloor |
Tablet operator stations, QR scanning, bake-window enforcer | planned |
fusion_plating_portal |
Customer portal | planned |
fusion_plating_process_en |
Electroless nickel — low/mid/high phos | planned |
fusion_plating_process_chrome |
Chrome coating (hex & trivalent) | planned |
fusion_plating_process_anodize |
Aluminum anodizing (Type II, III) | planned |
fusion_plating_process_black_oxide |
Black oxidizing | planned |
fusion_plating_aerospace |
AS9100 + Nadcap AC7108 | planned |
fusion_plating_nuclear |
CSA N299, CNSC, NQA-1 | planned |
fusion_plating_cgp |
Controlled Goods Program | planned |
fusion_plating_logistics |
Pickup & delivery routing | planned |
fusion_plating_culture |
Values / fundamentals framework | planned |
fusion_plating_bridge_sign |
EE bridge: e-sign CoC acceptance | planned |
fusion_plating_bridge_documents |
EE bridge: Documents workspace | planned |
fusion_plating_bridge_quality |
EE bridge: native quality module |
planned |
Installation
# Development
docker exec odoo-dev-app odoo -d fusion-dev -u fusion_plating --stop-after-init
# Production — after rsync to target server
docker exec <odoo-container> odoo -d <db> -u fusion_plating --stop-after-init
No external Python dependencies. Depends only on standard Odoo 19 Community
base modules (base, mail, contacts, product, stock, sale_management,
purchase, hr, uom).
Design principles
- Works on both Odoo Community and Enterprise. Never depends on
quality,documents,sign,studio, ormrp_plm. EE-specific integrations live in separatefusion_plating_bridge_*modules. - No client-specific strings in core. Configuration, not code.
- Regions are data, not code. Sewer limits, waste classes, reporting forms come from region packs.
- Processes are plug-ins. New process (copper, zinc, tin) = new
fusion_plating_process_*module, core untouched. - Dashboards are configured, not coded. Shops pick their own headline KPIs.
- Theme-aware. Uses Odoo/Bootstrap CSS variables. One source of truth for colours; Odoo's theme engine decides light vs dark.
Security groups
| Group | Intended for |
|---|---|
| Operator | Shop-floor staff. Reads reference data, writes chemistry logs. |
| Supervisor | Line supervisors. Manages baths, schedules jobs, reviews logs. |
| Manager | Quality, EHS, plant manager, engineer. Full CRUD on configuration. |
| Administrator | Owner, system admin. All manager rights + system settings. |
Field naming convention
- New models use
fusion.plating.*namespace. - Fields on our own models use simple names (no prefix).
- Fields added to base Odoo models (
res.company,res.partner,product.template, etc.) use thex_fc_prefix per the repo convention.
Developer notes
- All models inheriting from
mail.threaduse the Odoo 19 chatter pattern. - Security follows the Odoo 19
res.groups.privilegepattern (module category → privilege → groups), not the legacycategory_id-on-group pattern. - Sequence numbers use
ir.sequenceseeded indata/fp_sequence_data.xml. - SCSS uses
color-mix()against CSS custom properties — never hardcodes hex values. Seestatic/src/scss/fusion_plating.scssfor the theming contract. - No
group expand="0"in search views (Odoo 19 incompatibility). - No
category_idorusersfield onres.groups(Odoo 19 incompatibility).