feat(fusion_plating): kind.area_kind drives Shop Floor column routing
Add required area_kind Selection to fp.step.kind so each kind self-declares which plant-view column its steps belong in. Replaces the hardcoded _STEP_KIND_TO_AREA dict (removed in fp_job_step.py in the follow-up commit). - New `blast` kind for the Blasting column (sequence=35) - 26 existing kind records seeded with area_kind in XML - Pre-migrate 19.0.21.2.0 seeds existing rows BEFORE NOT NULL hits the schema; also activates derack/demask/gating that were deactivated in 19.0.20.6.0 but are needed for the full taxonomy - Step Kind form + list views surface area_kind (badge + chip) - Step Kind search adds Group By Shop Floor Column - Simple Editor kind picker shows "Masking — Masking column" suffix so authors see the routing at pick time - Add Hot Water Porosity Test (A-15) + Final Inspection / Packaging templates (used by 7+3 recipe nodes that previously had no library entry) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
"""19.0.21.2.0 — Shop Floor live-step + kind taxonomy.
|
||||
|
||||
Seeds fp.step.kind.area_kind on existing kinds BEFORE the required
|
||||
NOT NULL constraint on the new field hits the schema. Also activates
|
||||
the three kinds (derack/demask/gating) that were deactivated in
|
||||
19.0.20.6.0 but are needed for the full area_kind taxonomy.
|
||||
|
||||
Idempotent: only fills NULL / inactive rows.
|
||||
|
||||
See docs/superpowers/specs/2026-05-24-shopfloor-live-step-fix-design.md.
|
||||
"""
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
KIND_TO_AREA = {
|
||||
'other': 'plating',
|
||||
'wet_process': 'plating',
|
||||
'receiving': 'receiving',
|
||||
'contract_review': 'receiving',
|
||||
'gating': 'receiving',
|
||||
'racking': 'racking',
|
||||
'derack': 'de_racking',
|
||||
'mask': 'masking',
|
||||
'demask': 'de_racking',
|
||||
'cleaning': 'plating',
|
||||
'electroclean': 'plating',
|
||||
'etch': 'plating',
|
||||
'rinse': 'plating',
|
||||
'strike': 'plating',
|
||||
'plate': 'plating',
|
||||
'replenishment': 'plating',
|
||||
'wbf_test': 'plating',
|
||||
'dry': 'plating',
|
||||
'bake': 'baking',
|
||||
'inspect': 'inspection',
|
||||
'final_inspect': 'inspection',
|
||||
'hardness_test': 'inspection',
|
||||
'adhesion_test': 'inspection',
|
||||
'salt_spray': 'inspection',
|
||||
'packaging': 'shipping',
|
||||
'ship': 'shipping',
|
||||
'blast': 'blasting',
|
||||
'bead_blast': 'blasting',
|
||||
'media_blast': 'blasting',
|
||||
}
|
||||
|
||||
|
||||
def migrate(cr, version):
|
||||
# Phase 1 — Pre-create the column NULL-permitting so we can seed it
|
||||
# BEFORE Odoo's schema sync tries to enforce NOT NULL.
|
||||
cr.execute(
|
||||
"ALTER TABLE fp_step_kind "
|
||||
"ADD COLUMN IF NOT EXISTS area_kind VARCHAR"
|
||||
)
|
||||
|
||||
# Phase 2 — Seed area_kind on existing kinds. Idempotent: only fills
|
||||
# NULLs, so re-running -u is safe.
|
||||
seeded = 0
|
||||
for code, area in KIND_TO_AREA.items():
|
||||
cr.execute(
|
||||
"UPDATE fp_step_kind SET area_kind = %s "
|
||||
"WHERE code = %s "
|
||||
"AND (area_kind IS NULL OR area_kind = '')",
|
||||
(area, code),
|
||||
)
|
||||
seeded += cr.rowcount
|
||||
_logger.info(
|
||||
'[live-step-fix] kind.area_kind seeded on %s known-code rows',
|
||||
seeded,
|
||||
)
|
||||
|
||||
# Phase 3 — Fallback: any user-created custom kinds not in our seed
|
||||
# map → 'plating'. Clears the NOT NULL constraint for any leftover.
|
||||
cr.execute(
|
||||
"UPDATE fp_step_kind SET area_kind = 'plating' "
|
||||
"WHERE area_kind IS NULL OR area_kind = ''"
|
||||
)
|
||||
if cr.rowcount:
|
||||
_logger.info(
|
||||
'[live-step-fix] %s unknown kinds defaulted to plating',
|
||||
cr.rowcount,
|
||||
)
|
||||
|
||||
# Phase 4 — Activate kinds we need for full coverage.
|
||||
activated = 0
|
||||
for code in ('derack', 'demask', 'gating'):
|
||||
cr.execute(
|
||||
"UPDATE fp_step_kind SET active = TRUE "
|
||||
"WHERE code = %s AND active = FALSE",
|
||||
(code,),
|
||||
)
|
||||
activated += cr.rowcount
|
||||
_logger.info(
|
||||
'[live-step-fix] %s kinds activated (derack/demask/gating)',
|
||||
activated,
|
||||
)
|
||||
Reference in New Issue
Block a user