Spec for the upcoming Simple Recipe Editor refinement: - Fix node_type bug so Simple-Editor recipes generate job steps - Inline + New Step / pencil-edit library authoring with prompts - Back button + breadcrumb-aware navigation (mirrors tree editor) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 KiB
Simple Recipe Editor — Refinement (Bug Fix + Inline Library Authoring + Breadcrumbs)
Status: Design — pending implementation plan
Date: 2026-04-30
Modules touched: fusion_plating, fusion_plating_jobs
Versions to bump: fusion_plating 19.0.11.4.0 → 19.0.12.0.0 (migration), fusion_plating_jobs 19.0.7.x` (no schema change, optional)
Problem
Three issues, surfaced together while a customer was trying to author recipes using the Simple Editor:
-
Generation bug — Simple-Editor recipes produce zero job steps.
walk_node()infp_job.py:631only createsfp.job.steprows fornode.node_type == 'operation'. The Simple Editor inserts library templates withnode_type='step'directly under the recipe root (simple_recipe_controller.py:178). Top-level step children of a recipe fall through. Verified on entech:LGPS1104has 19 flat step rows under the recipe root —fp_jobhas 0 rows referencing it. Real downstream consequence: no traveller content, no shopfloor tablet queue entries, no CoC moves, nothing. The recipe is silently inert. -
Library authoring requires a menu trip. Users have to leave the Simple Editor, navigate to Configuration → Recipes & Steps → Step Library, create a template, configure prompts in a list view, then come back to the editor to drag it in. The template form is manager-grade (notebook with 4 tabs); it's not the right tool for a shop foreman who wants to capture a one-off step their facility does.
-
No way back from the Simple Editor. Click "Open Simple Editor" from the recipe form → full-screen client action with no back button, no breadcrumb. Operator has to use Chrome's back arrow to escape. The Tree Editor has had a custom "← Back to Recipes" button since 2026-04-22; the Simple Editor was never given one.
Goals
- Simple-Editor-authored recipes produce correct job steps end-to-end — WO traveller, shopfloor tablet, CoC, reports.
- A shop foreman can author a new library step (with prompts, kind, stations, instructions) without leaving the Simple Editor.
- A shop foreman can edit an existing library step without leaving the Simple Editor.
- Closing the Simple Editor returns to the recipe list (or part form, if opened from the Process Composer).
- Existing tree-editor recipes are untouched. Existing simple-editor recipes get migrated, with a chatter note explaining the change.
Non-goals
- No new step kinds. The existing 23-value
default_kindSelection stays as-is. Free-text custom kinds are explicitly out of scope — templates without a kind continue to behave as "Generic" (no auto- seeded prompts, no auto-gates), which is fine. - No change to the Tree Editor.
- No change to the manager-grade Step Library form view.
- No prompt-collection runtime behaviour change (
collect_measurements, per-inputcollect, etc. all keep working as today).
Bucket 1 — Generation bug fix
Migration (one-shot, fusion_plating 19.0.12.0.0/post-migrate.py)
-- Flip top-level step children of recipes → operation. Filter is
-- intentionally narrow: only nodes whose parent is a recipe root.
-- Tree-editor 'step' rows (which sit under operation parents) are
-- untouched.
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'
);
After the SQL runs, walk every distinct recipe_root_id whose children
were touched and post a chatter note:
"Recipe migrated to v19.0.12.0.0 step layout. 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
node_typechanged. If this recipe was already authored via the Tree Editor with explicit sub-process / operation hierarchy, this migration was a no-op for it."
Controller change (going forward)
simple_recipe_controller.py:178 —
new_vals = {
'parent_id': recipe.id,
'node_type': 'operation', # was 'step' — fix Bucket 1 bug
'sequence': target_seq,
}
_snapshot_step_into() (template/import path) gets the same fix on
line 295.
What "just works" after this
walk_node()finds operation nodes, createsfp.job.steprows.- WO traveller (
report_fp_job_traveller.xml) iteratesjob.step_ids— populated. - Shopfloor tablet
/fp/shopfloor/scanreturns the same step rows. - CoC chronological body uses
fp.job.step.moverows that get created on tablet operations against real step rows. - Quality-point matching (
fp.quality.point._matches) keys offstep.kind, which is mapped fromnode.default_kindin the same walk_node code path. Templates with no kind getstep.kind='other'— behaves like a generic step. No regression.
Verification checklist (manual, after deploy)
- Create a new job against
LGPS1104on entech. - Confirm
fp.job.step_idscontains 19 rows (or however many the recipe has). - Print the WO Traveller — every step listed.
- Open the operator tablet for that job — every step in My Queue.
- Walk one step start → finish on the tablet —
fp.job.step.moverow created. - Generate a chronological CoC against the closed job — body lists each step heading.
Bucket 2 — Inline library authoring in Simple Editor
UX
In the right-hand Step Library panel, above the search input:
┌──────────────────────────────┐
│ + New Step │
├──────────────────────────────┤
│ [Search… ] │
├──────────────────────────────┤
│ ⚙ Acid Dip ✎ │
│ 🔗 Adhesion Test ✎ │
│ ... │
└──────────────────────────────┘
- + New Step opens an inline form (replaces the library list while open, "Save" / "Cancel" return to list).
- Pencil ✎ next to each library row → same form, prefilled with the template's current values.
Inline form fields
Two-column grid:
NAME * KIND
[ ] [Generic — no automatic ▾]
ICON ALLOWED STATIONS
[⚙ Cog ▾] [tag1] [tag2] [+]
INSTRUCTIONS
[ ]
[ ]
[ ]
FLAGS
☐ Require QA Sign-off
☐ Require Predecessor Done
☐ Requires Rack Assignment
☐ Requires Transition Form
PROMPTS (Operation Measurements — what the operator records during this step)
┌───────┬──────────────────┬──────────┬─────┬─────┬────┬───┐
│Collect│ Prompt │ Type │ Min │ Max │Req │ × │
├───────┼──────────────────┼──────────┼─────┼─────┼────┼───┤
│ ☑ │ Actual Time │ Time(sec)│ │ │ │ × │
│ ☑ │ Bath ID │ Text │ │ │ │ × │
└───────┴──────────────────┴──────────┴─────┴─────┴────┴───┘
[+ Add prompt] [Seed defaults from kind]
[Save] [Cancel]
The PROMPTS table reuses the same column layout as the existing
per-recipe-step edit panel (simple_recipe_editor.xml:127-200). Same
input-type Selection (15 options), same min/max/req fields. Authors
get one consistent table whether they're editing a recipe step or a
library template.
The "Seed defaults from kind" button calls
action_seed_default_inputs() server-side and refreshes — gives the
shop foreman the same one-click seeding the manager form has.
Controller endpoints (new)
POST /fp/simple_recipe/library/load { template_id }
POST /fp/simple_recipe/library/save { template_id|null, vals } # create or update
POST /fp/simple_recipe/library/seed_defaults { template_id } # action_seed_default_inputs
POST /fp/simple_recipe/library/input/add { template_id, payload }
POST /fp/simple_recipe/library/input/write { input_id, payload }
POST /fp/simple_recipe/library/input/remove { input_id }
library/save does an upsert: if template_id is null, creates;
otherwise writes. Returns the full template payload (same shape as
library/load) so the OWL component can refresh state in one call.
The existing library/create, library/write, library/delete stay
for back-compat (they're called by no other code today, so we could
delete them, but cheap to leave).
Snapshot semantics (no change)
When the author saves a new template and then drags it into a recipe,
the existing _copy_inputs_from_template() (simple_recipe_controller.py:223)
copies all input_template_ids → recipe-step input_ids. Editing the
template later does NOT mutate recipes already built (Q4 = A locked
2026-04-27). This bucket changes nothing about that contract.
What's excluded from inline form (still requires manager form)
- Time/Temp/Voltage/Viscosity targets (Advanced tab) — rarely set by shop foreman, lots of pickers, would bloat the inline form. Stays on the manager form.
- Transition Form fields — Sub 12b feature, more compliance-heavy, needs the dedicated tab. Stays on the manager form.
- Common Audit Fields seeding — accessible via
action_add_common_audit_fieldson the manager form. Could be added to the inline form later if asked.
The pencil ✎ form has a small "Open in full editor" link in the
corner that does action.doAction({type:'ir.actions.act_window', res_model:'fp.step.template', res_id:tpl.id}) for the manager-only escape hatch.
Bucket 3 — Breadcrumb / Back navigation
Header layout (Simple Editor)
[← Back to Recipes] Recipe: LGPS1104 [Open in Tree Editor]
Logic (mirrors recipe_tree_editor.js:548)
onBackToList() {
const partId = this.props.action?.context?.part_id;
if (partId) {
this.action.doAction({
type: "ir.actions.act_window",
res_model: "fp.part.catalog",
res_id: partId,
views: [[false, "form"]],
target: "current",
}, { clearBreadcrumbs: true });
return;
}
this.action.doAction("fusion_plating.action_fp_process_recipe", {
clearBreadcrumbs: true,
});
}
clearBreadcrumbs: true is critical — without it, every part-form →
composer → editor → back leaves the intermediate pages on the breadcrumb
stack. Same battle-scar the Tree Editor learned from in 2026-04-22.
Bucket 4 — Downstream verification
No code expected. Manual checklist after Buckets 1–3 ship to entech:
- Job generated from LGPS1104 has 19 fp.job.step rows
- WO Traveller PDF lists every step
- Tablet "My Queue" lists every step on the operator with that job's work centre
- Step start → finish creates an
fp.job.step.moverow - Closed-job CoC body (chronological style) lists every step heading
- User-added templates (Blasting, Surface Activation, Nickel Strip — Steel Line, Nickel Strip (S-1), Air Dry) flow through correctly
- Templates without
default_kindflow through withfp.job.step.kind='other'and behave as plain steps (no auto-gates) - Existing tree-editor recipes still produce the same number of steps as before (no regression)
Risks + mitigations
| Risk | Mitigation |
|---|---|
| Migration touches a recipe authored by Tree Editor that happens to have a flat step under recipe root | Filter is parent_id IN (recipe ids). Tree-editor step rows have operation parents, not recipe. Verified zero false positives on entech (only Simple-Editor recipes have step children of recipe). |
| New job-step rows surface a Sub 12b "Requires Rack Assignment" or Sub 8 racking-inspection gate operator wasn't expecting | All such gates check requires_rack_assignment / default_kind=='racking'. User-added Blasting / Surface Activation templates have neither set, so they'll behave as plain operations. |
| Inline form lets a foreman delete a library template that's used in 30 recipes | library/delete is already soft-delete (sets active=False) when used. Inline form keeps the same behaviour. |
| Author edits a library template's prompts and expects existing recipes to update | They won't — snapshot semantics still apply. UX mitigation: on save, post a notification "Saved. Existing recipes using this step keep their old prompts; new drops will use the new prompts." |
| Migration runs twice | SQL is idempotent (only flips step → operation; second run finds no step children of recipes, no-op). Chatter note is gated on node_type change so won't double-post. |
Module versions
fusion_plating: bump to 19.0.12.0.0 (migration + controller change + OWL changes)fusion_plating_jobs: no version bump required, but worth a smoke test
Build order
- Migration
fusion_plating/migrations/19.0.12.0.0/post-migrate.py— flip + chatter - Controller — change
node_type='operation'in two places + add 6 newlibrary/*endpoints - OWL JS —
simple_recipe_editor.jsadds inline form state + handlers + back button - OWL XML —
simple_recipe_editor.xmladds inline form template + back button + pencil - SCSS — minimal; reuse existing classes from edit panel
- Bump
fusion_plating/__manifest__.pyversion - Deploy to entech, run verification checklist
Things explicitly NOT in this spec
- New step kinds (deferred — clients add templates as they go, kind stays optional)
- Tree Editor changes
- Step Library manager-grade form changes
- New report content
- New shopfloor tablet content
- Free-text custom kinds (rejected — would silently lose 4 functional behaviours)