6.0 KiB
FP Step Kind — User-Extensible Model
Date: 2026-05-04 Status: design + implementation
Problem
default_kind on fp.step.template is a hardcoded Selection of 24 entries. Users can't add new kinds (e.g. "Shot Peen", "Passivation"). The same Selection list is duplicated on fusion.plating.process.node. Default-input seeding (DEFAULT_INPUTS_BY_KIND) is also locked in Python — adding a new kind would require a code change + module update.
Solution
Convert default_kind from Selection → Many2one('fp.step.kind'). Move the default-input templates from a Python dict into seeded data records on a new fp.step.kind.default.input child model. Users add new kinds through the standard Odoo CRUD form.
Models
fp.step.kind
| Field | Type | Notes |
|---|---|---|
code |
Char, required, unique per company | Technical key (lowercase). Stable XML IDs use this. |
name |
Char, required, translated | UI label (e.g. "Cleaning") |
sequence |
Integer | Order in dropdown |
active |
Boolean default True | Archive instead of delete |
icon |
Selection (reuses 24-icon list from fp.process.node) |
Optional |
description |
Html | Optional ops note |
company_id |
Many2one res.company | Multi-co support |
default_input_ids |
One2many → fp.step.kind.default.input |
The seed list |
fp.step.kind.default.input
Same shape as fp.step.template.input: name, input_type, target_unit, sequence, required, hint, selection_options. Plus kind_id parent FK.
Field changes
fp.step.template
- add
kind_id = Many2one('fp.step.kind', ondelete='restrict', string='Step Kind')— user-facing input - change existing
default_kindfromSelection(...)todefault_kind = fields.Char(related='kind_id.code', store=True, readonly=True)— back-compat shim. Lets every legacynode.default_kind == 'cleaning'comparison keep working without touching 30+ sites. Stored=True so existing search domains (('default_kind', '=', 'foo')) still work.
fusion.plating.process.node
- Same: add
kind_id, convertdefault_kindtorelated='kind_id.code'stored Char.
fp.job.workflow.state.trigger_default_kinds
- No change in Phase 1. Stays a Char of comma-separated codes. The codes still match
kind_id.codeafter migration. Phase 2 deferred convert to m2m.
DEFAULT_INPUTS_BY_KIND
Removed from fp_step_template.py. Lives in seed data XML. action_seed_default_inputs reads tpl.kind_id.default_input_ids instead of the dict.
Migration 19.0.18.13.0/post-migrate.py
- SQL-read existing
default_kindtext values fromfp_step_templateandfusion_plating_process_nodeBEFORE Odoo recomputes the related field. - Build map
code → fp.step.kind.idfrom seeded records. - SQL UPDATE
kind_idper row. - Trigger recompute of stored related
default_kind(or leave — values are already there from step 1). - Log counts.
Why not drop default_kind entirely?
- Comma-CSV
trigger_default_kindson workflow state still searches it. - 30+ comparison sites and existing search domains in views.
- Stored related Char keeps it a single source of truth (m2o-derived) without a churn-PR through every dependent.
View changes
fp_step_template_views.xml— replace<field name="default_kind"/>with<field name="kind_id" options="{'no_create_edit': false, 'no_quick_create': false}"/>. Same for search filter andgroup_by="default_kind"→group_by="kind_id".fp_process_node_views.xml— same swap on the one occurrence.- New
fp_step_kind_views.xml— list/form/menu so admins can manage kinds. Form embedsdefault_input_idsas inline list.
Controller / JS changes
simple_recipe_controller.py:- Add
kind_id(id) andkind_name(label) to all step-payload responses. - Accept
kind_idint on_save_recipe/template-create endpoints. - Keep returning
default_kind(the code Char) for back-compat with deployed editor sessions until cache flushes.
- Add
simple_recipe_editor.js:- Replace the
<select>over selection options with a Many2one-style typeahead. Fetch list from new endpoint/fusion_plating/recipe/kindsreturning[{id, code, name, icon}]. - Submit
kind_id(int) instead ofdefault_kind(string).
- Replace the
simple_recipe_editor.xml:- Replace
<select t-model=".default_kind">block with a<select t-model=".kind_id">populated from fetched list, plus a "+ New kind…" link that opens a small inline form via/fusion_plating/recipe/kinds/create.
- Replace
ACLs (ir.model.access.csv)
access_fp_step_kind_operator,fp.step.kind.operator,model_fp_step_kind,group_fusion_plating_operator,1,0,0,0
access_fp_step_kind_supervisor,fp.step.kind.supervisor,model_fp_step_kind,group_fusion_plating_supervisor,1,1,1,0
access_fp_step_kind_manager,fp.step.kind.manager,model_fp_step_kind,group_fusion_plating_manager,1,1,1,1
access_fp_step_kind_default_input_* … same triplet
Manifest
- Bump
versionto19.0.18.13.0 - Add to
data:data/fp_step_kind_data.xml(BEFOREfp_step_template_data.xmlsince templates reference kinds)views/fp_step_kind_views.xml
Out of scope (Phase 2)
- Convert
trigger_default_kindsChar-CSV to m2m onfp.job.workflow.state - Remove DEFAULT_INPUTS_BY_KIND dict from migration scripts (one-shot dev scripts — no harm leaving)
- Migrate stored
default_kindChar to a non-stored related once all callers refactored
Test plan
odoo -d admin -u fusion_plating --stop-after-init(entech) — install + migration runs cleanly- UI smoke: open a step template, kind dropdown shows 24 seeded kinds, dropdown allows quick-create
- Create new kind "Passivation" with 3 default inputs → save → return to step template → "Seed defaults" button populates the 3 inputs
- Open recipe editor (simple): kind dropdown matches; existing recipes show correct kind label
- Run a step that's wired through workflow-state trigger (e.g. completion of a
receivingstep → state changes to "On Floor") to confirm CSV-trigger backwards compat still works