Files
Odoo-Modules/fusion_plating/CLAUDE.md
gsinghpal d9f58b9851 changes
2026-04-26 15:05:17 -04:00

52 KiB
Raw Blame History

Fusion Plating — Claude Code Instructions

Project

Fusion Plating is a multi-module Odoo 19 ERP for electroless nickel plating and metal finishing shops. Built by Nexa Systems for EN Technologies (the client). Replaces Steelhead Software.

Module Structure (30 modules)

fusion_plating/                     — Core: facilities, process types, tanks, baths, chemistry, recipes
fusion_plating_batch/               — Rack/barrel batch tracking (FpBatch, FpBatchChemistry)
fusion_plating_kpi/                 — KPI definitions, daily auto-compute, dashboard views
fusion_plating_configurator/        — Quotation configurator, pricing engine, part catalog, 3D viewer
fusion_plating_receiving/           — Parts receiving, inspection, damage logging
fusion_plating_invoicing/           — Invoice strategies (deposit/progress/net/COD), account holds
fusion_plating_certificates/        — Certificate registry (CoC, thickness reports), Fischerscope data
fusion_plating_notifications/       — Auto-email engine, notification templates, audit log
fusion_plating_shopfloor/           — Tablet UI, plant overview kanban, process tree visualization
fusion_plating_portal/              — Customer portal + self-service configurator wizard
fusion_plating_reports/             — PDF reports (WO margin, discharge sample, CoC, etc.)
fusion_plating_compliance/          — Compliance framework, jurisdictions
fusion_plating_compliance_on/       — Ontario compliance reference data (data-only, no menus)
fusion_plating_compliance_tor/      — Toronto bylaw discharge limits (data-only, no menus)
fusion_plating_aerospace/           — AS9100 / Nadcap
fusion_plating_nuclear/             — CSA N299 / CNSC
fusion_plating_cgp/                 — Controlled Goods Program
fusion_plating_safety/              — SDS, WHMIS, JHSC
fusion_plating_quality/             — QMS (NCR, CAPA, calibration)
fusion_plating_logistics/           — Pickup & delivery, chain of custody
fusion_plating_culture/             — Values / fundamentals (⚠️ RETIRED — do NOT auto-install)
fusion_plating_bridge_mrp/          — MRP integration (recipe→WO, portal job, work order priorities)
fusion_plating_bridge_sign/         — Digital signatures
fusion_plating_bridge_quality/      — Quality bridge
fusion_plating_bridge_documents/    — Odoo Documents integration (NCR, CAPA, FAIR, Doc Control)
fusion_plating_process_en/          — Electroless nickel process pack
fusion_plating_process_chrome/      — Chrome process pack
fusion_plating_process_anodize/     — Anodizing process pack
fusion_plating_process_black_oxide/ — Black oxide process pack
fusion_tasks/                       — Local delivery dispatch (GPS, maps, driver scheduling)

Menu Structure (Plating App)

The Plating app (menu_fp_root, seq 46) has these top-level menus:

Seq Menu Module Children
3 KPIs fusion_plating_kpi KPIs, KPI History, Production/Quality/Finance dashboards
5 Sales fusion_plating_configurator + portal Quotations, Sale Orders, Customers, Part Catalog, Quote Requests, Portal Jobs
8 Configurator fusion_plating_configurator New Quote, Coating Configs, Pricing Rules, Treatments
12 Shop Floor fusion_plating_shopfloor Plant Overview, Tablet Station, Bake Windows, First-Piece Gates
15 Receiving fusion_plating_receiving All Receiving, Pending Inspection, Discrepancies
18 Operations fusion_plating (core) Process Recipes, Production Priorities (bridge_mrp), Batches (batch), Baths, Chemistry Logs, Tanks
25 Certificates fusion_plating_certificates All, CoC, Thickness Reports
30 Quality fusion_plating_quality Holds, NCRs, CAPAs, FAIR, Audits, Doc Control
40 Compliance fusion_plating_compliance Permits, Discharge, Waste, Calendar, Spills, Config
45 Safety fusion_plating_safety SDS, Training, Exposure, JHSC, Incidents, PPE
50 Logistics fusion_plating_logistics + fusion_tasks Pickups, Deliveries, Routes, CoC, POD, Field Tasks, Task Map, Task Calendar
60 Aerospace fusion_plating_aerospace AS9100, Nadcap, Counterfeit, Config Items, Risk
65 Nuclear fusion_plating_nuclear Program, ITP, 10CFR21, Pedigree, CNSC
70 CGP fusion_plating_cgp Registration, AI, PSA, Visitors, Goods, Shipments, Security, Access Log
80 Culture fusion_plating_culture Values, Recognitions — RETIRED, uninstalled on entech, code kept in repo only
90 Configuration fusion_plating (core) + many Facilities, Work Centres, Process Categories/Types, Bath Params, Stations, Ovens, Invoice Strategy, Account Holds, Training Types, Chemicals, Notification Templates/Log, Calibration, Specs, AVL, Value Sets/Rotations, N299 Levels, Vehicles

Field Service (fusion_tasks) also has its own standalone root app (seq 45) with Map View, Tasks, Calendar, Configuration. The same task actions are also accessible under Plating > Logistics.

Key rule: Sales menu is unified in fusion_plating_configurator. Portal module adds Quote Requests + Portal Jobs as children (referencing fusion_plating_configurator.menu_fp_sales). Do NOT create a separate Sales menu in portal.

Retired / Do-Not-Install Modules

