feat(step-library): full plating workflow coverage + per-recipe configurability + audit
Implements 2026-04-29-step-library-audit-design.md. Bumps fusion_plating to 19.0.18.7.0, fusion_plating_jobs to 19.0.8.12.0, fusion_plating_reports to 19.0.10.2.0. LIBRARY EXPANSION - 8 new Step Kinds: Receiving, Electroclean, Strike, Salt Spray, Adhesion Test, Hardness Test, Packaging, Tank Replenishment - 4 new input types: photo, multi_point_thickness, bath_chemistry_panel, ph - DEFAULT_INPUTS_BY_KIND rewritten to seed audit-grade prompts on every kind (bath IDs, photos, multi-point thickness, signatures, etc.) - + Common Audit Fields one-click button on the library template form - Default Operator Instructions relabel + alert callout PER-RECIPE CONFIGURABILITY - collect (Boolean) per recipe-step input prompt — opt out without delete - collect_measurements (Boolean) master switch on recipe step — when off, wizard skips entirely - template_input_id (Many2one) traceability link from recipe to library - Recipe-step backend form view exposes the new fields with handle drag, toggle, target range, and library-source column RUNTIME WIRING - Step input wizard filters node.input_ids to step_input AND collect=True; short-circuits on collect_measurements=False - New input types: photo (image widget + ir.attachment), multi-point thickness (5 readings + auto avg, skips empty cells), bath chemistry panel (pH/conc/temp/bath bundle), pH (0-14 numeric) - Composite values JSON-serialized into value_text; photo via attachment CoC REPORT - Filters captured prompts to collect=True only - Renders new input types with appropriate format MIGRATION (post-migrate.py for 19.0.18.7.0) - Backfills collect=True on recipe-step inputs - Backfills collect_measurements=True on recipe steps - Re-runs action_seed_default_inputs on every existing template (idempotent, preserves user edits) - Backfills template_input_id by name-matching against source library template (handles JSONB vs varchar name columns) SEED DATA - 8 example templates (one per new kind) in fp_step_template_data.xml with noupdate=1 BATTLE TEST - bt_step_library_audit.py: 29 assertions all PASS on entech OWL EDITOR EXTENSION DEFERRED - The simple recipe editor's per-step Instructions/Measurements expansions were not implemented in this pass; users configure via the backend recipe-step form. Track follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Part of the Fusion Plating product family.
|
||||
|
||||
Standalone views for fp.coating.thickness so SO-line m2o pickers
|
||||
can offer "Create and edit..." — the inline-on-coating-config
|
||||
editor was the only way to add thicknesses pre-Sub-12d.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<record id="view_fp_coating_thickness_list" model="ir.ui.view">
|
||||
<field name="name">fp.coating.thickness.list</field>
|
||||
<field name="model">fp.coating.thickness</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Coating Thicknesses" decoration-muted="not active">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="coating_config_id"/>
|
||||
<field name="value" string="Nominal"/>
|
||||
<field name="value_min" string="Min" optional="show"/>
|
||||
<field name="value_max" string="Max" optional="show"/>
|
||||
<field name="uom"/>
|
||||
<field name="display_name" string="Label"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_fp_coating_thickness_form" model="ir.ui.view">
|
||||
<field name="name">fp.coating.thickness.form</field>
|
||||
<field name="model">fp.coating.thickness</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Coating Thickness">
|
||||
<sheet>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
|
||||
<div class="oe_title">
|
||||
<label for="display_name" string="Thickness"/>
|
||||
<h2><field name="display_name" readonly="1" placeholder="Auto-generated from value + UoM"/></h2>
|
||||
</div>
|
||||
<group>
|
||||
<group string="Spec">
|
||||
<field name="coating_config_id"
|
||||
options="{'no_create_edit': True}"/>
|
||||
<field name="value" string="Nominal"/>
|
||||
<field name="uom"/>
|
||||
</group>
|
||||
<group string="Acceptance Band (optional)">
|
||||
<field name="value_min" string="Min"/>
|
||||
<field name="value_max" string="Max"/>
|
||||
<div colspan="2" class="text-muted">
|
||||
Set Min/Max when the customer spec is a
|
||||
range (e.g. AMS-2404 Class 4 = 0.001"–0.0015").
|
||||
QC readings outside the band fail.
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="sequence"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_fp_coating_thickness_search" model="ir.ui.view">
|
||||
<field name="name">fp.coating.thickness.search</field>
|
||||
<field name="model">fp.coating.thickness</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="coating_config_id"/>
|
||||
<field name="display_name"/>
|
||||
<field name="uom"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
<group>
|
||||
<filter string="Coating" name="group_coating"
|
||||
context="{'group_by':'coating_config_id'}"/>
|
||||
<filter string="UoM" name="group_uom"
|
||||
context="{'group_by':'uom'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_fp_coating_thickness" model="ir.actions.act_window">
|
||||
<field name="name">Coating Thicknesses</field>
|
||||
<field name="res_model">fp.coating.thickness</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_fp_coating_thickness_search"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -111,4 +111,10 @@
|
||||
action="action_fp_treatment"
|
||||
sequence="40"/>
|
||||
|
||||
<menuitem id="menu_fp_part_materials"
|
||||
name="Materials"
|
||||
parent="menu_fp_configurator"
|
||||
action="action_fp_part_material"
|
||||
sequence="50"/>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
<field name="name" string="Part Name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="revision"/>
|
||||
<field name="substrate_material"/>
|
||||
<field name="material_id" string="Material"/>
|
||||
<field name="substrate_material" optional="hide"/>
|
||||
<field name="surface_area"/>
|
||||
<field name="complexity"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
@@ -116,7 +117,9 @@
|
||||
<field name="partner_id"/>
|
||||
<field name="revision"/>
|
||||
<field name="revision_number"/>
|
||||
<field name="substrate_material"/>
|
||||
<field name="material_id"
|
||||
options="{'no_quick_create': True}"/>
|
||||
<field name="substrate_material" invisible="1"/>
|
||||
<field name="geometry_source"/>
|
||||
<field name="is_latest_revision" invisible="1"/>
|
||||
<field name="parent_part_id" invisible="not parent_part_id"/>
|
||||
@@ -135,6 +138,7 @@
|
||||
<field name="effective_area_sqin" readonly="1"/>
|
||||
<field name="weight"/>
|
||||
<field name="material_weight_kg" readonly="1"/>
|
||||
<field name="x_fc_default_lead_time_days"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Quality & Delivery" name="quality_delivery">
|
||||
@@ -324,6 +328,7 @@
|
||||
<field name="name"/>
|
||||
<field name="part_number"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="material_id" string="Material"/>
|
||||
<separator/>
|
||||
<filter string="Aluminium" name="material_aluminium" domain="[('substrate_material','=','aluminium')]"/>
|
||||
<filter string="Steel" name="material_steel" domain="[('substrate_material','=','steel')]"/>
|
||||
@@ -340,7 +345,8 @@
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
<group>
|
||||
<filter string="Customer" name="group_partner" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Material" name="group_material" context="{'group_by':'substrate_material'}"/>
|
||||
<filter string="Material" name="group_material" context="{'group_by':'material_id'}"/>
|
||||
<filter string="Material Category" name="group_material_category" context="{'group_by':'substrate_material'}"/>
|
||||
<filter string="Complexity" name="group_complexity" context="{'group_by':'complexity'}"/>
|
||||
</group>
|
||||
</search>
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Part of the Fusion Plating product family.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<record id="view_fp_part_material_list" model="ir.ui.view">
|
||||
<field name="name">fp.part.material.list</field>
|
||||
<field name="model">fp.part.material</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Materials" editable="bottom" decoration-muted="not active">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="category"/>
|
||||
<field name="density" string="Density (g/cm³)"/>
|
||||
<field name="notes" optional="show"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_fp_part_material_form" model="ir.ui.view">
|
||||
<field name="name">fp.part.material.form</field>
|
||||
<field name="model">fp.part.material</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Material">
|
||||
<sheet>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
|
||||
<div class="oe_title">
|
||||
<label for="name" string="Material"/>
|
||||
<h1><field name="name" placeholder="e.g. Aluminium 6061"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="category"/>
|
||||
<field name="density"/>
|
||||
<field name="sequence"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="notes" placeholder="Alloy spec, source, supplier note..."/>
|
||||
</group>
|
||||
</group>
|
||||
<div class="text-muted">
|
||||
Leave Density at 0 to use the category default
|
||||
(Aluminium 2.70, Steel 7.85, Stainless 8.00,
|
||||
Copper 8.96, Titanium 4.51 g/cm³).
|
||||
</div>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_fp_part_material_search" model="ir.ui.view">
|
||||
<field name="name">fp.part.material.search</field>
|
||||
<field name="model">fp.part.material</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="name"/>
|
||||
<field name="category"/>
|
||||
<separator/>
|
||||
<filter string="Aluminium" name="cat_aluminium" domain="[('category','=','aluminium')]"/>
|
||||
<filter string="Steel" name="cat_steel" domain="[('category','=','steel')]"/>
|
||||
<filter string="Stainless" name="cat_stainless" domain="[('category','=','stainless')]"/>
|
||||
<filter string="Copper" name="cat_copper" domain="[('category','=','copper')]"/>
|
||||
<filter string="Titanium" name="cat_titanium" domain="[('category','=','titanium')]"/>
|
||||
<filter string="Other" name="cat_other" domain="[('category','=','other')]"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
|
||||
<group>
|
||||
<filter string="Category" name="group_category" context="{'group_by':'category'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_fp_part_material" model="ir.actions.act_window">
|
||||
<field name="name">Materials</field>
|
||||
<field name="res_model">fp.part.material</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_fp_part_material_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">No materials yet</p>
|
||||
<p>Define the materials your shop processes. Each material
|
||||
picks a category (Aluminium, Steel, etc.) used for pricing
|
||||
rules and density-based weight calculations.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -251,7 +251,9 @@
|
||||
string="Effective Plating Area"
|
||||
readonly="1"/>
|
||||
<field name="thickness_requested"/>
|
||||
<field name="substrate_material"/>
|
||||
<field name="material_id"
|
||||
options="{'no_quick_create': True}"/>
|
||||
<field name="substrate_material" invisible="1"/>
|
||||
<field name="masking_zones"/>
|
||||
<field name="turnaround_days"/>
|
||||
</group>
|
||||
|
||||
@@ -123,8 +123,10 @@
|
||||
<field name="x_fc_process_variant_id" optional="show"
|
||||
string="Process"/>
|
||||
<field name="product_uom_qty" string="Qty"/>
|
||||
<field name="x_fc_part_deadline" optional="show"
|
||||
string="Part Deadline"/>
|
||||
<field name="x_fc_effective_part_deadline" optional="show"
|
||||
string="Effective Deadline"/>
|
||||
<field name="x_fc_part_deadline" optional="hide"
|
||||
string="Part Deadline Override"/>
|
||||
<field name="x_fc_rush_order" optional="hide"/>
|
||||
<field name="x_fc_job_number" optional="show"
|
||||
string="Job #"/>
|
||||
@@ -188,6 +190,16 @@
|
||||
<field name="x_fc_internal_deadline"/>
|
||||
<field name="commitment_date" string="Customer Deadline"/>
|
||||
<field name="x_fc_deadline_countdown" readonly="1"/>
|
||||
<label for="x_fc_order_completion_date"/>
|
||||
<div class="o_row">
|
||||
<field name="x_fc_order_completion_date"
|
||||
readonly="1" class="oe_inline"/>
|
||||
<span class="badge text-bg-danger ms-2"
|
||||
invisible="not x_fc_is_late_forecast">
|
||||
<i class="fa fa-exclamation-triangle me-1"/>Late
|
||||
</span>
|
||||
<field name="x_fc_is_late_forecast" invisible="1"/>
|
||||
</div>
|
||||
<field name="x_fc_is_blanket_order"/>
|
||||
<field name="x_fc_block_partial_shipments"/>
|
||||
</group>
|
||||
@@ -250,24 +262,25 @@
|
||||
widget="boolean_toggle"
|
||||
invisible="not x_fc_process_variant_id"
|
||||
optional="hide"/>
|
||||
<button name="action_customize_process" type="object"
|
||||
string="Customize" icon="fa-pencil-square-o"
|
||||
class="btn-link"
|
||||
invisible="not x_fc_process_variant_id"/>
|
||||
<field name="x_fc_thickness_id"
|
||||
options="{'no_create': True}"
|
||||
options="{'no_quick_create': True}"
|
||||
context="{'default_coating_config_id': x_fc_coating_config_id}"
|
||||
domain="[('coating_config_id', '=', x_fc_coating_config_id)]"
|
||||
invisible="not x_fc_coating_config_id"
|
||||
optional="show"/>
|
||||
<field name="x_fc_serial_ids"
|
||||
widget="many2many_tags"
|
||||
options="{'no_quick_create': False, 'color_field': 'state_color'}"
|
||||
domain="[('part_id', '=', x_fc_part_catalog_id)]"
|
||||
optional="show"/>
|
||||
<field name="x_fc_serial_count"
|
||||
string="# SN"
|
||||
string="Serial Count"
|
||||
optional="hide"/>
|
||||
<button name="action_open_serial_bulk_add" type="object"
|
||||
string="Bulk Add Serials" icon="fa-list-ol"
|
||||
class="btn-link"/>
|
||||
title="Bulk add serials"
|
||||
icon="fa-list-ol"
|
||||
class="btn-link"
|
||||
invisible="not x_fc_part_catalog_id or x_fc_serial_count > 0"/>
|
||||
<field name="x_fc_job_number" optional="show"/>
|
||||
<field name="x_fc_revision_pick_id"
|
||||
string="Revision"
|
||||
@@ -278,7 +291,14 @@
|
||||
readonly="1"
|
||||
optional="hide"/>
|
||||
<field name="x_fc_treatment_ids" widget="many2many_tags" optional="hide"/>
|
||||
<field name="x_fc_part_deadline" optional="hide"/>
|
||||
<field name="x_fc_part_deadline" string="Part Deadline Override" optional="hide"/>
|
||||
<field name="x_fc_part_deadline_offset_days" string="Days Offset" optional="hide"/>
|
||||
<field name="x_fc_effective_part_deadline" string="Effective Deadline"
|
||||
optional="show"
|
||||
readonly="1"/>
|
||||
<field name="x_fc_effective_internal_deadline" string="Shop Target"
|
||||
optional="hide"
|
||||
readonly="1"/>
|
||||
<field name="x_fc_wo_group_tag" optional="hide"/>
|
||||
<field name="x_fc_start_at_node_id" optional="hide"/>
|
||||
<field name="x_fc_is_one_off" optional="hide"/>
|
||||
@@ -294,7 +314,8 @@
|
||||
<field name="model">sale.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Sale Orders" decoration-info="state == 'draft'"
|
||||
decoration-muted="state == 'cancel'">
|
||||
decoration-muted="state == 'cancel'"
|
||||
decoration-danger="x_fc_is_late_forecast">
|
||||
<header>
|
||||
<button name="%(action_fp_direct_order_wizard)d"
|
||||
type="action"
|
||||
@@ -308,6 +329,8 @@
|
||||
<field name="x_fc_customer_job_number" optional="show"/>
|
||||
<field name="x_fc_internal_deadline" optional="show"/>
|
||||
<field name="commitment_date" string="Customer Deadline" optional="show"/>
|
||||
<field name="x_fc_order_completion_date" string="Completion" optional="show"/>
|
||||
<field name="x_fc_is_late_forecast" optional="hide" widget="boolean_toggle"/>
|
||||
<field name="x_fc_deadline_countdown" optional="show"/>
|
||||
<field name="x_fc_wo_completion" optional="show"/>
|
||||
<field name="x_fc_planned_start_date" optional="hide"/>
|
||||
@@ -484,6 +507,8 @@
|
||||
<separator/>
|
||||
<filter name="blanket_orders" string="Blanket Orders"
|
||||
domain="[('x_fc_is_blanket_order', '=', True)]"/>
|
||||
<filter name="late_forecast" string="Will Be Late"
|
||||
domain="[('x_fc_is_late_forecast', '=', True)]"/>
|
||||
<filter name="rush_lines" string="Has Rush Line"
|
||||
domain="[('order_line.x_fc_rush_order', '=', True)]"/>
|
||||
<filter name="overdue" string="Overdue"
|
||||
|
||||
Reference in New Issue
Block a user