feat(promote-customer-spec): Phase E — final removal of coating + treatment
DELETED entirely (model + view + ACL + data file + menu): - fp.coating.config (configurator) - fp.treatment (configurator + seeded data) - fp.coating.thickness (configurator) — replaced by fp.recipe.thickness in Phase A - fp.customer.price.list (configurator) — coating-keyed, no replacement Field deletions: - sale.order.x_fc_coating_config_id - sale.order.line.x_fc_coating_config_id + x_fc_treatment_ids - account.move.line.x_fc_coating_config_id - fp.part.catalog.x_fc_default_coating_config_id + x_fc_default_treatment_ids - fp.job.coating_config_id - fp.pricing.rule.coating_config_id - fp.quality.point.coating_config_ids - fp.direct.order.line.coating_config_id + treatment_ids - fp.sale.description.template.coating_config_id Refactored: - fp.quote.configurator.coating_config_id → recipe_id (now points at fusion.plating.process.node, the actual recipe). All compute, onchange, and matcher logic updated to use recipe directly. Quality inherit extends matcher with spec-tier scoring. - fp.job._fp_create_certificates now reads spec from job.customer_spec_id and formats spec_reference as "code Rev rev". Same for thickness source — bake fields read from recipe_root (Phase A). - fp.job.step.button_finish bake-window auto-spawn reads bake settings from recipe_root instead of coating. - fp.certificate auto-fill spec_min_mils/max_mils from recipe (Phase A thickness fields) instead of coating. - jobs/sale_order.py: job creation reads x_fc_customer_spec_id from line, drops coating refs and the legacy header-coating fallback. - Wizards drop coating + treatment fields and refs. - Configurator views drop x_fc_coating_config_id + x_fc_treatment_ids fields entirely. Quality inherits re-anchor on stable fields (x_fc_part_catalog_id, x_fc_internal_description, default_process_id, process_variant_id, substrate_material) so they keep working. - Reports drop coating fallback elifs; print recipe / spec. - Tablet payload drops coating_config_id from job.read fields. Skipped (deferred to backlog): - fusion_plating_bridge_mrp — module is uninstalled per Sub 11; source files retain coating refs but no runtime impact. - fusion_plating_portal — circular dep (portal → quality → certs → portal). Customer-facing portal coating picker stays for now; promote-spec polish is a separate sub-project. Verification: grep for "coating_config_id|fp.coating.config| fp.treatment|fp.coating.thickness" in live (non-bridge_mrp, non-portal, non-script, non-test) Python/XML/CSV returns 3 hits, all in module / class docstrings explaining Phase E history. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -48,15 +48,12 @@ class FpJob(models.Model):
|
||||
string='Part',
|
||||
ondelete='restrict',
|
||||
)
|
||||
coating_config_id = fields.Many2one(
|
||||
'fp.coating.config',
|
||||
string='Coating Configuration',
|
||||
ondelete='restrict',
|
||||
)
|
||||
customer_spec_id = fields.Many2one(
|
||||
'fusion.plating.customer.spec',
|
||||
string='Customer Spec',
|
||||
string='Specification',
|
||||
ondelete='set null',
|
||||
help='Customer / industry spec the job ships under. Auto-filled '
|
||||
'from the SO line at job creation.',
|
||||
)
|
||||
portal_job_id = fields.Many2one(
|
||||
'fusion.plating.portal.job',
|
||||
@@ -996,29 +993,28 @@ class FpJob(models.Model):
|
||||
if node.estimated_duration:
|
||||
vals['dwell_time_minutes'] = node.estimated_duration
|
||||
|
||||
# Pull thickness target from the coating config when
|
||||
# this is a plating step (matched by node name keyword).
|
||||
coating = job.coating_config_id
|
||||
# Pull thickness target from the recipe root when this
|
||||
# is a plating step (matched by node name keyword).
|
||||
# Recipe-root carries thickness fields post-promote-spec.
|
||||
recipe_root = job.recipe_id
|
||||
name_l = (node.name or '').lower()
|
||||
is_plating_node = (
|
||||
'plat' in name_l or 'nickel' in name_l
|
||||
or 'chrome' in name_l or 'anodiz' in name_l
|
||||
)
|
||||
if coating and is_plating_node:
|
||||
if recipe_root and is_plating_node:
|
||||
if (
|
||||
'thickness_max' in coating._fields
|
||||
and coating.thickness_max
|
||||
'thickness_max' in recipe_root._fields
|
||||
and recipe_root.thickness_max
|
||||
):
|
||||
vals['thickness_target'] = coating.thickness_max
|
||||
vals['thickness_target'] = recipe_root.thickness_max
|
||||
if (
|
||||
'thickness_uom' in coating._fields
|
||||
and coating.thickness_uom
|
||||
'thickness_uom' in recipe_root._fields
|
||||
and recipe_root.thickness_uom
|
||||
):
|
||||
# fp.coating.config uses long-form uom names
|
||||
# (mils / microns / inches); fp.job.step uses
|
||||
# short codes (mil / um / inch). Map between
|
||||
# them. Unknown values fall through to the
|
||||
# step's default ('um').
|
||||
# Recipe uses long-form uom names (mils /
|
||||
# microns / inches); fp.job.step uses short
|
||||
# codes (mil / um / inch). Map between them.
|
||||
_UOM_MAP = {
|
||||
'mils': 'mil',
|
||||
'mil': 'mil',
|
||||
@@ -1029,7 +1025,7 @@ class FpJob(models.Model):
|
||||
'inch': 'inch',
|
||||
'in': 'inch',
|
||||
}
|
||||
mapped = _UOM_MAP.get(coating.thickness_uom)
|
||||
mapped = _UOM_MAP.get(recipe_root.thickness_uom)
|
||||
if mapped:
|
||||
vals['thickness_uom'] = mapped
|
||||
|
||||
@@ -1546,7 +1542,9 @@ class FpJob(models.Model):
|
||||
if not required:
|
||||
return
|
||||
has_job_link = 'x_fc_job_id' in Cert._fields
|
||||
coating = self.coating_config_id
|
||||
# Spec drives the cert spec_reference. The customer.spec was
|
||||
# auto-filled onto the job at confirm time (sale_order.py).
|
||||
spec = self.customer_spec_id
|
||||
for cert_type in sorted(required):
|
||||
# Idempotency per type.
|
||||
existing_dom = [('certificate_type', '=', cert_type)]
|
||||
@@ -1574,9 +1572,16 @@ class FpJob(models.Model):
|
||||
if 'sale_order_id' in Cert._fields and self.sale_order_id:
|
||||
vals['sale_order_id'] = self.sale_order_id.id
|
||||
# spec_reference is what action_issue blocks on.
|
||||
if coating and 'spec_reference' in Cert._fields \
|
||||
and getattr(coating, 'spec_reference', False):
|
||||
vals['spec_reference'] = coating.spec_reference
|
||||
# Format spec.code + revision for the cert text.
|
||||
if spec and 'spec_reference' in Cert._fields:
|
||||
ref = spec.code or ''
|
||||
if spec.revision:
|
||||
ref = (f'{ref} Rev {spec.revision}'
|
||||
if ref else f'Rev {spec.revision}')
|
||||
if ref:
|
||||
vals['spec_reference'] = ref
|
||||
if 'customer_spec_id' in Cert._fields:
|
||||
vals['customer_spec_id'] = spec.id
|
||||
if 'part_number' in Cert._fields and self.part_catalog_id:
|
||||
vals['part_number'] = (
|
||||
self.part_catalog_id.part_number or ''
|
||||
|
||||
Reference in New Issue
Block a user