These modules have source code in this repo but are intentionally NOT installed on entech (the client's live Odoo). Do not:

  • Include them in any -i or -u sequence that installs modules automatically.
  • Add them as a depends target from any other Fusion Plating module.
  • Re-sync their folders to /mnt/extra-addons/custom/ on entech.
  • Recommend installing them to the user without explicit confirmation.
Module State on entech Retired because What to do if revisiting
fusion_plating_culture state=uninstalled, dir removed from entech disk Soft people-ops feature (peer kudos / "Fundamental of the Week"); zero data entered; not a client priority. Top-level "Culture" menu confused operators. Ask the client whether they want it before reinstalling. If yes: re-sync folder + -i fusion_plating_culture + seed a value set.
fusion_plating_sensors deleted entirely (not in repo anymore) Duplicated fusion_plating_iot's scope but with no working alerting logic. Its valuables (sensor_type taxonomy, dashboard, location flexibility) were ported into fusion_iot/fusion_plating_iot/. N/A — gone. Any new sensor work goes in fusion_iot/fusion_plating_iot/.

Critical Rules — Odoo 19

  1. NEVER code from memory — Read reference files from the server first.
  2. Backend OWL: static template, static props = ["*"], standalone rpc() from @web/core/network/rpc. NOT useService("rpc").
  3. HTTP routes: type="jsonrpc" — NOT type="json" (deprecated in Odoo 19).
  4. Search views: NO group expand="0", NO string attribute on <search>, NO <group string="..."> wrapper for group-by filters. Use bare <group> for group-by.
  5. res.config.settings: Only boolean/integer/float/char/selection/many2one/datetime. NO Date fields.
  6. res.groups: Use privilege_id (NOT category_id). user_ids is OK but the deprecated users alias is NOT. Always include sequence field.
  7. Field params: parent_path does NOT accept unaccent parameter in Odoo 19.
  8. SCSS borders: Use $border-color (SCSS variable) for card borders, NOT color-mix() in border shorthand — the SCSS compiler drops it. color-mix() works fine in background-color, box-shadow, etc.
  9. Theme awareness: All colours must use CSS custom properties (var(--bs-body-bg), var(--bs-body-color), var(--bs-border-color), var(--bs-secondary-color), var(--o-action)). NO hardcoded hex. See fusion_plating_shopfloor.scss as the gold standard.
  10. XML comments: No double-hyphens (--) inside <!-- --> comments — invalid XML, causes lxml parse error.
  11. XML data ordering: Window actions must be defined BEFORE <menuitem> elements that reference them in the same file.
  12. Module install on new modules: Use --update=base alongside -i MODULE to ensure Odoo rescans the addons path and finds the new module directory.
  13. Implied group cascade: implied_ids on res.groups does NOT reliably propagate to users on module install. Always include user_ids to explicitly assign admin, or fix via SQL post-install.

Naming

  • New custom models (post-2026-04): fp.* prefix (e.g. fp.part.catalog, fp.certificate)
  • Existing custom models: Keep fusion.plating.* (e.g. fusion.plating.portal.job, fusion.plating.delivery)
  • New fields on standard Odoo models: x_fc_* prefix
  • Legacy fields: x_studio_*
  • Canadian English for all user-facing text
  • SCSS class prefix: o_fp_* (shopfloor: o_fp_po_*, o_fp_pt_*; recipes: o_fp_recipe_*)
  • Monetary fields: always pair with currency_id field on the same model

Process Recipe System (NEW — v19.0.2.x)

Model: fusion.plating.process.node (in fusion_plating core)

  • Hierarchical tree with _parent_store = True
  • Node types: recipe, sub_process, operation, step
  • Companion model: fusion.plating.process.node.input (operator inputs)
  • icon is a Selection field (24 curated plating icons), NOT a Char
  • Auto-icon: JS guessIcon(name) maps keywords → icons when adding nodes
  • OWL tree editor: registered as fp_recipe_tree_editor client action
  • Controller: fusion_plating/controllers/recipe_controller.py (7 endpoints)
  • SCSS: fusion_plating/static/src/scss/recipe_tree_editor.scss

Recipe Endpoints

POST /fp/recipe/tree              — full nested tree for OWL editor
POST /fp/recipe/node/create       — add child node
POST /fp/recipe/node/write        — update fields
POST /fp/recipe/node/unlink       — delete + cascade
POST /fp/recipe/node/reorder      — bulk sequence update
POST /fp/recipe/node/move         — change parent_id
POST /fp/recipe/duplicate         — deep-copy recipe

Steelhead Features Status

Feature Status
Hierarchical process tree Done
Node types (recipe/sub/op/step) Done
Auto-complete flag Done
Customer visible flag Done
Manual/automated flag Done
Requires sign-off Done
Opt In/Out (disabled/opt-in/opt-out) Done
Icon picker Done
Time tracking (created/updated with seconds) Done
Operator inputs Done
Description (rich text) Done
File attachments (via mail.thread) Done
OWL tree editor with drag-drop Done
Tags Not yet
Dashboard Transitions Not yet
Treatment Groups / Choices Not yet
Go To Node Options Not yet
Spec Fields Not yet

Client Recipes Created

  • ENP-ALUM-BASIC — Electroless Nickel Plating Aluminium Basic (9 operations, 15 steps). Data file: fusion_plating/data/fp_recipe_enp_alum_basic.xml

Plant Overview Dashboard

  • OWL client action: fp_plant_overview in fusion_plating_shopfloor
  • Kanban columns = work centres, cards = active mrp.workorder records
  • Drag & drop between columns (writes workcenter_id on the work order)
  • Endpoint: POST /fp/shopfloor/plant_overview
  • Move endpoint: POST /fp/shopfloor/plant_overview/move_card
  • Auto-refreshes every 30s

Deployment

odoo-entech (LXC 111 on pve-worker5)

  • Type: Native Odoo (apt package, NOT Docker)
  • IP: 10.200.1.26
  • DB: admin (PostgreSQL local, user odoo)
  • Config: /etc/odoo/odoo.conf
  • Addons: /mnt/extra-addons/custom/ (fusion_plating modules live here)
  • Service: systemctl {start|stop|restart} odoo
  • Update command:
    ssh pve-worker5 "pct exec 111 -- bash -c 'systemctl stop odoo && su - odoo -s /bin/bash -c \"/usr/bin/odoo -c /etc/odoo/odoo.conf -d admin -u MODULE_NAME --stop-after-init\" && systemctl start odoo'"
    
  • Copy files: cat LOCAL_FILE | ssh pve-worker5 "pct exec 111 -- bash -c 'cat > /mnt/extra-addons/custom/REMOTE_PATH'"
  • IMPORTANT: Must pass -c /etc/odoo/odoo.conf or Odoo won't find the repackaged enterprise addons

odoo-trial (VM 316 on pve-worker1)

  • Type: Docker (container odoo-trial-app, db odoo-trial-db)
  • DB: trial (user odoo)
  • Host addons path: /opt/odoo/custom-addons/ → mounts as /mnt/extra-addons/ in Docker
  • Docker network: odoo_odoo-network
  • Copy files (base64 pipe through qm guest exec):
    B64=$(base64 -w0 "LOCAL_FILE")
    ssh pve-worker1 "qm guest exec 316 -- bash -c 'echo $B64 | base64 -d > /opt/odoo/custom-addons/REMOTE_PATH'"
    
  • Clear asset cache (required after SCSS/JS changes):
    ssh pve-worker1 "qm guest exec 316 -- bash -c \"docker exec odoo-trial-db psql -U odoo -d trial -c \\\"DELETE FROM ir_attachment WHERE url LIKE '%/web/assets/%';\\\"\""
    
  • Update command:
    ssh pve-worker1 "qm guest exec 316 -- bash -c 'docker stop odoo-trial-app && docker run --rm --network odoo_odoo-network -v odoo_odoo-data:/var/lib/odoo -v /opt/odoo/custom-addons:/mnt/extra-addons -v /opt/odoo/enterprise-addons:/mnt/enterprise-addons -v /opt/odoo/odoo.conf:/etc/odoo/odoo.conf odoo:19 odoo -d trial -u MODULE_NAME --stop-after-init && docker start odoo-trial-app'"
    

Git Push

cd K:/Github/Odoo-Modules/fusion-plating && git push origin main

Pushes to both GitHub and Gitea (nexasystems.ca) via multiple remotes.

Supabase Knowledge Base

Project: nexasystems (id: ikvdlqkbqsitabxidvnq)

  • fusionapps.decisions — past architecture decisions
  • fusionapps.issues — known issues and fixes
  • fusionapps.code_snippets — reference code
  • fusionapps.quick_commands — deployment and admin commands
  • fusionapps.vm_registry — VM inventory
  • fusionapps.proxmox_nodes — cluster node specs

End-to-End Business Workflow

Full Lifecycle (What Exists Today)

┌─ QUOTATION ──────────────────────────────────────────────────────┐
│ 1. Customer submits RFQ on portal                     [DONE]     │
│    → FpQuoteRequest (state: new → under_review → quoted)         │
│    → Model: fusion_plating_portal/models/fp_quote_request.py     │
│                                                                   │
│ 2. Customer accepts → "Create Sale Order" button       [DONE]    │
│    → action_create_sale_order() creates SO with lines            │
│    → Links SO origin back to RFQ ref                             │
│                                                                   │
│ 3. SO confirmed → MRP creates Manufacturing Order      [DONE]    │
│    → Standard Odoo sale_mrp flow                                 │
└──────────────────────────────────────────────────────────────────┘

┌─ MANUFACTURING ──────────────────────────────────────────────────┐
│ 4. MO confirmed → Portal Job auto-created              [DONE]    │
│    → MrpProduction.action_confirm() override                     │
│    → Creates FpPortalJob (state: in_progress)                    │
│    → Links via x_fc_portal_job_id                                │
│                                                                   │
│ 5. Planner assigns recipe + configures steps           [DONE]    │
│    → x_fc_recipe_id set on MO                                    │
│    → Opens fp.recipe.config.wizard for opt-in/out                │
│    → Creates fusion.plating.job.node.override records            │
│                                                                   │
│ 6. Work orders generated from recipe                 [DONE]      │
│    → _generate_workorders_from_recipe() in bridge_mrp            │
│    → One WO per operation node, steps become WO instructions     │
│    → Respects opt-in/out overrides from job.node.override        │
│                                                                   │
│ 7. Operators execute WOs on shopfloor                  [DONE]    │
│    → Plant Overview kanban (drag between work centres)           │
│    → Batch chemistry tracking (FpBatch + FpBatchChemistry)       │
│    → Quality holds (FpQualityHold → FpNcr → FpCapa)             │
│                                                                   │
│ 8. MO marked done → Portal job ready_to_ship           [DONE]    │
│    → MrpProduction.button_mark_done() override                   │
│    → Auto-creates FpDelivery (draft)                             │
└──────────────────────────────────────────────────────────────────┘

┌─ SHIPPING & INVOICING ───────────────────────────────────────────┐
│ 9. CoC report generated                                [DONE]    │
│    → report_coc.xml (PDF with job info, certification, sig)      │
│    → Attached to delivery + portal job                           │
│                                                                   │
│ 10. Delivery scheduled & executed                      [DONE]    │
│     → FpDelivery: draft → scheduled → en_route → delivered       │
│     → Chain of custody auto-logged (FpChainOfCustody)            │
│     → Proof of delivery captured (FpProofOfDelivery)             │
│     → Routes with stops (FpRoute + FpRouteStop)                  │
│                                                                   │
│ 11. Delivery marked → Portal job shipped               [DONE]    │
│     → FpDelivery.action_mark_delivered() override                │
│     → Sets actual_ship_date + tracking_ref on portal job         │
│                                                                   │
│ 12. Account hold check before invoicing              [DONE]      │
│     → x_fc_account_hold on res.partner (fusion_plating_invoicing)│
│     → Blocks SO confirm, invoice post, shipping for non-managers │
│                                                                   │
│ 13. Invoice posted → Portal job complete               [DONE]    │
│     → AccountMove.action_post() override                         │
│     → Sets invoice_ref on portal job, state → complete           │
│                                                                   │
│ 14. Auto-email with CoC + Invoice + Tracking         [DONE]      │
│     → fusion_plating_notifications module                        │
│     → fp.notification.template (configurable per trigger event)  │
│     → fp.notification.log (audit trail)                          │
└──────────────────────────────────────────────────────────────────┘

┌─ CUSTOMER PORTAL ────────────────────────────────────────────────┐
│ 15. Customer sees on portal                            [DONE]    │
│     → Job progress bar (received → complete)                     │
│     → CoC download, invoice access, tracking ref                 │
│     → Quote request history                                      │
└──────────────────────────────────────────────────────────────────┘

Per-Job Recipe Overrides (v19.0.2.0.0 bridge_mrp)

  • x_fc_recipe_id on mrp.production → links MO to recipe
  • fusion.plating.job.node.override → per-job opt-in/out decisions
  • fp.recipe.config.wizard → checklist wizard for planner
  • "Overrides" stat button on MO form
  • Located in fusion_plating_bridge_mrp

All Gaps Resolved (2026-04-12/13)

Gap Resolution Module
Recipe → Work Orders _generate_workorders_from_recipe() — one WO per operation, steps become instructions fusion_plating_bridge_mrp v2.1.0
Account Hold Check x_fc_account_hold on res.partner, blocks SO/invoice/shipping for non-managers fusion_plating_invoicing
Auto-Email Package fp.notification.template + fp.notification.log with hooks on SO confirm, receiving, invoice fusion_plating_notifications
Quotation Configurator Part catalog, coating configs, pricing engine, 3D STL viewer, portal wizard fusion_plating_configurator
Parts Receiving Receiving records, inspection, damage logging, SO auto-create, MRP soft gate fusion_plating_receiving
Certificate Registry Unified fp.certificate with thickness readings, CoC/thickness/Nadcap types fusion_plating_certificates
Local Delivery Forked fusion_tasks with GPS/maps, stripped of claims/sync, delivery-specific fields fusion_tasks

Architectural Decisions Made

  1. Recipe → WO: One WO per operation node, child step nodes become numbered instructions in WO description
  2. Account hold: Manual flag on res.partner (auto from aging is roadmap)
  3. Email triggers: SO confirmed, parts received, invoice posted (configurable per trigger)
  4. Configurator: Custom build with formula-based pricing, estimator override, portal self-service wizard
  5. Model naming: New models use fp.* prefix, existing keep fusion.plating.*
  6. Security groups: Role-based (Estimator, Receiving, Accounting, Shop Manager) layered on existing privilege hierarchy (Operator→Supervisor→Manager→Admin)

Key Models Quick Reference

Model Module Purpose
fusion.plating.process.node fusion_plating Recipe tree (template)
fusion.plating.process.node.input fusion_plating Operator input definitions
fusion.plating.job.node.override fusion_plating_bridge_mrp Per-job opt-in/out
fp.part.catalog fusion_plating_configurator Customer part library (geometry, material)
fp.coating.config fusion_plating_configurator Coating configuration templates
fp.treatment fusion_plating_configurator Pre/post treatment steps
fp.pricing.rule fusion_plating_configurator Formula-based pricing engine
fp.pricing.complexity.surcharge fusion_plating_configurator Complexity surcharge lines
fp.quote.configurator fusion_plating_configurator Configurator session + price calc
fp.receiving fusion_plating_receiving Parts receiving record
fp.receiving.line fusion_plating_receiving Per-part receiving detail
fp.receiving.damage fusion_plating_receiving Damage log entry
fp.invoice.strategy.default fusion_plating_invoicing Customer-level invoice strategy
fp.certificate fusion_plating_certificates Certificate registry (CoC, thickness, etc.)
fp.thickness.reading fusion_plating_certificates Fischerscope measurement data
fp.notification.template fusion_plating_notifications Configurable email notification
fp.notification.log fusion_plating_notifications Email audit trail
fusion.plating.quote.request fusion_plating_portal Customer RFQ
fusion.plating.portal.job fusion_plating_portal Portal-facing job tracker
fusion.plating.customer.spec fusion_plating_quality Spec library
fusion.plating.quality.hold fusion_plating_quality Parts on hold
fusion.plating.ncr fusion_plating_quality Non-conformance reports
fusion.plating.capa fusion_plating_quality Corrective actions
fusion.plating.batch fusion_plating_batch Rack/barrel batch tracking
fusion.plating.kpi fusion_plating_kpi KPI definition (OTD, yield, throughput, etc.)
fusion.plating.kpi.value fusion_plating_kpi KPI daily value (auto-computed or manual)
fusion.plating.delivery fusion_plating_logistics Delivery with chain of custody
fusion.plating.pickup.request fusion_plating_logistics Customer pickup requests
fusion.plating.route fusion_plating_logistics Driver routes with stops
fusion.technician.task fusion_tasks Local delivery task (GPS, maps)
fusion.technician.location fusion_tasks Driver GPS tracking

Repackaged Enterprise Modules

See K:\Github\RePackaged-Odoo\CLAUDE.md for full details. Key points:

  • Odoo 19 enterprise modules repackaged for community edition
  • All OEEL-1 licenses changed to LGPL-3
  • Phone-home/telemetry gutted
  • web_enterprise and mail_enterprise are installed on odoo-entech
  • Addons path includes: _dependencies, accounting, inventory_manufacturing, hr, sales, ai, fusion_backend, custom, website

Fine-Tuning Initiative (Started 2026-04-21)

System-wide UX gap closure. Running PLAN → SPEC → IMPLEMENT per sub-project so we don't rewrite code as new requirements surface. Each sub-project has its own design doc in docs/superpowers/specs/ and its own implementation plan before any code lands.

Sub-Project Roadmap

# Sub-project Status Gaps
1 Direct Order Wizard fix (no auto-confirm/auto-email) Shipped 2026-04-22 (commit afd8bae+) Gap 1
2 Part Data Model Overhaul (part#/rev required, dual descriptions, per-part cert requirement, SKU→Part Number on customer docs) Shipped 2026-04-22 (commits 868b418..afd8bae) 2b, 2c, 2d, 4
3 Default Process + Composer per part (reuse recipe tree) Shipped 2026-04-22 (commits ce07daa..f059348) 2e, 2f
4 Contract Review (optional, per-part, settings-driven QA roster, QA-005 1:1 PDF) Shipped 2026-04-22 2i
5 Order-line fields (fp.serial registry, auto job#, coating-scoped thickness dropdown, revision picker) Shipped 2026-04-22 5, 6, Q2
6 Contact Profiles & Communication Routing (per-contact flags + per-location routing + global contact; single resolver helper) Shipped 2026-04-22 client transcript A/B/C
7 IoT tuning (per-sensor polling interval + ingest rate-limit; entech seeded with 25 tanks / 50 sensors) Shipped 2026-04-22 client transcript D
8 Receiving / Inspection / QC flow restructure (fp.receiving = box count only; new fp.racking.inspection per MO; WO soft gate; delivery box-parity warning) Shipped 2026-04-22 client transcript E
9 Process variants per part + persistent draft order wizard + tax per line + payment terms wired + chatter + nicer breadcrumbs across plating models Shipped 2026-04-26 various wizard/UX
10 Quote → Direct Order promotion (won quotes consolidate onto a single PO instead of spawning standalone 1-line SOs) Shipped 2026-04-26 redundancy concern
11 MRP cutout — bridge_mrp deletion + MRP module uninstall (7-phase migration: relocate models, swap inherits, drop legacy FK columns, uninstall mrp + 10 cascade modules) Shipped 2026-04-26 bridge_mrp removal
12 Native Quality — full Odoo quality_control replacement + RMA + integration polish In flight (planned) quality dependency removal
First-off / last-off QC Deferred client transcript F
VEC machine auto-ingest (Word-format thickness report from network-connected XRF; different machine from Fischerscope) Deferred client transcript G
RMA customer portal submission Deferred (Sub 12 phase 2) follow-on to Sub 12

Sub 2 Locked Decisions (2026-04-21)

Q Decision
Q1 — Cert requirement precedence Part wins; partner is fallback. New selection certificate_requirement on fp.part.catalog: inherit / none / coc / coc_thickness. Default inherit preserves current behaviour for existing records.
Q2 — Revision handling Keep existing chain (parent_part_id, is_latest_revision, revision_ids). Out-of-scope for Sub 2. The "revision picker at order entry" moves to Sub 5.
Q3 — Required-field flip Strict + backfill. On upgrade: part_number = name if empty; revision = 'A' if empty. Then required=True for both. name becomes optional.
Q4 — Descriptions shape Split fp.sale.description.template.description into internal_description + customer_facing_description. Repeater on the part's Descriptions tab gains two columns. Old description column dropped in migration.
Q5 — SKU vs Part Number Use fp.part.catalog.part_number directly as the source of truth. Don't sync to default_code. Customer-facing reports print part_number; internal reports keep showing default_code (service code). Odoo-native screens untouched.
Q6 — Description required at order entry Both required. SO line carries name (customer-facing, already Odoo standard) + new x_fc_internal_description (ops workflow). Both required before save.

Sub 2 Defensive Measures (Prevent Rework When Later Subs Land)

  1. Single-source cert resolution functionmrp.production._fp_resolve_cert_requirement(self) returns (want_coc, want_thickness). Every caller (cert cascade, QC gate, notification routing) goes through this. When Sub 6 restructures partner-level flags into location / contact permissions, one function updates — no call-site hunt.
  2. Shared QWeb line-header macrofusion_plating_reports.customer_line_header renders part_number + revision + customer-facing description with fallback to product name for non-part lines. All 4 customer-facing reports (SO, invoice, packing slip, BoL) call the macro. Sub 5's revision picker updates the macro once, all reports follow.
  3. Isolated migration — Sub 2's post_init_hook is idempotent (NULL/empty checks). Safe to re-run. Doesn't fight Sub 3/4/5/6 migrations.
  4. Additive SO line fieldsx_fc_internal_description, x_fc_description_template_id sit alongside future Sub 5 fields (x_fc_serial_number, x_fc_job_number, x_fc_thickness, x_fc_revision_snapshot) with zero touchpoints.
  5. Clean removal of old description column — migrated then dropped. Not kept as deprecated. One clean break now beats two migrations later.

Sub 6 Preview — Contact Profiles & Communication Routing (client transcript A/B/C)

  • Sub-contacts under res.partner with per-contact permissions: certs / QC / quotes+SO / invoices.
  • Multiple delivery locations per customer; each location has its own notification list.
  • Global contact (company-level + location-level) gets all communications.
  • Will restructure or augment the partner-level x_fc_send_coc / x_fc_send_thickness_report flags that Sub 2 currently falls back to. Sub 2's _fp_resolve_cert_requirement is the update point.

Sub 7 Preview — IoT Tuning (client transcript D)

  • 610 active tanks (of ~2025 total) need continuous monitoring.
  • Polling interval: 30 minutes acceptable, 15 minutes ideal. Configurable per tank.
  • Temperature, pH, nickel concentration — all on automated controller (existing fusion_plating_iot module).
  • Work scope: ensure per-sensor interval field exists + defaults + seed 610 tank.sensor records.

Sub 8 Preview — Receiving / Inspection / QC Restructure (client transcript E)

Current flow (wrong): Direct order → receiving entry → receiver inspects on arrival. Correct flow:

  1. Customer ships parts in boxes. Receiver counts boxes (does NOT inspect individual parts).
  2. Boxes sit in staging until racking.
  3. Racking crew opens boxes, inspects each part as they load racks (inspection ≠ receiving).
  4. Parts go through plating process.
  5. Post-plate QC on machine (thickness / depth / coating thickness) — existing QC gate (Phase 13 work).
  6. Pack back into the SAME boxes they arrived in. Same qty out as in.

Implication: The current fusion_plating_receiving module conflates receiving + inspection. Sub 8 splits them. Racking-time inspection becomes its own record, linked to WOs not to receiving.

Deferred Items (Future)

  • First-off / last-off QC — first and last part of each batch get full QC inspection; middle parts sampled. Not priority.
  • VEC machine auto-ingest — different from Fischerscope. Exports a Word doc (picture + data) named workorder_PO.docx to a network share. Plan: auto-scan the share, parse, attach to QC as thickness_report. Defer until core flow is solid.

Client-Confirmed Operational Thresholds

  • Tank polling: 1530 min, half-hour acceptable
  • Active tanks: 610 (not all 2025)
  • Boxes round-trip: parts ship back in the same boxes they arrived in, same quantity per box

How to Resume This Work in a Fresh Session

  1. Read this section (Fine-Tuning Initiative).
  2. Check the sub-project status table — which sub is in flight.
  3. Read the corresponding spec in docs/superpowers/specs/YYYY-MM-DD-sub<N>-*-design.md.
  4. Read the implementation plan if one exists.
  5. Continue from the next un-checked step.

Sub 11 — MRP Cutout (shipped 2026-04-26)

The Odoo mrp module + 10 cascade dependents have been uninstalled. fusion_plating_bridge_mrp is gone. The plating shop runs entirely on fp.job / fp.job.step. Document this so a fresh session doesn't try to re-add MRP refs.

Final state

  • 0 rows in mrp_production, mrp_workorder, mrp_workcenter
  • 205+ fp.job rows, 1,800+ fp.job.step rows in production
  • 0 custom-table FKs to MRP
  • Modules uninstalled: mrp, mrp_workorder, mrp_account, sale_mrp, purchase_mrp, quality_mrp, quality_mrp_workorder, project_mrp*, fusion_manufacturing, fusion_plating_bridge_mrp

Where things ended up after Sub 11

Model / asset Old home New home
fp.work.role, fp.operator.proficiency, hr.employee shop-roles, fusion.plating.process.node.x_fc_work_role_id fusion_plating_bridge_mrp fusion_plating (core)
fp.qc.checklist.template (+line) fusion_plating_bridge_mrp fusion_plating_quality
fusion.plating.quality.check (+line) fusion_plating_bridge_mrp fusion_plating_quality
fp.thickness.reading.quality_check_id link + auto_extracted fusion_plating_bridge_mrp fusion_plating_quality
res.partner.x_fc_requires_qc + x_fc_qc_template_id fusion_plating_bridge_mrp fusion_plating_quality
fp.job.consumption fusion_plating_bridge_mrp fusion_plating_jobs
sale.order.x_fc_workflow_stage + x_fc_assigned_manager_id + workflow buttons fusion_plating_bridge_mrp fusion_plating_jobs
QC tablet OWL (fp_qc_checklist.js/.xml/.scss) + /fp/qc/* controller fusion_plating_bridge_mrp fusion_plating_quality
Production Priorities kanban fusion_plating_bridge_mrp (mrp.workorder) fusion_plating_jobs (fp.job.step)

Hard rules going forward

  1. Never re-introduce 'mrp' as a manifest dep. Use fp.job for jobs, fp.job.step for operations.
  2. x_fc_job_id is the canonical job link, not production_id. Drop legacy MO refs as you find them.
  3. fusion_plating_quality depends on fusion_plating_shopfloor for SCSS tokens ($fp-page, $fp-card, $fp-accent). Don't strip that dep — the QC tablet bundle breaks without it.
  4. The QC tablet OWL template namespace is fusion_plating_quality.FpQcChecklist (was fusion_plating_bridge_mrp.FpQcChecklist). Don't rename back.

Sub 12 — Native Quality Module (in flight, ~4 working days)

Goal: Build a complete native quality stack matching Odoo quality_control functionality plus plating-specific extensions (RMA, CAPA effectiveness, holds, 8D reports), with zero dependency on Odoo's quality / quality_control. After Sub 12 lands, those modules + fusion_plating_bridge_quality get uninstalled.

Module choice

Enrich fusion_plating_quality — no new modules. Existing module already owns NCR / CAPA / Hold / Check / Calibration / AVL / FAIR / Audit / Doc Control / Customer Spec / Contract Review.

Locked decisions (don't re-ask in fresh session)

Q Decision
RMA portal submission Deferred to phase 2. Internal-only RMA in Sub 12.
8D format Full 8D (D1D8 sections in the combined NCR + CAPA PDF).
Quality Dashboard 5 tabs (Holds / Checks / NCRs / CAPAs / RMAs) in one client action with a summary header that totals open + overdue across all five.
Auto-NCR + auto-Hold on RMA receive Automatic, with a manager-only "skip this RMA's auto-spawn" toggle on the RMA record.
Auto-CAPA on NCR closure Automatic when severity in (high, critical), with a manager-only override on the NCR.
Quality team model Build a dedicated fp.quality.team rather than reusing res.groups. Teams need their own kanban grouping + per-team escalation chains, which groups don't model well.
Stage model vs. state field on NCR Both. Keep the existing state Selection (used by code paths). Add a parallel stage_id Many2one to fp.quality.alert.stage for the kanban draggable view. Computed bidirectional sync (stage ↔ state).
Trigger-based quality.point Build a new fp.quality.point model. Trigger types: manual, receiving_done, job_step_done, job_done. Existing fp.qc.checklist.template STAYS — it's the template a point fires; the point is the trigger rule.
RMA back-link to original SO line Required field. Always carry the original SO line so cert / part / coating context follows the return.
Module choice (one or many) Single module — enrich fusion_plating_quality.

Phase A — RMA model (~1 day)

File: fusion_plating_quality/models/fp_rma.py

Model: fusion.plating.rma

Field Type Notes
name Char Sequence RMA/YYYY/NNNN
partner_id M2O res.partner Required
sale_order_id M2O sale.order The original order being returned
sale_order_line_ids M2M sale.order.line Specific lines being returned (subset of the SO)
original_job_ids M2O fp.job (compute from SO lines) For navigation only
state Selection draft / authorised / shipped_to_us / received / triaged / resolving / resolved / closed / cancelled
trigger_source Selection customer_complaint / qc_fail_post_ship / inspection_post_delivery / other
severity Selection low / medium / high / critical
complaint_description Html What the customer reported
triage_findings Html What we found on inspection
resolution_type Selection replace / rework / refund / scrap
resolution_notes Html Free-form notes on the chosen path
replacement_job_id M2O fp.job When replace/rework — the new job created
refund_invoice_id M2O account.move When refund — the credit note
inbound_receiving_id M2O fp.receiving The receiving record auto-created when carrier delivers
inbound_picking_id M2O stock.picking Optional — if a stock.picking is also created
linked_ncr_ids O2M fusion.plating.ncr (inverse rma_id) NCRs spawned from this RMA
linked_capa_ids O2M fusion.plating.capa (related via NCRs) Read-only roll-up
linked_hold_ids O2M fusion.plating.quality.hold (inverse rma_id) Holds placed on returned parts
qty_returned Integer Total units customer is returning
qty_received Integer Counted on receipt
customer_tracking Char Customer's outbound tracking #
our_tracking Char Our return-to-shop tracking #
carrier_id M2O delivery.carrier Optional
qr_code Binary (compute) QR encoding /fp/rma/<id> for the authorisation PDF
auto_spawn_ncr Boolean Default True. Manager can toggle off before saving.
auto_spawn_hold Boolean Default True.
tag_ids M2M fp.quality.tag (Sub 12 Phase B)
reason_id M2O fp.quality.reason (Sub 12 Phase B)
team_id M2O fp.quality.team (Sub 12 Phase B)
chatter mail.thread mandatory

Lifecycle hooks

  • action_authorise: state draft → authorised. Generate the RMA authorisation PDF + email link/QR to customer (using fp.notification.template if installed; falls back to standard mail.template).
  • action_mark_shipped_to_us: customer-driven; updates state when carrier scan logged.
  • On fp.receiving create with rma_id set: state → received. If auto_spawn_ncr, create an fusion.plating.ncr pre-filled (description, severity, customer, parent SO line). If auto_spawn_hold, create fusion.plating.quality.hold for the returned qty.
  • action_triage_complete: state → triaged. Requires resolution_type set.
  • action_resolve: state → resolved. Triggers resolution-specific actions:
    • replace → spawn new fp.job cloned from original
    • rework → spawn new fp.job referencing the returned units (linked to inbound fp.receiving)
    • refund → open account.move.refund wizard, link result to refund_invoice_id
    • scrap → create fp.job.consumption row tagged 'rma_scrap' + post chatter
  • action_close: state → closed. Locks editing.
  • action_cancel: any state → cancelled (manager only).

Smart buttons

RMA form gets buttons to: original SO, original Jobs, inbound Receiving, replacement Job, refund Invoice, NCRs (count), CAPAs (count), Holds (count). Per-target button visibility based on resolution_type / state.

Sequence

Create ir.sequence fp.rma with prefix RMA/%(year)s/, padding 4. Data file fp_rma_sequence.xml.

Reports

fusion_plating_reports/report/report_fp_rma_authorisation.xml — single-page customer-facing PDF with QR code. Branded "EN Technologies".

Phase B — Categorisation & kanban infra (~half day)

Files: fusion_plating_quality/models/fp_quality_tag.py, fp_quality_reason.py, fp_quality_team.py, fp_quality_alert_stage.py

fp.quality.tag

  • name (Char, required, translate)
  • color (Integer, kanban color)
  • active (Boolean)
  • Reused by NCR / CAPA / Hold / RMA / Check via M2M tag_ids

fp.quality.reason

  • name, description, category (selection: process / supplier / equipment / human / material / other)
  • Curated reason library so root-cause classification is consistent

fp.quality.team

  • name, lead_user_id (M2O res.users), member_ids (M2M res.users)
  • escalation_user_id (manager who gets notified on missed deadlines)
  • Used by NCR / RMA — primary owner team

fp.quality.alert.stage

  • name, sequence, fold (Boolean — collapsed-by-default in kanban)
  • Default stages seeded: New / Investigating / Containment / Disposition / Awaiting Sign-off / Closed / Cancelled
  • Add stage_id = fields.Many2one('fp.quality.alert.stage') to fusion.plating.ncr AND fusion.plating.rma. Map state ↔ stage_id via _inverse_* so legacy code paths keep working.

Apply tag/reason/team M2M/M2O fields to: NCR, CAPA, Hold, Check, RMA

Each model gets tag_ids, reason_id, team_id. NCR + RMA additionally get stage_id.

Phase C — Trigger-based quality points (~half day)

File: fusion_plating_quality/models/fp_quality_point.py

fp.quality.point

  • name, active, description
  • trigger_type (Selection): manual / receiving_done / job_confirmed / job_step_done / job_done / so_confirmed
  • Filters (any combination): partner_ids (M2M), part_catalog_ids (M2M), coating_config_ids (M2M), step_kind (Selection — wet/bake/inspect/etc.)
  • template_id (M2O fp.qc.checklist.template) — required, the checks to spawn
  • assignee_user_id (M2O res.users) — optional default inspector
  • Fires _spawn_check_for(<source_record>) which creates a fusion.plating.quality.check from the template + binds it to the source via job_id or step_id.

Hooks (already partly in place — extend)

  • fp.receiving.write hook (existing): when state flips to closed, walk all fp.quality.point with trigger receiving_done matching the receiving's partner/parts → spawn checks.
  • fp.job.action_confirm hook (existing — currently calls _fp_create_qc_check_if_needed): replace with quality.point lookup. Keep the existing partner-template fallback as a default point seeded by fp_qc_data.xml.
  • fp.job.button_mark_done: trigger job_done points.
  • fp.job.step.button_finish: trigger job_step_done points.

Phase D — Integration polish (~1 day)

  1. fp.job form smart-button row: add Holds, Checks, NCRs, CAPAs, RMAs buttons with badge counts. Always-visible (zero is OK).
  2. sale.order form smart-button row: same five, rolled up across all linked jobs.
  3. res.partner form: customer-level "Quality History" smart button that opens a kanban filtered to that partner across all 5 record types.
  4. One-click cross-creation:
    • Hold form → Open NCR button — pre-fills NCR with hold's part / customer / quantity / linked job.
    • NCR form → Spawn CAPA button — visible when state ∈ {disposition, closed} and severity ≥ medium.
    • CAPA form → Verify Effectiveness button — schedules a follow-up check on the originating NCR.
  5. Unified Quality Dashboard (fp_quality_dashboard client action):
    • 5 tabs: Holds / Checks / NCRs / CAPAs / RMAs
    • Each tab is a kanban grouped by stage_id (NCRs/RMAs) or state (Holds/Checks/CAPAs)
    • Header summary card: open count + overdue count across all 5 types
    • Filters: my team / my customer / overdue / high-severity
    • Menu: Plating → Quality → Dashboard
  6. CAPA closure-loop linkage: when CAPA effectiveness verification fails, auto-spawn a new NCR linked back to the original. Closes the loop "we said we fixed it but it happened again."

Phase E — Reports (~half day)

Files: fusion_plating_reports/report/report_fp_rma_authorisation.xml, report_fp_8d.xml, report_fp_quality_monthly.xml

  1. RMA Authorisation PDF: single-page customer-facing. Header with our logo + customer info, RMA number, parts listed (table), return-to address, QR code linking to /fp/rma/<id> for status tracking, carrier instructions.
  2. 8D Report (NCR + CAPA combined):
    • D1: Team (from team_id + member_ids)
    • D2: Problem description (NCR description + scope)
    • D3: Containment (NCR containment narrative)
    • D4: Root cause analysis (CAPA root_cause + reason_id)
    • D5: Permanent corrective action (CAPA action_plan)
    • D6: Implement & verify (CAPA implementation_date + verification_evidence)
    • D7: Prevent recurrence (CAPA preventive_actions)
    • D8: Congratulate the team (CAPA closure notes + team sign-offs)
    • Auto-renders when both NCR and CAPA exist; degraded mode if CAPA missing.
  3. Monthly Quality Summary (fp_quality_monthly report):
    • Counts by record type / severity / customer / month
    • Overdue ageing buckets
    • CAPA effectiveness rate (verified / total closed)
    • Repeat-customer-issue flag (>2 NCRs same customer in 90 days)
    • Run via cron monthly + on-demand from dashboard.

Phase F — Test + verify (~half day)

End-to-end smoke flow on a fresh DB:

  1. Customer reports issue → create RMA → authorise → email PDF
  2. Customer ships → carrier delivers → fp.receiving auto-created → RMA receives → NCR + Hold auto-spawn
  3. QA triages NCR → finds root cause → spawns CAPA (auto via severity rule)
  4. CAPA assigned to engineering → action plan written → implemented → effectiveness check scheduled
  5. Effectiveness verified → CAPA closes → NCR closes → RMA resolves (rework path) → replacement job created from original → ships → CoC issued → invoice
  6. Run 8D report on the closed NCR/CAPA pair
  7. Verify dashboard counts update at every state transition
  8. Confirm legacy NCR/CAPA/Hold/Check forms still work (no regressions)
  9. ACL drilldown: operator sees what they should, supervisor more, manager all

Phase G — Drop Odoo quality cascade (~30 min)

Pre-conditions: Phases AF all merged + smoke-tested.

  1. Strip the three custom fields from fusion.plating.ncr (x_fc_quality_alert_id, x_fc_quality_alert_synced, x_fc_auto_sync — added by bridge_quality)
  2. Remove fusion_plating_bridge_quality from /mnt/extra-addons/custom/
  3. SQL: UPDATE ir_module_module SET state='to remove' WHERE name IN ('fusion_plating_bridge_quality', 'quality_control', 'quality') AND state='installed';
  4. Restart odoo → cascade uninstall fires
  5. ALTER TABLE drop the three NCR columns
  6. (Optional) move /mnt/extra-addons/inventory_manufacturing/quality{,_control}/ out of the path so they can't auto-reinstall

Server / deployment notes (entech)

  • LXC 111 on pve-worker5, native odoo (apt), DB admin, addons path /mnt/extra-addons/custom/
  • Update flow:
    ssh pve-worker5 "pct exec 111 -- bash -c 'systemctl stop odoo && \
      su - odoo -s /bin/bash -c \"/usr/bin/odoo -c /etc/odoo/odoo.conf -d admin \
        -u fusion_plating_quality --stop-after-init\" && systemctl start odoo'"
    
  • File copy:
    cat LOCAL | ssh pve-worker5 "pct exec 111 -- bash -c 'cat > REMOTE'"
    
  • Asset cache bust: DELETE FROM ir_attachment WHERE url LIKE '/web/assets/%';
  • Always bump module version in __manifest__.py for migrations to fire (current fusion_plating_quality: 19.0.3.0.0; bump to 19.0.4.0.0 for Sub 12).

Build order (executable checklist for fresh session)

  1. Read this Sub 12 section in full + the Sub 11 section above (for context on what's already native).
  2. Bump fusion_plating_quality/__manifest__.py version to 19.0.4.0.0.
  3. Phase A — RMA: create fp_rma.py model + fp_rma_views.xml + fp_rma_sequence.xml + ACL rows + add to __manifest__.py data list.
  4. Phase A migration: not needed (new model, fresh table).
  5. Phase B — categorisation: create the 4 small models + their views + ACL. Add tag_ids / reason_id / team_id M2M/M2O to NCR, CAPA, Hold, Check, RMA. Add stage_id to NCR + RMA.
  6. Phase B data: seed default stages + a few starter tags/reasons/teams in fp_quality_categorisation_data.xml.
  7. Phase C — fp.quality.point model + view + ACL + the 4 trigger hooks (in fp.receiving, fp.job.action_confirm, fp.job.button_mark_done, fp.job.step.button_finish).
  8. Phase D — smart buttons on fp.job, sale.order, res.partner. Cross-creation buttons. Dashboard client action.
  9. Phase E — three QWeb reports.
  10. Phase F — manual smoke test + ACL drilldown + screenshot the dashboard.
  11. Deploy each phase as it lands (don't batch — easier to roll back). Bump version each time.
  12. Phase G runs LAST, only after confirmation that AF work end-to-end.

Things to NOT do

  • Don't add 'quality' or 'quality_control' to any manifest dep. They will be uninstalled by Phase G.
  • Don't import from odoo.addons.quality.*. Use only native models.
  • Don't put RMA in a new module. It belongs in fusion_plating_quality.
  • Don't break the existing QC tablet OWL. Its template namespace is fusion_plating_quality.FpQcChecklist, endpoints are /fp/qc/*, and fusion_plating_quality depends on fusion_plating_shopfloor for SCSS tokens.
  • Don't re-introduce production_id references anywhere. Use job_id / x_fc_job_id. MRP is gone.
  • Don't forget rma_id inverse field on NCR + Hold — those One2many fields on RMA need an inverse Many2one on the linked model.

Status check before starting (run this first in the fresh session)

-- Should show 4: NCR, CAPA, Hold, Check (Sub 12 adds RMA = 5)
SELECT model FROM ir_model WHERE model LIKE 'fusion.plating.%' AND model SIMILAR TO '%(ncr|capa|hold|check|rma)%';

-- Should show 'fusion_plating_quality_bridge_quality_control' state — likely 'installed' until Phase G
SELECT name, state FROM ir_module_module WHERE name LIKE 'quality%' OR name LIKE 'fusion_plating_bridge_quality';

-- Confirm MRP is gone (Sub 11)
SELECT name, state FROM ir_module_module WHERE name = 'mrp';  -- expect 'uninstalled'

-- Live row counts so you know what survives
SELECT 'ncr' AS m, count(*) FROM fusion_plating_ncr
UNION ALL SELECT 'capa', count(*) FROM fusion_plating_capa
UNION ALL SELECT 'hold', count(*) FROM fusion_plating_quality_hold
UNION ALL SELECT 'check', count(*) FROM fusion_plating_quality_check;