changes
This commit is contained in:
@@ -27,7 +27,32 @@ def post_init_hook(env):
|
||||
_seed_default_timezone(env)
|
||||
_backfill_node_input_kind(env)
|
||||
_seed_step_library_if_empty(env)
|
||||
_backfill_contract_review_template(env)
|
||||
_seed_rack_tags_if_empty(env)
|
||||
_migrate_legacy_uom_columns(env)
|
||||
|
||||
|
||||
def _backfill_contract_review_template(env):
|
||||
"""Idempotent — ensure the Contract Review library template exists.
|
||||
|
||||
`_seed_step_library_if_empty` only fires on a fresh DB; existing DBs
|
||||
upgraded from pre-Policy-B versions still have a populated library
|
||||
minus the Contract Review entry. This function fills that hole.
|
||||
Re-running it is a no-op once the template exists.
|
||||
"""
|
||||
Tpl = env['fp.step.template']
|
||||
if Tpl.search([('default_kind', '=', 'contract_review')], limit=1):
|
||||
return # already there
|
||||
tpl = Tpl.create({
|
||||
'name': 'Contract Review',
|
||||
'default_kind': 'contract_review',
|
||||
})
|
||||
tpl.action_seed_default_inputs()
|
||||
_logger.info(
|
||||
"Fusion Plating: backfilled Contract Review library template "
|
||||
"(id=%s, %s default inputs).",
|
||||
tpl.id, len(tpl.input_template_ids),
|
||||
)
|
||||
|
||||
|
||||
def _seed_default_timezone(env):
|
||||
@@ -60,6 +85,12 @@ def _backfill_node_input_kind(env):
|
||||
# Mapping of recipe-step name → default_kind. Drives sane-default
|
||||
# input seeding on the starter library entries.
|
||||
_STARTER_KIND_BY_NAME = {
|
||||
# Policy B (2026-04-28) — recipe-side Contract Review step.
|
||||
# When an author drops this template into a recipe, fp.job.step.button_*
|
||||
# hooks in fusion_plating_jobs detect the kind=='contract_review' and
|
||||
# auto-open / gate the QA-005 audit form (fp.contract.review).
|
||||
'contract review': 'contract_review',
|
||||
'qa-005': 'contract_review',
|
||||
'soak clean': 'cleaning',
|
||||
'electroclean': 'cleaning',
|
||||
'solvent clean': 'cleaning',
|
||||
@@ -73,23 +104,85 @@ _STARTER_KIND_BY_NAME = {
|
||||
'zincate': 'etch',
|
||||
'strip zincate': 'etch',
|
||||
'acid dip': 'etch',
|
||||
'hcl activation': 'etch',
|
||||
'water break test': 'wbf_test',
|
||||
'water break free test': 'wbf_test',
|
||||
'issue panels': 'mask',
|
||||
'masking': 'mask',
|
||||
'mask': 'mask',
|
||||
'racking': 'racking',
|
||||
'rack': 'racking',
|
||||
'e-nickel plate': 'plate',
|
||||
'e-nickel plating': 'plate',
|
||||
'electroless nickel plate': 'plate',
|
||||
'electroless nickel plating': 'plate',
|
||||
'enp': 'plate',
|
||||
'plate': 'plate',
|
||||
'plating': 'plate',
|
||||
'drying': 'dry',
|
||||
'dry': 'dry',
|
||||
'bake': 'bake',
|
||||
'oven baking': 'bake',
|
||||
'oven bake': 'bake',
|
||||
'baking': 'bake',
|
||||
'hydrogen embrittlement bake': 'bake',
|
||||
'he bake': 'bake',
|
||||
'de-rack': 'derack',
|
||||
'de-racking': 'derack',
|
||||
'deracking': 'derack',
|
||||
'derack': 'derack',
|
||||
'demask': 'demask',
|
||||
'de-mask': 'demask',
|
||||
'de-masking': 'demask',
|
||||
'demasking': 'demask',
|
||||
'inspection': 'inspect',
|
||||
'incoming inspection': 'inspect',
|
||||
'post-plate inspection': 'inspect',
|
||||
'post plate inspection': 'inspect',
|
||||
'visual inspection': 'inspect',
|
||||
'porosity test': 'inspect',
|
||||
'adhesion test': 'inspect',
|
||||
'final inspection': 'final_inspect',
|
||||
'final inspection / packaging': 'final_inspect',
|
||||
'shipping': 'ship',
|
||||
'pack': 'ship',
|
||||
'packaging': 'ship',
|
||||
# Gating steps (Steelhead-style "Ready for X" intermediate states).
|
||||
'ready for incoming inspection': 'gating',
|
||||
'ready for plating': 'gating',
|
||||
'ready for racking': 'gating',
|
||||
'ready for de-masking': 'gating',
|
||||
'ready for demasking': 'gating',
|
||||
'ready for masking': 'gating',
|
||||
'ready for bake': 'gating',
|
||||
'ready for deracking': 'gating',
|
||||
'ready for de-racking': 'gating',
|
||||
'ready for post plate inspection': 'gating',
|
||||
'ready for post-plate inspection': 'gating',
|
||||
'ready for final inspection': 'gating',
|
||||
'ready for shipping': 'gating',
|
||||
}
|
||||
|
||||
|
||||
def fp_resolve_step_kind(name):
|
||||
"""Resolve a step name to a default_kind, tolerant of whitespace and
|
||||
case. Used by both the seeder and the migration backfill so we don't
|
||||
have two slightly-different lookup paths.
|
||||
|
||||
Returns the kind str or None when no match.
|
||||
"""
|
||||
if not name:
|
||||
return None
|
||||
key = name.strip().lower()
|
||||
if key in _STARTER_KIND_BY_NAME:
|
||||
return _STARTER_KIND_BY_NAME[key]
|
||||
# Gating "Ready for / Ready For" prefix — anything starting with that
|
||||
# is a gating node regardless of the destination step name.
|
||||
if key.startswith('ready for ') or key.startswith('ready '):
|
||||
return 'gating'
|
||||
return None
|
||||
|
||||
|
||||
def _seed_step_library_if_empty(env):
|
||||
"""Sub 12a — seed fp.step.template starter library.
|
||||
|
||||
@@ -135,7 +228,7 @@ def _create_template_from_node(env, node, seen):
|
||||
return
|
||||
seen.add(node.name.lower())
|
||||
|
||||
kind = _STARTER_KIND_BY_NAME.get(node.name.lower())
|
||||
kind = fp_resolve_step_kind(node.name)
|
||||
vals = {
|
||||
'name': node.name,
|
||||
'description': node.description or False,
|
||||
@@ -164,6 +257,7 @@ def _seed_minimal_library(env):
|
||||
"""Hard-coded minimal seed when ENP-ALUM-BASIC isn't on the target DB."""
|
||||
Tpl = env['fp.step.template']
|
||||
minimal = [
|
||||
('Contract Review', 'contract_review'),
|
||||
('Soak Clean', 'cleaning'),
|
||||
('Electroclean', 'cleaning'),
|
||||
('Rinse', 'rinse'),
|
||||
@@ -189,6 +283,38 @@ def _seed_minimal_library(env):
|
||||
)
|
||||
|
||||
|
||||
def _migrate_legacy_uom_columns(env):
|
||||
"""Translate every free-text UoM column in the plating suite into the
|
||||
new curated Selection keys.
|
||||
|
||||
Runs unconditionally on every fusion_plating upgrade so the day a
|
||||
downstream module's migration converts a Char to Selection, the data
|
||||
follows. Each call is a no-op when:
|
||||
* the column already holds selection keys (identity mapping)
|
||||
* the table doesn't exist (module not installed on this DB)
|
||||
"""
|
||||
from .models._fp_uom_selection import fp_migrate_uom_column
|
||||
|
||||
targets = [
|
||||
# core
|
||||
('fusion_plating_bath_parameter', 'uom', 'bath parameter'),
|
||||
('fusion_plating_process_node_input', 'uom', 'process node input'),
|
||||
('fusion_plating_process_node_input', 'target_unit', 'process node target'),
|
||||
('fp_step_template_input', 'target_unit', 'step template input target'),
|
||||
# compliance
|
||||
('fusion_plating_discharge_limit', 'uom', 'discharge limit'),
|
||||
('fusion_plating_discharge_sample_line', 'uom', 'discharge sample line'),
|
||||
('fusion_plating_waste_manifest', 'uom', 'waste manifest'),
|
||||
('fusion_plating_waste_stream', 'generation_uom', 'waste stream'),
|
||||
('fusion_plating_spill_register', 'uom', 'spill register'),
|
||||
# safety
|
||||
('fusion_plating_chemical', 'container_uom', 'chemical container'),
|
||||
('fusion_plating_exposure_monitoring', 'uom', 'exposure monitoring'),
|
||||
]
|
||||
for table, column, label in targets:
|
||||
fp_migrate_uom_column(env, table, column, label)
|
||||
|
||||
|
||||
def _seed_rack_tags_if_empty(env):
|
||||
"""Sub 12b — seed 4 starter rack tags."""
|
||||
Tag = env['fp.rack.tag']
|
||||
|
||||
Reference in New Issue
Block a user