# Backfill compliance data on existing records so the per-step audit # verifies the new gates against real data, not a fresh seed. env = env # noqa from collections import Counter # 1. Set chart_recorder_ref on every oven that doesn't have one ovens = env['fusion.plating.bake.oven'].search([]) n_ov = 0 for ov in ovens: if not ov.chart_recorder_ref: ov.sudo().chart_recorder_ref = f'CR-{ov.code or ov.id}-2026' n_ov += 1 print(f'1. ovens chart_recorder_ref backfilled: {n_ov}/{len(ovens)}') # 2. Backfill rack_id on existing rack/de-rack WOs WO = env['mrp.workorder'] all_wos = WO.search([]) test_rack = env['fusion.plating.rack'].search([], limit=1) if not test_rack: f = env['fusion.plating.facility'].search([], limit=1) test_rack = env['fusion.plating.rack'].sudo().create({ 'name': 'Standard Rack 1', 'code': 'RACK-1', 'facility_id': f.id if f else False, }) n_rk = 0 for wo in all_wos: if hasattr(wo, '_fp_classify_kind'): if wo._fp_classify_kind() == 'rack' and not wo.x_fc_rack_id: wo.sudo().x_fc_rack_id = test_rack.id n_rk += 1 print(f'2. rack WOs rack_id backfilled: {n_rk}') # 3. Backfill bake_temp + bake_duration_hours on existing bake WOs n_bk = 0 for wo in all_wos: if hasattr(wo, '_fp_classify_kind') and wo._fp_classify_kind() == 'bake': updates = {} if not wo.x_fc_bake_temp: updates['x_fc_bake_temp'] = 365.0 if not wo.x_fc_bake_duration_hours: updates['x_fc_bake_duration_hours'] = 4.0 if updates: wo.sudo().write(updates) n_bk += 1 print(f'3. bake WOs temp+duration backfilled: {n_bk}') # 4. Backfill masking_material on existing mask WOs n_mk = 0 for wo in all_wos: if hasattr(wo, '_fp_classify_kind') and wo._fp_classify_kind() == 'mask': if not wo.x_fc_masking_material: wo.sudo().x_fc_masking_material = 'tape' n_mk += 1 print(f'4. mask WOs masking_material backfilled: {n_mk}') # 5. Backfill thickness_target + dwell_time on existing wet plating WOs n_th = 0 for wo in all_wos: if hasattr(wo, '_fp_classify_kind') and wo._fp_classify_kind() == 'wet': # Only fill if name suggests a plating step (not pre-treat/rinse) name_l = (wo.name or '').lower() if 'plat' in name_l or 'nickel' in name_l: updates = {} if not wo.x_fc_thickness_target: updates['x_fc_thickness_target'] = 0.0005 # 0.5 mils if not wo.x_fc_dwell_time_minutes: updates['x_fc_dwell_time_minutes'] = 60.0 if updates: wo.sudo().write(updates) n_th += 1 print(f'5. plating WOs thickness/dwell backfilled: {n_th}') # 6. Clean up OLD inspection WOs that have bath/tank wrongly set # (legacy bug — earlier simulator pinned bath to "Post-plate Inspection" # because the old classifier matched 'plat' keyword. Fixed now.) n_cl = 0 for wo in all_wos: name_l = (wo.name or '').lower() if 'inspect' in name_l and (wo.x_fc_bath_id or wo.x_fc_tank_id): wo.sudo().write({'x_fc_bath_id': False, 'x_fc_tank_id': False}) n_cl += 1 print(f'6. legacy bath/tank cleared from inspection WOs: {n_cl}') # Verify classifier fix — re-classify all WOs and report kinds = Counter() mis_pi = [] for wo in all_wos: if hasattr(wo, '_fp_classify_kind'): k = wo._fp_classify_kind() kinds[k] += 1 if 'inspect' in (wo.name or '').lower() and k != 'inspect': mis_pi.append((wo.id, wo.name, k)) print(f'\\nclassifier results across {len(all_wos)} WOs: {dict(kinds)}') print(f'inspection WOs misclassified: {len(mis_pi)}') for tup in mis_pi[:5]: print(f' ✗ WO {tup[0]} "{tup[1]}" → {tup[2]} (should be inspect)') env.cr.commit() print('\\nBackfill committed.')