feat(sub12a): recipe form — buttons + is_template + Step Authoring tab
Process node form: - Header: keep 'Open Tree Editor' (primary, existing); add 'Open Simple Editor' (secondary). Both visible only for recipe-type nodes. - Recipe Settings group: add preferred_editor + is_template (the latter supervisor-only). - New 'Step Authoring' notebook page (visible for step/operation): Stations, default_kind, material_callout, predecessor/rack/transition flags, time/temp targets, voltage/viscosity, readonly source_template_id. Model: - New action_open_simple_editor (sibling of action_open_tree_editor). - New _resolve_preferred_editor() — per-recipe preferred_editor wins, 'auto' falls back to company.x_fc_default_recipe_editor, final fallback 'tree'. - New action_open_recipe_with_preferred_editor() — one-click route through the resolver. Reserved for menu-list / context-menu callers that want the simple-loving foreman path. Tree editor + every existing battle test path untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -544,6 +544,41 @@ class FpProcessNode(models.Model):
|
|||||||
'context': {'recipe_id': root.id},
|
'context': {'recipe_id': root.id},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def action_open_simple_editor(self):
|
||||||
|
"""Open the OWL Simple Recipe Editor for this recipe (Sub 12a)."""
|
||||||
|
self.ensure_one()
|
||||||
|
root = self if self.node_type == 'recipe' else self.recipe_root_id
|
||||||
|
return {
|
||||||
|
'type': 'ir.actions.client',
|
||||||
|
'tag': 'fp_simple_recipe_editor',
|
||||||
|
'name': f'Recipe — {root.name}',
|
||||||
|
'context': {'recipe_id': root.id},
|
||||||
|
}
|
||||||
|
|
||||||
|
def _resolve_preferred_editor(self):
|
||||||
|
"""Returns 'tree' or 'simple' for this recipe.
|
||||||
|
|
||||||
|
Per-recipe preferred_editor wins. 'auto' falls back to the
|
||||||
|
company-level default. 'tree' is the final fallback.
|
||||||
|
"""
|
||||||
|
self.ensure_one()
|
||||||
|
if self.preferred_editor in ('tree', 'simple'):
|
||||||
|
return self.preferred_editor
|
||||||
|
return self.env.company.x_fc_default_recipe_editor or 'tree'
|
||||||
|
|
||||||
|
def action_open_recipe_with_preferred_editor(self):
|
||||||
|
"""Routes to whichever editor the recipe (or company) prefers.
|
||||||
|
|
||||||
|
Used by menu actions / context-menu opens — gives the
|
||||||
|
simple-loving foreman a one-click path that respects their
|
||||||
|
preference without forcing a tree-loving engineer to pick
|
||||||
|
between two buttons every time.
|
||||||
|
"""
|
||||||
|
self.ensure_one()
|
||||||
|
if self._resolve_preferred_editor() == 'simple':
|
||||||
|
return self.action_open_simple_editor()
|
||||||
|
return self.action_open_tree_editor()
|
||||||
|
|
||||||
# ---- Copy (deep-duplicate) -----------------------------------------------
|
# ---- Copy (deep-duplicate) -----------------------------------------------
|
||||||
|
|
||||||
def copy(self, default=None):
|
def copy(self, default=None):
|
||||||
|
|||||||
@@ -40,6 +40,10 @@
|
|||||||
string="Open Tree Editor" class="btn-primary"
|
string="Open Tree Editor" class="btn-primary"
|
||||||
icon="fa-sitemap"
|
icon="fa-sitemap"
|
||||||
invisible="node_type != 'recipe'"/>
|
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>
|
</header>
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_button_box" name="button_box">
|
<div class="oe_button_box" name="button_box">
|
||||||
@@ -90,11 +94,14 @@
|
|||||||
widget="float_time"/>
|
widget="float_time"/>
|
||||||
<field name="product_id"
|
<field name="product_id"
|
||||||
options="{'no_create': True}"/>
|
options="{'no_create': True}"/>
|
||||||
|
<field name="preferred_editor"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="contract_review_user_ids"
|
<field name="contract_review_user_ids"
|
||||||
widget="many2many_tags"
|
widget="many2many_tags"
|
||||||
options="{'no_create': True}"/>
|
options="{'no_create': True}"/>
|
||||||
|
<field name="is_template"
|
||||||
|
groups="fusion_plating.group_fusion_plating_supervisor"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
@@ -135,6 +142,38 @@
|
|||||||
</list>
|
</list>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</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="default_kind"/>
|
||||||
|
<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">
|
<page string="Notes" name="notes">
|
||||||
<field name="notes" placeholder="Internal notes..."/>
|
<field name="notes" placeholder="Internal notes..."/>
|
||||||
</page>
|
</page>
|
||||||
|
|||||||
Reference in New Issue
Block a user