# -*- 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, )