This commit is contained in:
gsinghpal
2026-04-28 19:39:37 -04:00
parent 2d42b33d68
commit 13e300d90e
103 changed files with 4959 additions and 331 deletions

View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
"""19.0.12.5.0 — Backfill default_kind on existing recipe nodes.
The Page-2 audit (2026-04-28) showed that pre-Sub-12a recipe nodes
have NULL `default_kind` because the field was added later. The
recipe-side soft-gates (Sub 8 racking, Policy B contract review) fall
back to name-matching when the kind is missing, which means a
renamed step ("Hang on Bar" instead of "Racking") silently bypasses
the gate.
This migration walks `fusion.plating.process.node` rows with NULL
default_kind, resolves a sensible kind via the central
`fp_resolve_step_kind()` helper, and sets it.
It also walks `fp.job.step` rows whose `kind` is the legacy 'other'
placeholder and re-derives `kind` from `recipe_node_id.default_kind`
(after the node-side backfill above sets it). Non-other kinds are
left alone — operator may have set them deliberately.
Idempotent.
"""
import logging
from odoo.api import Environment
from odoo.addons.fusion_plating import fp_resolve_step_kind
_logger = logging.getLogger(__name__)
# Same mapping as in fp_job.py — keep them in sync.
_NODE_KIND_TO_STEP_KIND = {
'cleaning': 'wet',
'etch': 'wet',
'rinse': 'wet',
'plate': 'wet',
'dry': 'wet',
'wbf_test': 'wet',
'bake': 'bake',
'mask': 'mask',
'demask': 'mask',
'racking': 'rack',
'derack': 'rack',
'inspect': 'inspect',
'final_inspect': 'inspect',
'contract_review': 'other',
'gating': 'other',
'ship': 'other',
}
def migrate(cr, version):
env = Environment(cr, 1, {})
# ---- 1. Backfill default_kind on recipe nodes -----------------------
Node = env['fusion.plating.process.node']
blank = Node.search([
('default_kind', '=', False),
('node_type', 'in', ('operation', 'step')),
])
fixed = 0
for n in blank:
kind = fp_resolve_step_kind(n.name)
if kind:
n.default_kind = kind
fixed += 1
_logger.info(
'19.0.12.5.0: backfilled default_kind on %s/%s recipe nodes via '
'fp_resolve_step_kind.', fixed, len(blank),
)
# ---- 2. Re-derive fp.job.step.kind from recipe node default_kind ----
Step = env['fp.job.step']
other_steps = Step.search([
('kind', '=', 'other'),
('recipe_node_id', '!=', False),
('state', 'not in', ('done', 'cancelled')),
])
rederived = 0
for s in other_steps:
node_kind = (
s.recipe_node_id.default_kind
if 'default_kind' in s.recipe_node_id._fields else None
)
new_kind = _NODE_KIND_TO_STEP_KIND.get(node_kind) if node_kind else None
if new_kind and new_kind != 'other':
s.kind = new_kind
rederived += 1
_logger.info(
'19.0.12.5.0: re-derived kind on %s/%s in-flight job steps from '
'recipe node default_kind.', rederived, len(other_steps),
)