fix(plating): CoC + invoice PDFs render full content

Three reported PDF bugs from the customer-facing email package:

1. Invoice body was empty — Odoo 19 sets display_type='product' on
   regular invoice/SO lines (was empty string in 18.0). Both
   report_fp_invoice.xml and report_fp_sale.xml only matched
   `not line.display_type`, so every product line was skipped.
   Fixed both portrait + landscape variants to also match
   display_type == 'product'.

2. CoC PDF was a bare 30 KB header — _fp_generate_cert_pdf was
   rendering action_report_coc, which is bound to portal_job and
   has minimal content. Rewrote to use the rich fp.certificate-bound
   report (action_report_coc_en / action_report_coc_fr based on
   cert.partner_id.lang) and slugged the filename to
   CoC-<Customer>-<CertName>.pdf so the email attachment reads
   nicely instead of CERT-00123.pdf.

3. Thickness cert was an exact duplicate of the CoC — the CoC
   template already embeds thickness readings. Skip thickness cert
   creation entirely when the customer also wants CoC; only create
   a standalone thickness cert when the customer opted out of CoC.

Also: dispatcher in fp_notification_template now prefers
portal_job.coc_attachment_id (the rich one we just generated) and
falls back to rendering action_report_coc_en against fp.certificate
by partner.lang — never the bare portal-job report.

Versions bumped: bridge_mrp 19.0.6.0.0, notifications 19.0.4.0.0,
reports 19.0.4.0.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-19 01:16:27 -04:00
parent 167c423bf5
commit 633427bcf8
7 changed files with 93 additions and 38 deletions

View File

@@ -5,7 +5,7 @@
{
'name': 'Fusion Plating — Notifications',
'version': '19.0.3.0.0',
'version': '19.0.4.0.0',
'category': 'Manufacturing/Plating',
'summary': 'Auto-email notifications at workflow milestones with configurable templates, PDF attachments, and audit log.',
'author': 'Nexa Systems Inc.',

View File

@@ -218,25 +218,49 @@ class FpNotificationTemplate(models.Model):
)
if att:
ids.append(att)
# CoC — gated by customer preference (x_fc_send_coc, default True)
# CoC — gated by customer preference (x_fc_send_coc, default True).
# Prefer the rich PDF that mrp_production.button_mark_done already
# rendered against the fp.certificate (signatures, accreditation
# logos, thickness data). The legacy action_report_coc bound to
# fusion.plating.portal.job is only a header table; never use it
# when a real cert PDF exists.
if self.attach_coc and portal_job and _customer_wants('x_fc_send_coc'):
att = _render_report(
'fusion_plating_reports.action_report_coc', portal_job,
)
if att:
ids.append(att)
# Thickness report — gated by customer preference. Today the CoC
# template embeds thickness readings, so when a customer wants
# thickness-only we fall back to the CoC report attachment with
# a distinct filename. A standalone thickness-only template is
# TBD (not part of this chunk).
if portal_job.coc_attachment_id:
ids.append(portal_job.coc_attachment_id.id)
else:
# No pre-rendered cert (older job or cert-gen failed).
# Render the rich cert report against the most recent
# CoC fp.certificate, falling back to the bare portal_job
# template only if no cert exists at all.
Cert = self.env.get('fp.certificate')
cert = False
if Cert is not None and production:
cert = Cert.search([
('production_id', '=', production.id),
('certificate_type', '=', 'coc'),
], order='id desc', limit=1)
if cert:
lang = (cert.partner_id.lang or '').lower()
cert_xmlid = (
'fusion_plating_reports.action_report_coc_fr'
if lang.startswith('fr')
else 'fusion_plating_reports.action_report_coc_en'
)
att = _render_report(cert_xmlid, cert)
else:
att = _render_report(
'fusion_plating_reports.action_report_coc', portal_job,
)
if att:
ids.append(att)
# Thickness report — only attach when the customer opted OUT of
# CoC and ONLY wants thickness. The CoC PDF already embeds
# thickness data so attaching both would be a duplicate.
if (self.attach_thickness_report and portal_job
and _customer_wants('x_fc_send_thickness_report')
and not (self.attach_coc and _customer_wants('x_fc_send_coc'))):
# Avoid double-attaching the same PDF when both are wanted —
# the CoC already carries the thickness data.
att = _render_report(
'fusion_plating_reports.action_report_coc', portal_job,
'fusion_plating_reports.action_report_coc_en', portal_job,
)
if att:
ids.append(att)