feat(simple-editor): node_type bug fix + inline library authoring + back nav
Bucket 1 — Generation bug fix
- post-migrate.py for 19.0.18.8.0 promotes flat 'step' children of
recipes to 'operation' so fp.job._generate_steps() picks them up.
Filter is narrow: only direct children of node_type='recipe' get
flipped, tree-editor sub-steps (parent.node_type='operation') are
untouched. Idempotent. Posts an audit chatter note on each affected
recipe.
- Simple Editor controller hardcodes node_type='operation' on insert
+ snapshot-import path so future recipes start correct.
Bucket 2 — Inline library authoring
- 6 new JSONRPC routes (/fp/simple_recipe/library/load + save +
seed_defaults + input/{add,write,remove}, /fp/simple_recipe/tank/list).
- + New Step button in the right pane opens an inline form with name /
kind / icon / instructions / stations / flags / prompts table.
- Pencil icon on each library row reopens the same form prefilled.
- Step Kind picker leads with 'Generic — no automatic behaviour'.
- 'Seed defaults from kind' calls action_seed_default_inputs server-side
for kinds that have curated default prompts.
Bucket 3 — Back nav
- '← Recipes' button in the header (or '← Part' when opened from
Process Composer) mirrors recipe_tree_editor.js, with
clearBreadcrumbs:true to avoid stack pollution.
Verified on entech: LGPS1104's 19 'step' children now show as
'operation', migration chatter note posted on the recipe, asset cache
busted.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
"""Post-migration for 19.0.18.8.0 — Simple Editor node_type fix.
|
||||
|
||||
Background
|
||||
----------
|
||||
The Simple Recipe Editor's controller used to insert library templates
|
||||
into a recipe with `node_type='step'` directly under the recipe root.
|
||||
But fp.job._generate_steps() (in fusion_plating_jobs/models/fp_job.py)
|
||||
only creates fp.job.step rows for nodes whose node_type is 'operation'.
|
||||
Top-level 'step' children of a recipe were silently skipped, meaning
|
||||
Simple-Editor recipes generated zero job steps — no traveller content,
|
||||
no shopfloor tablet entries, no CoC moves.
|
||||
|
||||
Fix
|
||||
---
|
||||
Promote every `step` node whose direct parent is a `recipe` to
|
||||
`node_type='operation'`. Tree-editor authored 'step' nodes (which sit
|
||||
under `operation` parents) are left untouched — the filter is on
|
||||
`parent.node_type='recipe'`.
|
||||
|
||||
Idempotent: a second run finds no `step` children of recipes and is
|
||||
a no-op. Posts a chatter note on each affected recipe so QA / clients
|
||||
have a paper trail.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
_AUDIT_BODY = (
|
||||
'<p><strong>Recipe migrated to v19.0.18.8.0 step layout.</strong></p>'
|
||||
'<p>Step nodes that were direct children of this recipe (Simple '
|
||||
'Editor authoring) have been promoted to operation nodes so they '
|
||||
'generate work-order steps correctly. No data was lost — only '
|
||||
'<code>node_type</code> changed.</p>'
|
||||
'<p>If this recipe was authored via the Tree Editor with explicit '
|
||||
'sub-process / operation hierarchy, this migration was a no-op '
|
||||
'for it.</p>'
|
||||
)
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
if not version:
|
||||
return
|
||||
from odoo.api import Environment, SUPERUSER_ID
|
||||
env = Environment(cr, SUPERUSER_ID, {})
|
||||
|
||||
# Find recipe ids whose direct children include any 'step' rows.
|
||||
# We need this list BEFORE we flip the rows so we can post chatter
|
||||
# afterwards.
|
||||
cr.execute("""
|
||||
SELECT DISTINCT parent.id
|
||||
FROM fusion_plating_process_node parent
|
||||
JOIN fusion_plating_process_node child
|
||||
ON child.parent_id = parent.id
|
||||
WHERE parent.node_type = 'recipe'
|
||||
AND child.node_type = 'step'
|
||||
""")
|
||||
affected_recipe_ids = [r[0] for r in cr.fetchall()]
|
||||
|
||||
if not affected_recipe_ids:
|
||||
_logger.info(
|
||||
"Sub Simple-Editor migration: no flat-step recipes found, "
|
||||
"nothing to do."
|
||||
)
|
||||
return
|
||||
|
||||
# Flip the node_type. Filter is intentionally narrow — only direct
|
||||
# children of a recipe get promoted. Tree-editor sub-step rows
|
||||
# (parent.node_type='operation') are untouched.
|
||||
cr.execute("""
|
||||
UPDATE fusion_plating_process_node child
|
||||
SET node_type = 'operation'
|
||||
WHERE child.node_type = 'step'
|
||||
AND child.parent_id IN (
|
||||
SELECT id
|
||||
FROM fusion_plating_process_node
|
||||
WHERE node_type = 'recipe'
|
||||
)
|
||||
""")
|
||||
flipped = cr.rowcount
|
||||
_logger.info(
|
||||
"Sub Simple-Editor migration: promoted %s step nodes to "
|
||||
"operation across %s recipes.",
|
||||
flipped, len(affected_recipe_ids),
|
||||
)
|
||||
|
||||
# Post a chatter note on each affected recipe (best-effort).
|
||||
Node = env['fusion.plating.process.node']
|
||||
for recipe in Node.browse(affected_recipe_ids):
|
||||
try:
|
||||
recipe.message_post(
|
||||
body=_AUDIT_BODY,
|
||||
message_type='notification',
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
except Exception as e:
|
||||
_logger.warning(
|
||||
"Failed to post audit note on recipe %s: %s",
|
||||
recipe.id, e,
|
||||
)
|
||||
Reference in New Issue
Block a user