This commit is contained in:
gsinghpal
2026-05-21 09:22:50 -04:00
parent 894eea7ce2
commit d022e529d9
3 changed files with 90 additions and 13 deletions

View File

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

View File

@@ -394,9 +394,10 @@
<field name="report_type">qweb-pdf</field>
<field name="report_name">fusion_plating_reports.report_fp_packing_slip_portrait</field>
<field name="report_file">fusion_plating_reports.report_fp_packing_slip_portrait</field>
<field name="print_report_name">'Packing Slip - %s' % object.name</field>
<field name="print_report_name">'Packing Slip - %s' % (object.sale_id.name.rsplit('-', 1)[-1] if object.sale_id else object.name)</field>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_type">report</field>
<field name="paperformat_id" ref="paperformat_fp_a4_portrait"/>
</record>
<record id="action_report_fp_packing_slip_landscape" model="ir.actions.report">
@@ -405,7 +406,7 @@
<field name="report_type">qweb-pdf</field>
<field name="report_name">fusion_plating_reports.report_fp_packing_slip_landscape</field>
<field name="report_file">fusion_plating_reports.report_fp_packing_slip_landscape</field>
<field name="print_report_name">'Packing Slip - %s' % object.name</field>
<field name="print_report_name">'Packing Slip - %s' % (object.sale_id.name.rsplit('-', 1)[-1] if object.sale_id else object.name)</field>
<field name="binding_model_id" ref="stock.model_stock_picking"/>
<field name="binding_type">report</field>
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>

View File

