feat(promote-customer-spec): Phase C — pricing, quality, job, cert re-keyed
Pricing:
- Quality inherit on fp.pricing.rule adds customer_spec_id + recipe_id
- Quality inherit on fp.quote.configurator adds customer_spec_id field
+ extends _find_matching_rule with priority chain:
spec (+8) > recipe (+6) > coating (+4) > material (+2) > cert (+1)
- View inherit surfaces both new pickers on the rule form
Quality points:
- fp.quality.point now has customer_spec_ids + recipe_ids M2M filters
- Matcher (_matches + _find_matching) accepts new args
- Hook overrides on SO confirm + job confirm/done + step finish
pass spec/recipe context through to the matcher
- View surfaces both new M2M widgets
Job:
- jobs/sale_order.py wires x_fc_customer_spec_id from SO line to
fp.job.customer_spec_id on action_confirm
Cert:
- Quality inherit on fp.certificate adds customer_spec_id field +
create() override auto-fills spec_reference from spec.code+revision
Resolution priority: explicit spec_reference > cert.customer_spec_id
> SO line spec (with print_on_cert) > legacy coating fallback
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
# Part of the Fusion Plating product family.
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class FpCertificate(models.Model):
|
||||
"""Add Specification linkage + auto-fill spec_reference from it.
|
||||
|
||||
Lives in fusion_plating_quality because customer.spec lives here.
|
||||
Quality already depends on certificates, so the inverse direction
|
||||
works.
|
||||
"""
|
||||
_inherit = 'fp.certificate'
|
||||
|
||||
customer_spec_id = fields.Many2one(
|
||||
'fusion.plating.customer.spec',
|
||||
string='Specification',
|
||||
help='Snapshot of the specification the cert was issued against. '
|
||||
'Drives the spec_reference printed on the CoC.',
|
||||
)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""Auto-fill spec_reference from the SO line's customer_spec_id.
|
||||
|
||||
Resolution order (first match wins):
|
||||
1. Explicit spec_reference passed in vals.
|
||||
2. customer_spec_id (this field) → format "code Rev rev".
|
||||
3. SO line x_fc_customer_spec_id (with print_on_cert=True).
|
||||
4. Existing legacy fall-back lives in the parent module
|
||||
(reads x_fc_coating_config_id.spec_reference). Untouched.
|
||||
"""
|
||||
SaleOrder = self.env['sale.order']
|
||||
for vals in vals_list:
|
||||
if vals.get('spec_reference'):
|
||||
continue
|
||||
spec = False
|
||||
# 2. Explicit spec on the cert.
|
||||
if vals.get('customer_spec_id'):
|
||||
spec = self.env['fusion.plating.customer.spec'].browse(
|
||||
vals['customer_spec_id'],
|
||||
).exists()
|
||||
# 3. SO line's spec.
|
||||
if not spec and vals.get('sale_order_id'):
|
||||
so = SaleOrder.browse(vals['sale_order_id'])
|
||||
if 'x_fc_customer_spec_id' in so.order_line._fields:
|
||||
spec = so.order_line.mapped(
|
||||
'x_fc_customer_spec_id',
|
||||
).filtered('print_on_cert')[:1]
|
||||
if spec and not vals.get('customer_spec_id'):
|
||||
vals['customer_spec_id'] = spec.id
|
||||
if spec:
|
||||
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
|
||||
return super().create(vals_list)
|
||||
Reference in New Issue
Block a user