Files
Odoo-Modules/fusion_plating/docs/superpowers/specs/2026-05-04-fp-step-kind-model.md
gsinghpal 586f05d567 chnages
2026-05-04 02:14:34 -04:00

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 SelectionMany2one('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_kind from Selection(...) to default_kind = fields.Char(related='kind_id.code', store=True, readonly=True) — back-compat shim. Lets every legacy node.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, convert default_kind to related='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.code after 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

  1. SQL-read existing default_kind text values from fp_step_template and fusion_plating_process_node BEFORE Odoo recomputes the related field.
  2. Build map code → fp.step.kind.id from seeded records.
  3. SQL UPDATE kind_id per row.
  4. Trigger recompute of stored related default_kind (or leave — values are already there from step 1).
  5. Log counts.

Why not drop default_kind entirely?

  • Comma-CSV trigger_default_kinds on 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 and group_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 embeds default_input_ids as inline list.

Controller / JS changes

  • simple_recipe_controller.py:
    • Add kind_id (id) and kind_name (label) to all step-payload responses.
    • Accept kind_id int on _save_recipe/template-create endpoints.
    • Keep returning default_kind (the code Char) for back-compat with deployed editor sessions until cache flushes.
  • simple_recipe_editor.js:
    • Replace the <select> over selection options with a Many2one-style typeahead. Fetch list from new endpoint /fusion_plating/recipe/kinds returning [{id, code, name, icon}].
    • Submit kind_id (int) instead of default_kind (string).
  • 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.

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 version to 19.0.18.13.0
  • Add to data:
    • data/fp_step_kind_data.xml (BEFORE fp_step_template_data.xml since templates reference kinds)
    • views/fp_step_kind_views.xml

Out of scope (Phase 2)

  • Convert trigger_default_kinds Char-CSV to m2m on fp.job.workflow.state
  • Remove DEFAULT_INPUTS_BY_KIND dict from migration scripts (one-shot dev scripts — no harm leaving)
  • Migrate stored default_kind Char to a non-stored related once all callers refactored

Test plan

  1. odoo -d admin -u fusion_plating --stop-after-init (entech) — install + migration runs cleanly
  2. UI smoke: open a step template, kind dropdown shows 24 seeded kinds, dropdown allows quick-create
  3. Create new kind "Passivation" with 3 default inputs → save → return to step template → "Seed defaults" button populates the 3 inputs
  4. Open recipe editor (simple): kind dropdown matches; existing recipes show correct kind label
  5. Run a step that's wired through workflow-state trigger (e.g. completion of a receiving step → state changes to "On Floor") to confirm CSV-trigger backwards compat still works