Files
Odoo-Modules/fusion_plating/fusion_plating/views/fp_process_node_views.xml
gsinghpal 06dc6a62b9 feat(fusion_plating): long_running flag on process node (auto-pause opt-out)
Plan task P2.1. Boolean on fusion.plating.process.node that exempts
steps generated from this node from the shop-floor auto-pause cron
(added in P2.4/P2.5). Use for 24h bakes, multi-shift soaks, and
similar long-but-legitimate operations.

Toggle visible on the process-node form for operation/step types,
grouped with parallel_start in the Behaviour section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 22:01:13 -04:00

345 lines
19 KiB
XML

<?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>
<!-- ===== TREE (LIST) VIEW — Recipes only ===== -->
<record id="view_fp_process_node_tree" model="ir.ui.view">
<field name="name">fusion.plating.process.node.tree</field>
<field name="model">fusion.plating.process.node</field>
<field name="arch" type="xml">
<list string="Process Recipes" default_order="sequence, name">
<field name="sequence" widget="handle"/>
<field name="code" optional="show"/>
<field name="name"/>
<field name="node_type" widget="badge"
decoration-info="node_type == 'recipe'"
decoration-success="node_type == 'operation'"
decoration-warning="node_type == 'sub_process'"
decoration-muted="node_type == 'step'"/>
<field name="process_type_id" optional="show"/>
<field name="work_center_id" optional="show"/>
<field name="child_count" string="Steps"/>
<field name="version" optional="hide"/>
<field name="active" column_invisible="True"/>
</list>
</field>
</record>
<!-- ===== FORM VIEW ===== -->
<record id="view_fp_process_node_form" model="ir.ui.view">
<field name="name">fusion.plating.process.node.form</field>
<field name="model">fusion.plating.process.node</field>
<field name="arch" type="xml">
<form string="Process Node">
<header>
<button name="action_open_tree_editor" type="object"
string="Open Tree Editor" class="btn-primary"
icon="fa-sitemap"
invisible="node_type != 'recipe'"/>
<button name="action_open_simple_editor" type="object"
string="Open Simple Editor" class="btn-secondary"
icon="fa-list-ol"
invisible="node_type != 'recipe'"/>
</header>
<widget name="web_ribbon" title="LOCKED — Manager Edit Only"
bg_color="text-bg-warning"
invisible="not is_locked"/>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_open_tree_editor" type="object"
class="oe_stat_button" icon="fa-sitemap"
invisible="node_type != 'recipe'">
<field name="child_count" widget="statinfo"
string="Tree Editor"/>
</button>
<button name="action_open_simple_editor" type="object"
class="oe_stat_button" icon="fa-list-ol"
invisible="node_type != 'recipe'">
<div class="o_stat_info">
<span class="o_stat_text">Simple</span>
<span class="o_stat_text">Editor</span>
</div>
</button>
</div>
<widget name="web_ribbon" title="Archived"
bg_color="text-bg-danger"
invisible="active"/>
<div class="oe_title">
<h1>
<field name="name" placeholder="Node name..."/>
</h1>
</div>
<group>
<group string="Classification">
<field name="code"/>
<field name="node_type"/>
<field name="process_type_id"/>
<field name="work_center_id"/>
<field name="parent_id"/>
<field name="icon"/>
</group>
<group string="Behaviour">
<field name="sequence"/>
<field name="estimated_duration"/>
<field name="auto_complete"/>
<field name="customer_visible"/>
<field name="is_manual"/>
<field name="requires_signoff"/>
<field name="opt_in_out"/>
<field name="version"/>
<field name="active" invisible="True"/>
<!-- Sub 13 — per-step opt-out from sequential gate -->
<field name="parallel_start"
invisible="node_type not in ('operation', 'step')"
help="When the parent recipe is Sequential, ticking this lets the step start while earlier-sequence steps are still in progress."/>
<!-- Phase 2 tablet redesign — opt out of the
auto-pause cron for legitimately-long steps
(24h bakes, multi-shift soaks). -->
<field name="long_running"
invisible="node_type not in ('operation', 'step')"/>
<field name="requires_predecessor_done"
invisible="node_type not in ('operation', 'step')"
groups="fusion_plating.group_fusion_plating_supervisor"
help="LEGACY per-step gate. Only fires when the recipe is in Free-Flow mode (Enforce Sequential = False)."/>
</group>
</group>
<!-- Recipe-only metadata (lead time, product link,
contract review approvers). Hidden on
operation/step nodes since those values are
only meaningful at the recipe root. -->
<group string="Recipe Settings"
invisible="node_type != 'recipe'">
<group>
<field name="default_lead_time"
widget="float_time"/>
<field name="product_id"
options="{'no_create': True}"/>
<field name="preferred_editor"/>
<!-- Sub 13 — recipe-level enforcement toggle -->
<field name="enforce_sequential"
widget="boolean_toggle"
help="When ON (the default), every operation under this recipe waits for earlier-sequence steps to finish before it can start. Mark a specific step as Parallel Start to opt that one out."/>
</group>
<group>
<field name="contract_review_user_ids"
widget="many2many_tags"
options="{'no_create': True}"/>
<field name="is_template"
groups="fusion_plating.group_fusion_plating_supervisor"/>
</group>
</group>
<group>
<group string="Tracking">
<field name="create_date" string="Created"/>
<field name="create_uid" string="Created By"/>
<field name="write_date" string="Last Updated"/>
<field name="write_uid" string="Updated By"/>
</group>
</group>
<notebook>
<page string="Description" name="description">
<field name="description" widget="html"/>
</page>
<page string="Instruction Images"
name="instruction_images">
<p class="text-muted">
Photos and screenshots operators see while
running this step — masking patterns,
fixture orientation, annotated diagrams,
gauge readings. Drop one or many images
here; they appear on the shop-floor
step-detail panel and the Record Inputs
dialog.
</p>
<field name="instruction_attachment_ids"
widget="many2many_binary"
options="{'accepted_file_extensions': 'image/*'}"
nolabel="1"/>
</page>
<page string="Operator Inputs" name="inputs">
<group>
<field name="collect_measurements"
widget="boolean_toggle"
help="Master switch — when off, the operator wizard skips this step entirely."/>
</group>
<field name="input_ids">
<list editable="bottom">
<field name="sequence" widget="handle"/>
<field name="collect" widget="boolean_toggle"
string="Collect"/>
<field name="name"/>
<field name="input_type"/>
<field name="kind" optional="hide"/>
<field name="target_min" optional="hide"/>
<field name="target_max" optional="hide"/>
<field name="target_unit" optional="hide"/>
<field name="required"/>
<field name="hint"/>
<field name="selection_options"
invisible="input_type != 'selection'"/>
<field name="template_input_id" optional="hide"
string="From Library"/>
</list>
</field>
</page>
<page string="Child Steps" name="children">
<field name="child_ids">
<list default_order="sequence, name">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="node_type" widget="badge"/>
<field name="work_center_id"/>
<field name="estimated_duration"/>
<field name="child_count" string="Sub-Steps"/>
</list>
</field>
</page>
<page string="Step Authoring" name="step_authoring"
invisible="node_type not in ('step', 'operation')">
<group>
<group string="Stations">
<field name="tank_ids" widget="many2many_tags"/>
<field name="kind_id"
options="{'no_create_edit': false, 'no_quick_create': false}"/>
<field name="material_callout"/>
</group>
<group string="Flags">
<field name="requires_predecessor_done"/>
<field name="requires_rack_assignment"/>
<field name="requires_transition_form"/>
</group>
</group>
<group>
<group string="Time Target">
<field name="time_min_target"/>
<field name="time_max_target"/>
<field name="time_unit"/>
</group>
<group string="Temperature Target">
<field name="temp_min_target"/>
<field name="temp_max_target"/>
<field name="temp_unit"/>
</group>
</group>
<group>
<field name="voltage_target"/>
<field name="viscosity_target"/>
<field name="source_template_id" readonly="1"/>
</group>
</page>
<page string="Notes" name="notes">
<field name="notes" placeholder="Internal notes..."/>
</page>
<page string="Specification &amp; Bake"
name="spec_metadata"
invisible="node_type != 'recipe' or parent_id">
<group>
<group string="Spec Metadata">
<field name="phosphorus_level"/>
<field name="thickness_min"/>
<field name="thickness_max"/>
<field name="thickness_uom"/>
</group>
<group string="Bake Relief (AMS 2759/9)">
<field name="requires_bake_relief"/>
<field name="bake_window_hours"
invisible="not requires_bake_relief"/>
<field name="bake_temperature"
invisible="not requires_bake_relief"/>
<field name="bake_temperature_uom"
invisible="not requires_bake_relief"/>
<field name="bake_duration_hours"
invisible="not requires_bake_relief"/>
</group>
</group>
<group string="Change Control (NADCAP)">
<field name="is_locked" widget="boolean_toggle"
help="When ON, only managers can edit this recipe and its child operations / steps. Use for NADCAP-qualified processes."/>
</group>
<!-- Thickness Options group removed. The
fp.recipe.thickness picker model was
retired in favour of a single free-text
thickness range field on the SO line.
Recipe still carries thickness_min /
thickness_max above as documentation
of the recipe's capability range. -->
<!-- Applicable Specifications group is added
by fusion_plating_quality via an inherit
view (the field lives there too). -->
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ===== SEARCH VIEW ===== -->
<record id="view_fp_process_node_search" model="ir.ui.view">
<field name="name">fusion.plating.process.node.search</field>
<field name="model">fusion.plating.process.node</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="code"/>
<field name="process_type_id"/>
<field name="work_center_id"/>
<filter name="recipes_only" string="Recipes"
domain="[('node_type', '=', 'recipe')]"/>
<filter name="sub_processes" string="Sub-Processes"
domain="[('node_type', '=', 'sub_process')]"/>
<filter name="operations" string="Operations"
domain="[('node_type', '=', 'operation')]"/>
<separator/>
<filter name="archived" string="Archived"
domain="[('active', '=', False)]"/>
<filter name="group_type" string="Type"
context="{'group_by': 'node_type'}"/>
<filter name="group_process" string="Process Type"
context="{'group_by': 'process_type_id'}"/>
<filter name="group_wc" string="Work Centre"
context="{'group_by': 'work_center_id'}"/>
<!-- Part-scoped filters live in fusion_plating_configurator;
the part_catalog_id field is declared there (core
can't see it without a circular dep). -->
</search>
</field>
</record>
<!-- ===== WINDOW ACTION — Recipe list ===== -->
<!-- Domain only narrows by node_type in core. The configurator
module adds the part_catalog_id = False narrowing via a
view/action inherit (see fusion_plating_configurator). -->
<record id="action_fp_process_recipe" model="ir.actions.act_window">
<field name="name">Process Recipes</field>
<field name="res_model">fusion.plating.process.node</field>
<field name="view_mode">list,form</field>
<field name="domain">[('node_type', '=', 'recipe')]</field>
<field name="context">{'default_node_type': 'recipe', 'search_default_recipes_only': 1}</field>
<field name="search_view_id" ref="view_fp_process_node_search"/>
<field name="x_fc_pickable_landing" eval="True"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first process recipe
</p>
<p>
Recipes define the step-by-step process for plating parts.
Each recipe is a reusable template with nested operations
and sub-processes.
</p>
</field>
</record>
<!-- ===== CLIENT ACTION — OWL Tree Editor ===== -->
<record id="action_fp_recipe_tree_editor" model="ir.actions.client">
<field name="name">Recipe Tree Editor</field>
<field name="tag">fp_recipe_tree_editor</field>
</record>
</odoo>