Revert "feat(sticker): restore older 3-cell-header + right-Notes-panel layout"

This reverts commit 83c4eb7ee1.
This commit is contained in:
gsinghpal
2026-05-12 22:01:18 -04:00
parent 83c4eb7ee1
commit 4e58e84622
2 changed files with 185 additions and 187 deletions

View File

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

View File

@@ -67,26 +67,8 @@
else (_mo and _mo.name) or ''"/> else (_mo and _mo.name) or ''"/>
<t t-set="_internal_note" t-value="_internal_note <t t-set="_internal_note" t-value="_internal_note
or (_so and _so.x_fc_internal_note or (_so and _so.x_fc_internal_note
and _so.x_fc_internal_note.striptags()[:400]) and _so.x_fc_internal_note.striptags()[:100])
or '-'"/> or '-'"/>
<!-- Serial number(s): pre-set by outer (fp.job sets it from the
linked SO line), otherwise resolve from _line if present.
Joined with commas when multiple serials live on one line. -->
<t t-set="_serial_names" t-value="_serial_names
or (_line and 'x_fc_serial_ids' in _line._fields
and _line.x_fc_serial_ids
and ', '.join(_line.x_fc_serial_ids.mapped('name')))
or '-'"/>
<!-- Thickness range: prefer outer-supplied string; otherwise compose
from the coating's min/max + uom. Shows "-" when no coating or
both min/max are zero. -->
<t t-set="_thickness_str" t-value="_thickness_str or (_coating
and (_coating.thickness_min or _coating.thickness_max)
and (
('%s - %s' % (_coating.thickness_min, _coating.thickness_max))
+ (' ' + (_coating.thickness_uom or '') if _coating.thickness_uom else '')
)
) or '-'"/>
<!-- Inline the QR as base64 data URI so wkhtmltopdf doesn't need <!-- Inline the QR as base64 data URI so wkhtmltopdf doesn't need
to fetch /report/barcode/ over the network during rendering. to fetch /report/barcode/ over the network during rendering.
Generated at 600x600 (was 300x300) so it down-scales rather Generated at 600x600 (was 300x300) so it down-scales rather
@@ -103,10 +85,10 @@
width: 100% !important; width: 100% !important;
height: 100% !important; height: 100% !important;
} }
/* Layout: 3-cell header (Logo | WO# | QR) above a 3-col body /* Boxy professional layout: thick outer border, horizontal row
(Label | Value | Notes-rowspan). Notes spans the full body borders, vertical label/value divider. Absolute positioning +
so operators have a tall right-side panel for multi-line % row heights force the content to fill the full page in
notes — the original ENTECH sticker layout. */ wkhtmltopdf (which ignores vh/vw/flex). ------------------- */
.fp-sticker { .fp-sticker {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
color: #000; color: #000;
@@ -118,13 +100,14 @@
page-break-after: always; page-break-after: always;
page-break-inside: avoid; page-break-inside: avoid;
} }
/* ---- HEADER band — 32% height, 3 cells side-by-side. */ /* ---- HEADER band — 40% to fit 2x WO# + logo + QR. */
.fp-sticker-head-wrap { .fp-sticker-head-wrap {
position: absolute; position: absolute;
left: 0; right: 0; top: 0; left: 0; right: 0; top: 0;
height: 32%; height: 40%;
border-bottom: 2px solid #000; border-bottom: 2px solid #000;
box-sizing: border-box; box-sizing: border-box;
padding: 0;
} }
table.fp-sticker-head { table.fp-sticker-head {
width: 100%; width: 100%;
@@ -132,53 +115,82 @@
table-layout: fixed; table-layout: fixed;
border-collapse: collapse; border-collapse: collapse;
} }
table.fp-sticker-head td { table.fp-sticker-head td { padding: 0; vertical-align: middle; }
padding: 0; col.fp-col-head-left { width: 66%; }
vertical-align: middle; col.fp-col-head-right { width: 34%; }
td.fp-sticker-head-left {
overflow: hidden;
border-right: 2px solid #000;
}
td.fp-sticker-head-right {
text-align: center; text-align: center;
vertical-align: middle;
overflow: hidden; overflow: hidden;
} }
col.fp-col-head-logo { width: 28%; } /* Left column nested 2-row table: logo on top, WO# below.
col.fp-col-head-wo { width: 44%; } Horizontal divider between rows mirrors body row borders. */
col.fp-col-head-qr { width: 28%; } table.fp-sticker-head-left-stack {
td.fp-sticker-head-logo { border-right: 2px solid #000; } width: 100%;
td.fp-sticker-head-wo { border-right: 2px solid #000; } height: 100%;
table-layout: fixed;
border-collapse: collapse;
}
table.fp-sticker-head-left-stack tr.fp-row-logo { height: 50%; }
table.fp-sticker-head-left-stack tr.fp-row-wo { height: 50%; }
table.fp-sticker-head-left-stack td {
padding: 0 14px;
vertical-align: middle;
}
/* Logo cell + WO# cell each get explicit vertical-align so the
content sits in the middle of its half of the header band. */
table.fp-sticker-head-left-stack tr.fp-row-logo td,
table.fp-sticker-head-left-stack tr.fp-row-wo td {
vertical-align: middle;
}
table.fp-sticker-head-left-stack tr + tr td {
border-top: 1px solid #000;
}
.fp-sticker-logo { .fp-sticker-logo {
max-height: 22mm; /* Logo bumped 40% (116 → 162px height, 520 → 728px width). */
max-width: 90%; max-height: 162px;
display: inline-block; max-width: 728px;
display: block;
} }
.fp-sticker-wo { .fp-sticker-wo {
font-size: 36pt; font-size: 72pt;
font-weight: 900; font-weight: 900;
letter-spacing: 0.2mm; letter-spacing: 0.2mm;
line-height: 1; line-height: 1;
white-space: nowrap; white-space: nowrap;
margin: 0; margin: 0;
} }
/* QR wrapper crops the ~12% quiet-zone the barcode generator /* QR wrapper crops the white quiet-zone around the QR pattern
adds around the pattern so the visible QR fills the cell. */ so it doesn't visually float on a white square inside the
cell. The PNG from Odoo's barcode generator carries a
~12% border (4 modules of quiet-zone) on each side; we
render the image larger than the wrapper and offset it so
the wrapper clips that border out. ---------------------- */
.fp-sticker-qr-wrap { .fp-sticker-qr-wrap {
width: 240px; width: 380px;
height: 240px; height: 380px;
display: inline-block; display: inline-block;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
.fp-sticker-qr { .fp-sticker-qr {
width: 320px; width: 510px;
height: 320px; height: 510px;
position: absolute; position: absolute;
top: -40px; top: -65px;
left: -40px; left: -65px;
margin: 0; margin: 0;
display: block; display: block;
} }
/* ---- BODY band — 68%, 3 cols (Label | Value | Notes-rowspan). */ /* ---- BODY band (7 rows, each 14.28% of the band) ---- */
.fp-sticker-body-wrap { .fp-sticker-body-wrap {
position: absolute; position: absolute;
left: 0; right: 0; left: 0; right: 0;
top: 32%; bottom: 0; top: 40%; bottom: 0;
} }
table.fp-sticker-body { table.fp-sticker-body {
width: 100%; width: 100%;
@@ -186,22 +198,15 @@
table-layout: fixed; table-layout: fixed;
border-collapse: collapse; border-collapse: collapse;
} }
col.fp-col-label { width: 22%; }
col.fp-col-value { width: 48%; }
col.fp-col-notes { width: 30%; }
/* 7 rows of equal height. wkhtmltopdf needs explicit row
heights to fill the band; without it rows collapse to
text-line height. -------------------------------------- */
table.fp-sticker-body tr { height: 14.28%; } table.fp-sticker-body tr { height: 14.28%; }
table.fp-sticker-body tr + tr td.fp-sticker-label, table.fp-sticker-body tr + tr td { border-top: 1px solid #000; }
table.fp-sticker-body tr + tr td.fp-sticker-value { col.fp-col-label { width: 32%; }
border-top: 1px solid #000; col.fp-col-value { width: 68%; }
}
table.fp-sticker-body td { table.fp-sticker-body td {
vertical-align: middle; vertical-align: middle;
padding: 0 12px; padding: 0 14px;
font-size: 17pt; font-size: 38pt;
line-height: 1.15; line-height: 1.1;
} }
td.fp-sticker-label { td.fp-sticker-label {
font-weight: 700; font-weight: 700;
@@ -213,143 +218,138 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
border-right: 2px solid #000;
}
/* Notes spans all 7 body rows — multi-line text wraps freely
(no nowrap, top-aligned, modest padding). Big bold "Notes:"
heading then the body text. */
td.fp-sticker-notes {
vertical-align: top;
padding: 10px 14px;
font-size: 14pt;
line-height: 1.3;
white-space: pre-line;
}
.fp-sticker-notes-head {
font-weight: 700;
font-size: 16pt;
display: block;
margin-bottom: 6px;
} }
.fp-sticker-strong { font-weight: 700; } .fp-sticker-strong { font-weight: 700; }
.fp-sticker-muted { color: #555; font-size: 13pt; } .fp-sticker-muted { color: #555; font-size: 28pt; }
</style> </style>
<div class="fp-sticker"> <div class="fp-sticker">
<div class="fp-sticker-head-wrap"> <div class="fp-sticker-head-wrap">
<table class="fp-sticker-head"> <table class="fp-sticker-head">
<colgroup> <colgroup>
<col class="fp-col-head-logo"/> <col class="fp-col-head-left"/>
<col class="fp-col-head-wo"/> <col class="fp-col-head-right"/>
<col class="fp-col-head-qr"/> </colgroup>
</colgroup> <tr>
<tr> <td class="fp-sticker-head-left">
<td class="fp-sticker-head-logo"> <!-- env.company.logo is often blank while logo_web
<!-- env.company.logo is often blank while is populated from the company partner's image.
logo_web is populated. Fall back across Fall back across both + partner.image_1920. -->
both + partner.image_1920. --> <t t-set="_logo" t-value="env.company.logo
<t t-set="_logo" t-value="env.company.logo or env.company.logo_web
or env.company.logo_web or env.company.partner_id.image_1920
or env.company.partner_id.image_1920 or False"/>
or False"/> <table class="fp-sticker-head-left-stack">
<img t-if="_logo" <tr class="fp-row-logo">
class="fp-sticker-logo" <td>
t-att-src="image_data_uri(_logo)"/> <img t-if="_logo"
</td> class="fp-sticker-logo"
<td class="fp-sticker-head-wo"> t-att-src="image_data_uri(_logo)"/>
<div class="fp-sticker-wo"> </td>
WO #<span t-esc="_order_id"/> </tr>
</div> <tr class="fp-row-wo">
</td> <td>
<td> <div class="fp-sticker-wo">
<div class="fp-sticker-qr-wrap" t-if="_qr_src"> WO #<span t-esc="_order_id"/>
<img class="fp-sticker-qr" </div>
t-att-src="_qr_src"/> </td>
</div> </tr>
</td> </table>
</tr> </td>
</table> <td class="fp-sticker-head-right">
<div class="fp-sticker-qr-wrap" t-if="_qr_src">
<img class="fp-sticker-qr"
t-att-src="_qr_src"/>
</div>
</td>
</tr>
</table>
</div> </div>
<div class="fp-sticker-body-wrap"> <div class="fp-sticker-body-wrap">
<table class="fp-sticker-body"> <table class="fp-sticker-body">
<colgroup> <colgroup>
<col class="fp-col-label"/> <col class="fp-col-label"/>
<col class="fp-col-value"/> <col class="fp-col-value"/>
<col class="fp-col-notes"/> </colgroup>
</colgroup> <tr>
<tr> <td class="fp-sticker-label">PO (RO):</td>
<td class="fp-sticker-label">PO #:</td> <td class="fp-sticker-value">
<td class="fp-sticker-value"> <span class="fp-sticker-strong"
t-esc="_po_number"/>
<t t-if="_mo_ref">
<span class="fp-sticker-muted">
(<span t-esc="_mo_ref"/>)
</span>
</t>
</td>
</tr>
<tr>
<td class="fp-sticker-label">Customer:</td>
<td class="fp-sticker-value">
<span t-esc="_partner_name"/>
</td>
</tr>
<tr>
<td class="fp-sticker-label">Process:</td>
<td class="fp-sticker-value">
<t t-if="_process">
<span t-esc="_process.name"/>
</t>
<t t-elif="_coating">
<span t-esc="_coating.name"/>
</t>
<t t-else="">-</t>
</td>
</tr>
<tr>
<td class="fp-sticker-label">Part Number:</td>
<td class="fp-sticker-value">
<t t-if="_part">
<span class="fp-sticker-strong" <span class="fp-sticker-strong"
t-esc="_po_number"/> t-esc="_part.part_number"/>
<t t-if="_mo_ref"> <t t-if="_part.revision">
<!-- Some parts store the revision with a
"Rev " prefix already (e.g. "Rev 1"),
others store just the value ("1", "A").
Strip a leading "Rev " (case insensitive)
so we don't print "Rev Rev 1". -->
<t t-set="_rev_clean" t-value="_part.revision.strip()"/>
<t t-if="_rev_clean.lower().startswith('rev ')">
<t t-set="_rev_clean" t-value="_rev_clean[4:].strip()"/>
</t>
<span class="fp-sticker-muted"> <span class="fp-sticker-muted">
(<span t-esc="_mo_ref"/>) Rev <span t-esc="_rev_clean"/>
</span> </span>
</t> </t>
</td> </t>
<!-- Notes panel spans all 7 body rows. --> <t t-else="">-</t>
<td class="fp-sticker-notes" rowspan="7"> </td>
<span class="fp-sticker-notes-head">Notes:</span> </tr>
<t t-esc="_internal_note"/> <tr>
</td> <td class="fp-sticker-label">Due Date:</td>
</tr> <td class="fp-sticker-value">
<tr> <t t-if="_due">
<td class="fp-sticker-label">SN #:</td> <span t-esc="_due.strftime('%b %d, %Y')"/>
<td class="fp-sticker-value"> </t>
<span t-esc="_serial_names"/> <t t-else="">-</t>
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="fp-sticker-label">Customer:</td> <td class="fp-sticker-label">Qty:</td>
<td class="fp-sticker-value"> <td class="fp-sticker-value">
<span t-esc="_partner_name"/> <span class="fp-sticker-strong">
</td> <span t-esc="int(_qty) if _qty == int(_qty) else _qty"/>
</tr> </span>
<tr> </td>
<td class="fp-sticker-label">Part #:</td> </tr>
<td class="fp-sticker-value"> <tr>
<t t-if="_part"> <td class="fp-sticker-label">Notes:</td>
<span class="fp-sticker-strong" <td class="fp-sticker-value">
t-esc="_part.part_number"/> <t t-esc="_internal_note"/>
<t t-if="_part.revision"> </td>
<t t-set="_rev_clean" t-value="_part.revision.strip()"/> </tr>
<t t-if="_rev_clean.lower().startswith('rev ')"> </table>
<t t-set="_rev_clean" t-value="_rev_clean[4:].strip()"/>
</t>
<span class="fp-sticker-muted">
Rev <span t-esc="_rev_clean"/>
</span>
</t>
</t>
<t t-else="">-</t>
</td>
</tr>
<tr>
<td class="fp-sticker-label">Due Date:</td>
<td class="fp-sticker-value">
<t t-if="_due">
<span t-esc="_due.strftime('%b %d, %Y')"/>
</t>
<t t-else="">-</t>
</td>
</tr>
<tr>
<td class="fp-sticker-label">Thickness:</td>
<td class="fp-sticker-value">
<span t-esc="_thickness_str"/>
</td>
</tr>
<tr>
<td class="fp-sticker-label">Qty:</td>
<td class="fp-sticker-value">
<span class="fp-sticker-strong">
<span t-esc="int(_qty) if _qty == int(_qty) else _qty"/>
</span>
</td>
</tr>
</table>
</div> </div>
</div> </div>
</template> </template>
@@ -372,8 +372,6 @@
<t t-set="_partner_name" t-value="False"/> <t t-set="_partner_name" t-value="False"/>
<t t-set="_mo_ref" t-value="False"/> <t t-set="_mo_ref" t-value="False"/>
<t t-set="_internal_note" t-value="False"/> <t t-set="_internal_note" t-value="False"/>
<t t-set="_serial_names" t-value="False"/>
<t t-set="_thickness_str" t-value="False"/>
<t t-set="_scan_path" t-value="False"/> <t t-set="_scan_path" t-value="False"/>
</template> </template>