@@ -13,6 +13,25 @@
<!-- ============================================================= -->
<template id="fp_packing_slip_styles">
<style>
/* CoC pattern: paperformat_fp_a4_portrait reserves only
margin_top=8mm; the body padding-top clears the header
band. Same trick as .fp-coc and .fp-sale. */
.fp-report.fp-ps .page { padding-top: 20mm; }
/* Title bar: float div layout (NO table — see CLAUDE.md
wkhtmltopdf overlap §2). Stacked bilingual title with
English bold on top and French italic-grey below. */
.fp-ps-titlebar { margin: 0 0 10px 0; padding: 0; overflow: hidden; }
.fp-ps-title-en { font-size: 18pt; font-weight: bold; color: #2e2e2e; line-height: 1.1; display: block; }
.fp-ps-title-fr { font-size: 13pt; font-style: italic; color: #555; line-height: 1.1; display: block; margin-top: 2px; }
.fp-ps-title-num { font-weight: bold; margin-left: 6px; }
/* Code128 barcode block (top-right of title bar). Same
sizing/centering as the SO confirmation; encodes the
packing-slip number so the printed label matches the
visible title. */
.fp-ps-barcode { float: right; margin-left: 12px; }
.fp-ps-barcode .fp-bc-wrap { display: inline-block; text-align: center; }
.fp-ps-barcode img { height: 48px; max-width: 240px; border: 0 !important; padding: 0; display: block; }
.fp-ps-barcode .fp-bc-label { font-size: 10pt; color: #333; margin-top: 6px; letter-spacing: 0.5px; }
.fp-ps-addrtable td { vertical-align: top; padding: 8px 10px; font-size: 10pt; }
.fp-ps-addrtable .fp-ps-addr-label { font-weight: bold; font-size: 9pt; color: #333; text-transform: uppercase; margin-bottom: 4px; }
.fp-ps-info-table th { background-color: #eaeaea; }
@@ -187,16 +206,49 @@
<t t-set="tracking_ref" t-value="doc.carrier_tracking_ref if 'carrier_tracking_ref' in doc._fields and doc.carrier_tracking_ref else False"/>
<t t-set="tracking_text" t-value="tracking_ref if tracking_ref else ('Ready for pick up' if not has_carrier else '—')"/>
<t t-set="po_number" t-value="(doc.sale_id.client_order_ref if doc.sale_id and doc.sale_id.client_order_ref else '')"/>
<!-- Packing slip number derived from the SO so it
matches the order/work order number: SO-30045
→ "30045". When the SO has multiple outbound
pickings (partial shipments), the 2nd onwards
get a -NN suffix: "30045-02", "30045-03". The
first/only picking is just the bare number.
Falls back to picking name (WH/OUT/00168) for
pickings without a linked SO. -->
<t t-set="so_name_raw" t-value="doc.sale_id.name if doc.sale_id else doc.name"/>
<t t-set="ps_base_num" t-value="so_name_raw.rsplit('-', 1)[-1] if '-' in so_name_raw else so_name_raw"/>
<t t-set="outbound_pickings" t-value="doc.sale_id.picking_ids.filtered(lambda p: p.picking_type_id and p.picking_type_id.code == 'outgoing') if doc.sale_id else doc"/>
<t t-set="picking_position" t-value="(sorted(outbound_pickings.ids).index(doc.id) + 1) if (doc.sale_id and doc.id in outbound_pickings.ids) else 1"/>
<t t-set="ps_number" t-value="ps_base_num if picking_position &lt;= 1 else ('%s-%02d' % (ps_base_num, picking_position))"/>
<!-- Code128 barcode encoding the packing-slip number so
the printed label matches the visible title. Inlined
via barcode_data_uri (no /report/barcode/ HTTP fetch
— wkhtmltopdf network calls fail on entech). -->
<t t-set="ps_barcode_uri" t-value="doc.env['ir.actions.report'].sudo().barcode_data_uri('Code128', ps_number, 600, 100) if ps_number else False"/>
<t t-set="qr_payload" t-value="doc.name or ''"/>
<t t-set="qr_uri" t-value="doc.env['ir.actions.report'].sudo().barcode_data_uri('QR', qr_payload, 220, 220) if qr_payload else False"/>
<div class="fp-report">
<div class="fp-report fp-ps">
<div class="page">
<h4>
Packing Slip #
<span t-field="doc.name"/>
</h4>
<!-- Bilingual title (EN bold on top, FR
italic-grey below) matching SO and CoC. -->
<div class="fp-ps-titlebar">
<t t-if="ps_barcode_uri">
<div class="fp-ps-barcode">
<div class="fp-bc-wrap">
<img t-att-src="ps_barcode_uri" alt="Packing Slip Barcode"/>
<div class="fp-bc-label"><t t-esc="ps_number"/></div>
</div>
</div>
</t>
<span class="fp-ps-title-en">
Packing Slip<span class="fp-ps-title-num"># <t t-esc="ps_number"/></span>
</span>
<span class="fp-ps-title-fr">Bordereau d'expédition</span>
</div>
<!-- Bill To / Ship To -->
<table class="bordered fp-ps-addrtable">
@@ -294,16 +346,40 @@
<t t-set="tracking_ref" t-value="doc.carrier_tracking_ref if 'carrier_tracking_ref' in doc._fields and doc.carrier_tracking_ref else False"/>
<t t-set="tracking_text" t-value="tracking_ref if tracking_ref else ('Ready for pick up' if not has_carrier else '—')"/>
<t t-set="po_number" t-value="(doc.sale_id.client_order_ref if doc.sale_id and doc.sale_id.client_order_ref else '')"/>
<!-- See portrait template for the numbering logic. -->
<t t-set="so_name_raw" t-value="doc.sale_id.name if doc.sale_id else doc.name"/>
<t t-set="ps_base_num" t-value="so_name_raw.rsplit('-', 1)[-1] if '-' in so_name_raw else so_name_raw"/>
<t t-set="outbound_pickings" t-value="doc.sale_id.picking_ids.filtered(lambda p: p.picking_type_id and p.picking_type_id.code == 'outgoing') if doc.sale_id else doc"/>
<t t-set="picking_position" t-value="(sorted(outbound_pickings.ids).index(doc.id) + 1) if (doc.sale_id and doc.id in outbound_pickings.ids) else 1"/>
<t t-set="ps_number" t-value="ps_base_num if picking_position &lt;= 1 else ('%s-%02d' % (ps_base_num, picking_position))"/>
<!-- Code128 barcode encoding the packing-slip number so
the printed label matches the visible title. Inlined
via barcode_data_uri (no /report/barcode/ HTTP fetch
— wkhtmltopdf network calls fail on entech). -->
<t t-set="ps_barcode_uri" t-value="doc.env['ir.actions.report'].sudo().barcode_data_uri('Code128', ps_number, 600, 100) if ps_number else False"/>
<t t-set="qr_payload" t-value="doc.name or ''"/>
<t t-set="qr_uri" t-value="doc.env['ir.actions.report'].sudo().barcode_data_uri('QR', qr_payload, 220, 220) if qr_payload else False"/>
<div class="fp-landscape">
<div class="fp-landscape fp-ps">
<div class="page">
<h2 style="text-align: left;">
Packing Slip #
<span t-field="doc.name"/>
</h2>
<div class="fp-ps-titlebar">
<t t-if="ps_barcode_uri">
<div class="fp-ps-barcode">
<div class="fp-bc-wrap">
<img t-att-src="ps_barcode_uri" alt="Packing Slip Barcode"/>
<div class="fp-bc-label"><t t-esc="ps_number"/></div>
</div>
</div>
</t>
<span class="fp-ps-title-en">
Packing Slip<span class="fp-ps-title-num"># <t t-esc="ps_number"/></span>
</span>
<span class="fp-ps-title-fr">Bordereau d'expédition</span>
</div>
<!-- Bill To / Ship To -->
<table class="bordered fp-ps-addrtable">