fix(plating): CoC signer follows Settings "Certificate Owner" (no stale freeze)
Changing Settings -> Certificate Owner didn't move existing certs: the signer was snapshotted from the company owner at cert-creation time, and the CoC prefers that snapshot over the live owner. - _fp_create_certificates no longer freezes the company owner into certified_by_id; it snapshots ONLY a deliberate per-spec signer. Empty certified_by_id then resolves the LIVE company owner in the CoC report. - action_issue lazy-fill made robust: resolves the company via the SO / env.company (fp.certificate has no company_id) so it fills the CURRENT owner at issue and the "Certified By" gate still passes. - Settings help text corrected: signature comes from the user's Plating Signature (Preferences -> My Profile), not "HR Employee". - Data fix on entech: cleared certified_by_id on 5 stale draft CoCs with no per-spec signer so they follow the current owner. Bump certificates 19.0.9.3.0, jobs 19.0.11.4.0. Verified: CoC-30058 resolves signer = Garry Singh (has Plating Signature), renders clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Fusion Plating — Certificates',
|
'name': 'Fusion Plating — Certificates',
|
||||||
'version': '19.0.9.2.0',
|
'version': '19.0.9.3.0',
|
||||||
'category': 'Manufacturing/Plating',
|
'category': 'Manufacturing/Plating',
|
||||||
'summary': 'Certificate registry for CoC, thickness reports, and quality documents.',
|
'summary': 'Certificate registry for CoC, thickness reports, and quality documents.',
|
||||||
'description': """
|
'description': """
|
||||||
|
|||||||
@@ -485,17 +485,28 @@ class FpCertificate(models.Model):
|
|||||||
rec.contact_partner_id = (
|
rec.contact_partner_id = (
|
||||||
rec.partner_id.x_fc_default_coc_contact_id
|
rec.partner_id.x_fc_default_coc_contact_id
|
||||||
)
|
)
|
||||||
# Guard with field-existence check — fp.certificate doesn't
|
# Lazy-fill the signer from the LIVE company owner (Settings
|
||||||
# declare company_id directly; production picks it up from
|
# "Certificate Owner") when no per-cert / per-spec signer was
|
||||||
# auto-creation context but tests can build a cert without
|
# chosen. As of 2026-05-28 the cert no longer freezes the
|
||||||
# one. Without the guard, AttributeError on the .company_id
|
# company owner at creation, so certified_by_id is empty in
|
||||||
# access bubbles up as a test error.
|
# the common case and this fill is what locks the signer at
|
||||||
if (not rec.certified_by_id
|
# issue. fp.certificate doesn't declare company_id directly,
|
||||||
and 'company_id' in rec._fields
|
# so resolve the company from the SO (then env.company) the
|
||||||
and rec.company_id
|
# same way the CoC report does — otherwise this fill is
|
||||||
and 'x_fc_owner_user_id' in rec.company_id._fields
|
# skipped and the "Certified By is not set" gate below would
|
||||||
and rec.company_id.x_fc_owner_user_id):
|
# block issuance.
|
||||||
rec.certified_by_id = rec.company_id.x_fc_owner_user_id
|
if not rec.certified_by_id:
|
||||||
|
company = (
|
||||||
|
(rec.company_id
|
||||||
|
if 'company_id' in rec._fields and rec.company_id
|
||||||
|
else False)
|
||||||
|
or (rec.sale_order_id.company_id
|
||||||
|
if rec.sale_order_id else False)
|
||||||
|
or rec.env.company
|
||||||
|
)
|
||||||
|
if (company and 'x_fc_owner_user_id' in company._fields
|
||||||
|
and company.x_fc_owner_user_id):
|
||||||
|
rec.certified_by_id = company.x_fc_owner_user_id
|
||||||
# Spec Reference is OPTIONAL (client request 2026-05-28).
|
# Spec Reference is OPTIONAL (client request 2026-05-28).
|
||||||
# The customer-facing description now serves as the cert's
|
# The customer-facing description now serves as the cert's
|
||||||
# spec / certificate information (see
|
# spec / certificate information (see
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
help="Branding, accreditation logos, and default signer for Certificates of Conformance.">
|
help="Branding, accreditation logos, and default signer for Certificates of Conformance.">
|
||||||
<setting id="fp_coc_owner"
|
<setting id="fp_coc_owner"
|
||||||
string="Certificate Owner (Default Signer)"
|
string="Certificate Owner (Default Signer)"
|
||||||
help="Their HR Employee signature appears on issued certificates by default.">
|
help="Signs every CoC that has no per-spec or per-cert signer. Their Plating Signature (Preferences → My Profile) is printed. Changing this flows through to draft certificates.">
|
||||||
<field name="x_fc_owner_user_id"
|
<field name="x_fc_owner_user_id"
|
||||||
options="{'no_create': True, 'no_open': True}"/>
|
options="{'no_create': True, 'no_open': True}"/>
|
||||||
</setting>
|
</setting>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||||
{
|
{
|
||||||
'name': 'Fusion Plating — Native Jobs',
|
'name': 'Fusion Plating — Native Jobs',
|
||||||
'version': '19.0.11.3.0',
|
'version': '19.0.11.4.0',
|
||||||
'category': 'Manufacturing/Plating',
|
'category': 'Manufacturing/Plating',
|
||||||
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
|
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
|
||||||
'author': 'Nexa Systems Inc.',
|
'author': 'Nexa Systems Inc.',
|
||||||
|
|||||||
@@ -2572,8 +2572,10 @@ class FpJob(models.Model):
|
|||||||
|
|
||||||
Resolution sources for the new prefill fields:
|
Resolution sources for the new prefill fields:
|
||||||
- process_description ← recipe.name (the job's process root)
|
- process_description ← recipe.name (the job's process root)
|
||||||
- certified_by_id ← customer_spec.signer_user_id, falling
|
- certified_by_id ← customer_spec.signer_user_id ONLY
|
||||||
back to company.x_fc_owner_user_id
|
(a per-spec override). Left empty
|
||||||
|
otherwise so the LIVE company owner
|
||||||
|
resolves at render / issue time.
|
||||||
- contact_partner_id ← partner.x_fc_default_coc_contact_id
|
- contact_partner_id ← partner.x_fc_default_coc_contact_id
|
||||||
- nc_quantity ← qty_scrapped + qty_visual_insp_rejects
|
- nc_quantity ← qty_scrapped + qty_visual_insp_rejects
|
||||||
|
|
||||||
@@ -2596,12 +2598,17 @@ class FpJob(models.Model):
|
|||||||
# sourced from sale_order.x_fc_coating_config_id (since retired);
|
# sourced from sale_order.x_fc_coating_config_id (since retired);
|
||||||
# recipe.name is the human-readable replacement.
|
# recipe.name is the human-readable replacement.
|
||||||
recipe = self.recipe_id
|
recipe = self.recipe_id
|
||||||
# Signer resolution: per-spec override wins, company default fills.
|
# Signer resolution (2026-05-28): snapshot ONLY a deliberate
|
||||||
|
# per-spec signer here. Do NOT freeze the company owner into
|
||||||
|
# certified_by_id — leaving it empty lets the CoC report and
|
||||||
|
# action_issue resolve the LIVE company owner (res.company
|
||||||
|
# .x_fc_owner_user_id / Settings "Certificate Owner") at render /
|
||||||
|
# issue time. That way changing the Settings signer flows through
|
||||||
|
# to existing draft certs instead of being frozen to whoever was
|
||||||
|
# the owner when the cert was created.
|
||||||
signer = False
|
signer = False
|
||||||
if spec and 'signer_user_id' in spec._fields:
|
if spec and 'signer_user_id' in spec._fields:
|
||||||
signer = spec.signer_user_id
|
signer = spec.signer_user_id
|
||||||
if not signer and 'x_fc_owner_user_id' in self.company_id._fields:
|
|
||||||
signer = self.company_id.x_fc_owner_user_id
|
|
||||||
# Contact: per-customer default; blank means manager picks at issue.
|
# Contact: per-customer default; blank means manager picks at issue.
|
||||||
contact = False
|
contact = False
|
||||||
if 'x_fc_default_coc_contact_id' in self.partner_id._fields:
|
if 'x_fc_default_coc_contact_id' in self.partner_id._fields:
|
||||||
|
|||||||
Reference in New Issue
Block a user