Implements 2026-04-29-step-library-audit-design.md. Bumps fusion_plating to 19.0.18.7.0, fusion_plating_jobs to 19.0.8.12.0, fusion_plating_reports to 19.0.10.2.0. LIBRARY EXPANSION - 8 new Step Kinds: Receiving, Electroclean, Strike, Salt Spray, Adhesion Test, Hardness Test, Packaging, Tank Replenishment - 4 new input types: photo, multi_point_thickness, bath_chemistry_panel, ph - DEFAULT_INPUTS_BY_KIND rewritten to seed audit-grade prompts on every kind (bath IDs, photos, multi-point thickness, signatures, etc.) - + Common Audit Fields one-click button on the library template form - Default Operator Instructions relabel + alert callout PER-RECIPE CONFIGURABILITY - collect (Boolean) per recipe-step input prompt — opt out without delete - collect_measurements (Boolean) master switch on recipe step — when off, wizard skips entirely - template_input_id (Many2one) traceability link from recipe to library - Recipe-step backend form view exposes the new fields with handle drag, toggle, target range, and library-source column RUNTIME WIRING - Step input wizard filters node.input_ids to step_input AND collect=True; short-circuits on collect_measurements=False - New input types: photo (image widget + ir.attachment), multi-point thickness (5 readings + auto avg, skips empty cells), bath chemistry panel (pH/conc/temp/bath bundle), pH (0-14 numeric) - Composite values JSON-serialized into value_text; photo via attachment CoC REPORT - Filters captured prompts to collect=True only - Renders new input types with appropriate format MIGRATION (post-migrate.py for 19.0.18.7.0) - Backfills collect=True on recipe-step inputs - Backfills collect_measurements=True on recipe steps - Re-runs action_seed_default_inputs on every existing template (idempotent, preserves user edits) - Backfills template_input_id by name-matching against source library template (handles JSONB vs varchar name columns) SEED DATA - 8 example templates (one per new kind) in fp_step_template_data.xml with noupdate=1 BATTLE TEST - bt_step_library_audit.py: 29 assertions all PASS on entech OWL EDITOR EXTENSION DEFERRED - The simple recipe editor's per-step Instructions/Measurements expansions were not implemented in this pass; users configure via the backend recipe-step form. Track follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
"""Post-migration for 19.0.18.7.0 — Step Library audit expansion.
|
|
|
|
1. Default `collect=True` on all existing recipe-step inputs.
|
|
2. Default `collect_measurements=True` on all existing recipe steps.
|
|
3. Re-run action_seed_default_inputs on every existing template to
|
|
pull in the newly-added prompts (idempotent — skips rows whose
|
|
name is already present, so user edits survive).
|
|
4. Backfill template_input_id by name-matching against the linked
|
|
library template (best-effort).
|
|
"""
|
|
|
|
import logging
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
def migrate(cr, version):
|
|
if not version:
|
|
return
|
|
from odoo.api import Environment, SUPERUSER_ID
|
|
env = Environment(cr, SUPERUSER_ID, {})
|
|
|
|
# 1. Default collect=True on all recipe-step inputs that have NULL
|
|
cr.execute("""
|
|
UPDATE fusion_plating_process_node_input
|
|
SET collect = TRUE
|
|
WHERE collect IS NULL
|
|
""")
|
|
_logger.info(
|
|
"Backfilled collect=True on %s recipe-step inputs", cr.rowcount
|
|
)
|
|
|
|
# 2. Default collect_measurements=True on recipe steps with NULL
|
|
cr.execute("""
|
|
UPDATE fusion_plating_process_node
|
|
SET collect_measurements = TRUE
|
|
WHERE collect_measurements IS NULL
|
|
""")
|
|
_logger.info(
|
|
"Backfilled collect_measurements=True on %s recipe steps", cr.rowcount
|
|
)
|
|
|
|
# 3. Re-seed defaults on every existing template (idempotent)
|
|
Template = env['fp.step.template']
|
|
templates = Template.search([('default_kind', '!=', False)])
|
|
for tpl in templates:
|
|
try:
|
|
tpl.action_seed_default_inputs()
|
|
except Exception as e:
|
|
_logger.warning(
|
|
"Failed to re-seed defaults on template %s: %s", tpl.id, e
|
|
)
|
|
_logger.info("Re-seeded defaults on %s templates", len(templates))
|
|
|
|
# 4. Backfill template_input_id — name-match recipe-node inputs against
|
|
# their parent recipe's source library template.
|
|
# Note: fusion_plating_process_node_input.name is plain varchar;
|
|
# fp_step_template_input.name is translatable JSONB (use ->>'en_US').
|
|
cr.execute("""
|
|
SELECT ni.id, ni.name, n.source_template_id
|
|
FROM fusion_plating_process_node_input ni
|
|
JOIN fusion_plating_process_node n ON n.id = ni.node_id
|
|
WHERE ni.template_input_id IS NULL
|
|
AND n.source_template_id IS NOT NULL
|
|
""")
|
|
rows = cr.fetchall()
|
|
matched = 0
|
|
for ni_id, name, tpl_id in rows:
|
|
if not name:
|
|
continue
|
|
cr.execute("""
|
|
SELECT id FROM fp_step_template_input
|
|
WHERE template_id = %s
|
|
AND name->>'en_US' = %s
|
|
LIMIT 1
|
|
""", (tpl_id, name))
|
|
match = cr.fetchone()
|
|
if match:
|
|
cr.execute("""
|
|
UPDATE fusion_plating_process_node_input
|
|
SET template_input_id = %s WHERE id = %s
|
|
""", (match[0], ni_id))
|
|
matched += 1
|
|
_logger.info(
|
|
"Backfilled template_input_id on %s recipe-step inputs", matched
|
|
)
|