chore(plating): de-dash shipped code + intake-neutral customer emails
Replace em-dashes and en-dashes with hyphens across 789 shipped source files (py/xml/js/scss) so the delivered module reads as human-written; em-dashes had become a recognizable AI-generated tell. Internal .md dev notes are excluded. The WO-sticker mojibake strippers keep their dash search targets (now written — / –). No logic changes: comments and display strings only; validated with py_compile + lxml parse. Rewrite the 7 customer notification emails to be intake-neutral (ship-in / drop-off / pickup) and repair-aware, and fix the Shipped email documents line (packing slip vs bill of lading; certificate only when issued). Subjects use a hyphen separator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Per-step compliance audit — walks every WO of the most recent MO
|
||||
"""Per-step compliance audit - walks every WO of the most recent MO
|
||||
and reports which compliance data points are captured vs missing,
|
||||
broken down by WO kind.
|
||||
|
||||
@@ -32,7 +32,7 @@ KIND_RULES = {
|
||||
('x_fc_oven_id', 'CRITICAL', 'Which oven'),
|
||||
('x_fc_bake_temp', 'CRITICAL', 'Setpoint temp (Nadcap req)'),
|
||||
('x_fc_bake_duration_hours','CRITICAL','Actual bake duration'),
|
||||
('chart_recorder_ref', 'CRITICAL', 'Chart-recorder ref on the OVEN — auditor demands the chart for the run'),
|
||||
('chart_recorder_ref', 'CRITICAL', 'Chart-recorder ref on the OVEN - auditor demands the chart for the run'),
|
||||
('duration', 'CRITICAL', 'WO timer duration'),
|
||||
('x_fc_started_by_user_id','IMPORTANT','Who started'),
|
||||
('x_fc_finished_by_user_id','IMPORTANT','Who finished'),
|
||||
@@ -40,7 +40,7 @@ KIND_RULES = {
|
||||
'mask': [
|
||||
('x_fc_assigned_user_id', 'CRITICAL', 'Operator'),
|
||||
('duration', 'CRITICAL', 'Run time'),
|
||||
('masking_material', 'IMPORTANT','Which material — needed for stripping later'),
|
||||
('masking_material', 'IMPORTANT','Which material - needed for stripping later'),
|
||||
('x_fc_started_by_user_id','IMPORTANT','Who started'),
|
||||
('x_fc_finished_by_user_id','IMPORTANT','Who finished'),
|
||||
],
|
||||
@@ -72,7 +72,7 @@ def check_field(wo, field):
|
||||
if field == 'bath_log_during_window':
|
||||
# Look for any bath log on this WO's bath, between start+finish
|
||||
if not wo.x_fc_bath_id or not wo.x_fc_started_at or not wo.x_fc_finished_at:
|
||||
return ('—', False, 'no log searchable')
|
||||
return ('-', False, 'no log searchable')
|
||||
Log = env['fusion.plating.bath.log']
|
||||
n = Log.search_count([
|
||||
('bath_id', '=', wo.x_fc_bath_id.id),
|
||||
@@ -82,11 +82,11 @@ def check_field(wo, field):
|
||||
return (f'{n} log(s)', n > 0, '')
|
||||
if field == 'chart_recorder_ref':
|
||||
ref = wo.x_fc_oven_id.chart_recorder_ref if wo.x_fc_oven_id else False
|
||||
return (ref or '—', bool(ref), 'on oven')
|
||||
return (ref or '-', bool(ref), 'on oven')
|
||||
if field == 'masking_material':
|
||||
val = wo.x_fc_masking_material if 'x_fc_masking_material' in wo._fields else False
|
||||
if not val:
|
||||
return ('—', False, '')
|
||||
return ('-', False, '')
|
||||
label = dict(wo._fields['x_fc_masking_material'].selection).get(val, val)
|
||||
return (label, True, '')
|
||||
if field == 'thickness_readings':
|
||||
@@ -99,7 +99,7 @@ def check_field(wo, field):
|
||||
('production_id', '=', wo.production_id.id),
|
||||
])
|
||||
if not rs:
|
||||
return ('—', False, 'no readings')
|
||||
return ('-', False, 'no readings')
|
||||
n_with = sum(1 for r in rs if r.calibration_std_ref)
|
||||
return (f'{n_with}/{len(rs)} have cal std', n_with == len(rs), '')
|
||||
if field == 'gauge_serial':
|
||||
@@ -107,14 +107,14 @@ def check_field(wo, field):
|
||||
r = env['fp.thickness.reading'].search(
|
||||
[('production_id', '=', wo.production_id.id)], limit=1)
|
||||
if not r:
|
||||
return ('—', False, 'no readings')
|
||||
return (r.equipment_model or '—', bool(r.equipment_model), 'from reading.equipment_model')
|
||||
return ('-', False, 'no readings')
|
||||
return (r.equipment_model or '-', bool(r.equipment_model), 'from reading.equipment_model')
|
||||
# Direct field on WO
|
||||
val = getattr(wo, field, False) if field in wo._fields else None
|
||||
if val is None:
|
||||
return ('(field n/a)', False, '')
|
||||
if hasattr(val, '_name'):
|
||||
label = val.display_name if val else '—'
|
||||
label = val.display_name if val else '-'
|
||||
return (label, bool(val.ids), '')
|
||||
if isinstance(val, (int, float)):
|
||||
return (str(val), val > 0, '')
|
||||
@@ -158,7 +158,7 @@ for wo in mo.workorder_ids.sorted('sequence'):
|
||||
print(ln)
|
||||
|
||||
# =====================================================================
|
||||
banner('SUMMARY — gaps per WO kind across this MO')
|
||||
banner('SUMMARY - gaps per WO kind across this MO')
|
||||
# =====================================================================
|
||||
|
||||
for kind, gaps in PER_KIND.items():
|
||||
@@ -169,7 +169,7 @@ for kind, gaps in PER_KIND.items():
|
||||
print(f' × {field:<30} missing in {n} WO(s)')
|
||||
|
||||
print(f'\n Totals: {GAP_TOTALS["CRITICAL"]} CRITICAL gaps, {GAP_TOTALS["IMPORTANT"]} IMPORTANT gaps')
|
||||
print('\n Note: "missing" doesn\'t always mean "broken" — some fields')
|
||||
print('\n Note: "missing" doesn\'t always mean "broken" - some fields')
|
||||
print(' are optional today but should be required for stricter')
|
||||
print(' AS9100 / Nadcap compliance. See the per-kind list to')
|
||||
print(' decide which are real bugs vs roadmap items.')
|
||||
|
||||
Reference in New Issue
Block a user