feat(plating): fully bilingual CoC — all labels EN/FR

Convert every remaining CoC label from single-language (is_fr branch) to
bilingual EN/FR: document title, customer block (Name / Address / Contact /
Email / Phone), Fischerscope thickness report title + metadata (Equipment /
Product / Application / Directory / Calibration Std. / Operator / Measured /
Measuring Time), reading stats (Mean / Std Dev / Range), Source file,
Certified By, Name, and the Certification Statement heading. The statement
paragraph now prints both English and French. Reuses the SO report's inline
.fp-bl-en/.fp-bl-fr bilingual classes. Bump reports 19.0.11.30.0.

Deployed + render-verified on entech (CoC-30059 with thickness block, 243KB).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-28 22:11:40 -04:00
parent 9d9be17542
commit ec78fc148d
2 changed files with 34 additions and 49 deletions

View File

@@ -3,7 +3,7 @@
# License OPL-1 (Odoo Proprietary License v1.0)
{
'name': 'Fusion Plating — Reports',
'version': '19.0.11.29.0',
'version': '19.0.11.30.0',
'category': 'Manufacturing/Plating',
'summary': 'PDF reports for Fusion Plating: quote, SO, WO, packing, BoL, CoC, invoice, receipt, quality + compliance.',
'depends': [

View File

@@ -51,6 +51,8 @@
.fp-coc-nadcap-logo { max-height: 45px; max-width: 115px; display: inline-block; }
.fp-coc-title { font-size: 18pt; font-weight: bold; color: #2e2e2e;
line-height: 1.1; display: block; }
.fp-coc-title-fr { font-size: 12pt; font-style: italic; color: #555;
line-height: 1.1; display: block; margin-top: 1px; }
/* Barcode: inline-block wrap so the cert-number label centres
under the bars. Explicit no-border (wkhtmltopdf frames
inline-data imgs on entech). */
@@ -92,10 +94,8 @@
</t>
</div>
<div class="fp-coc-header-right">
<span class="fp-coc-title">
<t t-if="not is_fr">Certificate of Conformance</t>
<t t-if="is_fr">Certificat de Conformité</t>
</span>
<span class="fp-coc-title">Certificate of Conformance</span>
<span class="fp-coc-title-fr">Certificat de Conformité</span>
<t t-if="coc_barcode_uri">
<div class="fp-coc-bc-wrap">
<img t-att-src="coc_barcode_uri" alt="Cert Barcode"/>
@@ -145,6 +145,11 @@
.fp-coc .fp-bl-fr-stk { display: block; font-weight: normal;
font-style: italic; color: #555;
font-size: 80%; margin-top: 1px; }
/* Inline bilingual (EN bold / FR italic grey) for field labels
+ section headings. */
.fp-coc .fp-bl-en { font-weight: bold; }
.fp-coc .fp-bl-sep { color: #999; margin: 0 3px; font-weight: normal; }
.fp-coc .fp-bl-fr { font-weight: normal; font-style: italic; color: #555; }
.fp-coc .cert-statement-box { padding: 0; font-size: 8.5pt; }
.fp-coc .cert-statement-box h4 { margin: 0 0 6px 0; font-size: 9.5pt; font-weight: bold; }
.fp-coc .signature-img { max-height: 2.2cm; max-width: 7cm; }
@@ -198,13 +203,11 @@
<tr>
<td style="width: 50%; vertical-align: top;">
<div>
<strong t-if="not is_fr">Customer Name: </strong>
<strong t-if="is_fr">Nom du client : </strong>
<span class="fp-bl-en">Customer Name</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Nom du client</span>:
<t t-esc="doc.partner_id.name or ''"/>
</div>
<div style="margin-top: 4px;">
<strong t-if="not is_fr">Customer Address:</strong>
<strong t-if="is_fr">Adresse du client :</strong>
<span class="fp-bl-en">Customer Address</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Adresse du client</span>:
<br/>
<t t-if="doc.partner_id.street"><t t-esc="doc.partner_id.street"/><br/></t>
<t t-if="doc.partner_id.street2"><t t-esc="doc.partner_id.street2"/><br/></t>
@@ -216,18 +219,15 @@
<td style="width: 50%; vertical-align: top;">
<t t-set="contact" t-value="doc.contact_partner_id or doc.partner_id"/>
<div>
<strong t-if="not is_fr">Contact Name: </strong>
<strong t-if="is_fr">Nom du contact : </strong>
<span class="fp-bl-en">Contact Name</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Nom du contact</span>:
<t t-esc="contact.name or ''"/>
</div>
<div>
<strong t-if="not is_fr">Customer Email: </strong>
<strong t-if="is_fr">Courriel : </strong>
<span class="fp-bl-en">Customer Email</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Courriel</span>:
<t t-esc="contact.email or '-'"/>
</div>
<div>
<strong t-if="not is_fr">Customer Phone: </strong>
<strong t-if="is_fr">Téléphone : </strong>
<span class="fp-bl-en">Customer Phone</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Téléphone</span>:
<t t-esc="contact.phone or '-'"/>
</div>
</td>
@@ -371,8 +371,7 @@
<!-- Section header — full-width bar, drawn by the
div's bottom-border, no internal table needed. -->
<div class="ftk-title">
<t t-if="not is_fr">Fischerscope XRF Thickness Report</t>
<t t-if="is_fr">Rapport d'épaisseur Fischerscope XRF</t>
<span class="fp-bl-en">Fischerscope XRF Thickness Report</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Rapport d'épaisseur Fischerscope XRF</span>
</div>
<!-- Equipment metadata — 4-column key/value grid.
@@ -384,39 +383,33 @@
<table>
<tr class="ftk-row-divider">
<td class="ftk-label ftk-cell-divider" style="width: 18%;">
<t t-if="not is_fr">Equipment</t>
<t t-if="is_fr">Équipement</t>
<span class="fp-bl-en">Equipment</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Équipement</span>
</td>
<td class="ftk-cell-divider" style="width: 32%;">
<t t-esc="doc.x_fc_thickness_equipment or '—'"/>
</td>
<td class="ftk-label ftk-cell-divider" style="width: 18%;">
<t t-if="not is_fr">Calibration Std.</t>
<t t-if="is_fr">Étalon</t>
<span class="fp-bl-en">Calibration Std.</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Étalon</span>
</td>
<td style="width: 32%;"><t t-esc="calib or '—'"/></td>
</tr>
<tr class="ftk-row-divider">
<td class="ftk-label ftk-cell-divider">
<t t-if="not is_fr">Product</t>
<t t-if="is_fr">Produit</t>
<span class="fp-bl-en">Product</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Produit</span>
</td>
<td class="ftk-cell-divider"><t t-esc="doc.x_fc_thickness_product or '—'"/></td>
<td class="ftk-label ftk-cell-divider">
<t t-if="not is_fr">Operator</t>
<t t-if="is_fr">Opérateur</t>
<span class="fp-bl-en">Operator</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Opérateur</span>
</td>
<td><t t-esc="doc.x_fc_thickness_operator or '—'"/></td>
</tr>
<tr class="ftk-row-divider">
<td class="ftk-label ftk-cell-divider">
<t t-if="not is_fr">Application</t>
<t t-if="is_fr">Application</t>
<span class="fp-bl-en">Application</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Application</span>
</td>
<td class="ftk-cell-divider"><t t-esc="doc.x_fc_thickness_application or '—'"/></td>
<td class="ftk-label ftk-cell-divider">
<t t-if="not is_fr">Measured</t>
<t t-if="is_fr">Mesuré le</t>
<span class="fp-bl-en">Measured</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Mesuré le</span>
</td>
<td>
<t t-if="doc.x_fc_thickness_datetime"
@@ -426,13 +419,11 @@
</tr>
<tr class="ftk-row-divider">
<td class="ftk-label ftk-cell-divider">
<t t-if="not is_fr">Directory</t>
<t t-if="is_fr">Répertoire</t>
<span class="fp-bl-en">Directory</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Répertoire</span>
</td>
<td class="ftk-cell-divider"><t t-esc="doc.x_fc_thickness_directory or '—'"/></td>
<td class="ftk-label ftk-cell-divider">
<t t-if="not is_fr">Measuring Time</t>
<t t-if="is_fr">Durée de mesure</t>
<span class="fp-bl-en">Measuring Time</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Durée de mesure</span>
</td>
<td>
<t t-if="doc.x_fc_thickness_measuring_time_sec"
@@ -479,8 +470,7 @@
class="ftk-stat-mean ftk-row-divider"
style="page-break-inside: avoid;">
<td class="ftk-cell-divider">
<t t-if="not is_fr">Mean</t>
<t t-if="is_fr">Moyenne</t>
<span class="fp-bl-en">Mean</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Moyenne</span>
</td>
<td class="ftk-cell-divider"><t t-esc="'%.4f' % nip_mean"/></td>
<td class="ftk-cell-divider"><t t-esc="'%.3f' % ni_mean"/></td>
@@ -490,8 +480,7 @@
class="ftk-stat ftk-row-divider"
style="page-break-inside: avoid;">
<td class="ftk-cell-divider">
<t t-if="not is_fr">Std Dev</t>
<t t-if="is_fr">Écart-type</t>
<span class="fp-bl-en">Std Dev</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Écart-type</span>
</td>
<td class="ftk-cell-divider"><t t-esc="'%.4f' % nip_std"/></td>
<td class="ftk-cell-divider"><t t-esc="'%.3f' % ni_std"/></td>
@@ -509,8 +498,7 @@
class="ftk-stat ftk-row-divider"
style="page-break-inside: avoid;">
<td class="ftk-cell-divider">
<t t-if="not is_fr">Range</t>
<t t-if="is_fr">Étendue</t>
<span class="fp-bl-en">Range</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Étendue</span>
</td>
<td class="ftk-cell-divider"><t t-esc="'%.4f' % nip_range"/></td>
<td class="ftk-cell-divider"><t t-esc="'%.3f' % ni_range"/></td>
@@ -535,8 +523,7 @@
normal weight prints cleanly. -->
<div t-if="doc.x_fc_thickness_source_filename"
style="margin-top: 4px; font-size: 8pt; color: #555;">
<strong t-if="not is_fr">Source file:</strong>
<strong t-if="is_fr">Fichier source :</strong>
<span class="fp-bl-en">Source file</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Fichier source</span>:
<t t-esc="' ' + (doc.x_fc_thickness_source_filename or '')"/>
<t t-if="doc.x_fc_local_thickness_evidence_id"> (attached to cert as evidence)</t>
</div>
@@ -553,8 +540,7 @@
<tr style="page-break-inside: avoid;">
<td style="width: 50%; vertical-align: top;">
<div>
<strong t-if="not is_fr">Certified By:</strong>
<strong t-if="is_fr">Certifié par :</strong>
<span class="fp-bl-en">Certified By</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Certifié par</span>:
</div>
<div style="min-height: 2.5cm; margin-top: 6px;">
<img t-if="signature_img"
@@ -563,16 +549,15 @@
alt=""/>
</div>
<div style="margin-top: 4px; border-top: 1px solid #000; padding-top: 4px;">
<strong t-if="not is_fr">Name: </strong>
<strong t-if="is_fr">Nom : </strong>
<span class="fp-bl-en">Name</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Nom</span>:
<t t-esc="signer_name or ''"/>
</div>
</td>
<td style="width: 50%; vertical-align: top; padding-left: 14px;">
<div class="cert-statement-box">
<h4 t-if="not is_fr">Certification Statement</h4>
<h4 t-if="is_fr">Énoncé de conformité</h4>
<p t-if="not is_fr" style="margin: 0;">
<h4><span class="fp-bl-en">Certification Statement</span><span class="fp-bl-sep">/</span><span class="fp-bl-fr">Énoncé de conformité</span></h4>
<p style="margin: 0;">
This is to certify that the items listed herein have
been processed, inspected and tested in accordance
with your Purchase Order, drawings and specification
@@ -580,7 +565,7 @@
Made in Canada. There is no Mercury used in the
processing of this order.
</p>
<p t-if="is_fr" style="margin: 0;">
<p style="margin: 6px 0 0 0; font-style: italic; color: #444;">
Ceci est pour certifier que les articles inscrits ont
été procédés, inspectés et mis à l'essai selon votre
bon de commande, dessins et spécifications. Tous les