fix(reports): restore the original ENTECH box-sticker layout for fp.job + sale.order

The original mrp.production / mrp.workorder sticker (logo + WO# stack
on the left, big QR on the right, 7-row body with PO/Customer/Process/
Part Number/Due/Qty/Notes — the design ENTECH has been printing for
months) lives in fusion_plating_reports.report_fp_wo_sticker_inner.

The new fp.job sticker had been rebuilt from scratch with a different
look. This wires fp.job into the existing canonical template instead.

What changed:

- report_fp_wo_sticker_inner — every t-set now uses the
  "_var or fallback-from-_mo" pattern so callers can pre-resolve
  values; mrp.production/mrp.workorder callers still work via the
  fallback path.
- report_fp_wo_sticker_defaults — new shared template that initialises
  every overridable name to False so the inner's `or` chain doesn't
  NameError when an outer hasn't set it.
- report_fp_job_sticker_template — replaces the parallel layout with
  a t-call to report_fp_wo_sticker_inner, feeding it from fp.job
  fields (name, partner_id, qty, date_deadline, sale_order_id,
  sale_order_line_ids, recipe_id, part_catalog_id, coating_config_id).
- report_fp_so_sticker — new outer that iterates sale.order.order_line
  and emits one sticker per line that has a part_catalog_id. Bound to
  sale.order's print menu via action_report_fp_so_sticker.

Versions: reports 19.0.7.14.0 -> 19.0.7.15.0,
          jobs    19.0.5.0.0  -> 19.0.5.1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-25 13:03:29 -04:00
parent c27e8a109c
commit ecac43eef4
5 changed files with 159 additions and 97 deletions

View File

@@ -3,7 +3,7 @@
# License OPL-1 (Odoo Proprietary License v1.0)
{
'name': 'Fusion Plating — Native Jobs',
'version': '19.0.5.0.0',
'version': '19.0.5.1.0',
'category': 'Manufacturing/Plating',
'summary': 'Native plating job model — replaces mrp.production / mrp.workorder bridge.',
'author': 'Nexa Systems Inc.',

View File

@@ -3,12 +3,12 @@
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Native fp.job sticker — parallel to fusion_plating_reports' WO Box
Sticker which binds to mrp.production/mrp.workorder. Coexists during
the migration period.
QR encodes /fp/job/<id> (controller added in Task TBD; for now scan
will fall back to /web/login if controller absent).
Native fp.job sticker — reuses the canonical box-sticker design from
fusion_plating_reports.report_fp_wo_sticker_inner. The visual layout
(logo + WO# stack on the left, big QR on the right, 7-row body table
underneath, all wrapped in a 2px border) is the one shop staff have
been printing since the mrp.production days; we just feed it from
fp.job fields here instead of mrp.production.
-->
<odoo>
@@ -43,73 +43,29 @@
<template id="report_fp_job_sticker_template">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="job">
<t t-set="_base_url" t-value="env['ir.config_parameter'].sudo().get_param('web.base.url', '')"/>
<t t-set="_scan_url" t-value="_base_url + '/fp/job/' + str(job.id)"/>
<t t-set="_qr_src" t-value="env['ir.actions.report'].barcode_data_uri('QR', _scan_url, width=300, height=300)"/>
<style>
@page { margin: 0; size: 152mm 102mm; }
html, body { margin: 0 !important; padding: 0 !important; width: 100% !important; height: 100% !important; }
.fp-job-sticker {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
color: #000;
position: absolute;
top: 4px; left: 4px; right: 4px; bottom: 4px;
padding: 8px;
box-sizing: border-box;
border: 2px solid #000;
}
.fp-job-sticker-head {
display: flex;
justify-content: space-between;
align-items: flex-start;
border-bottom: 1.5px solid #000;
padding-bottom: 6px;
margin-bottom: 8px;
}
.fp-job-sticker-id {
font-size: 36pt;
font-weight: 900;
line-height: 1;
}
.fp-job-sticker-qr { width: 32mm; height: 32mm; display: block; }
.fp-job-sticker-row { padding: 3px 0; font-size: 14pt; }
.fp-job-sticker-label { font-weight: 700; display: inline-block; min-width: 30mm; }
</style>
<div class="fp-job-sticker">
<div class="fp-job-sticker-head">
<div>
<div style="font-size: 10pt; letter-spacing: 0.5mm; text-transform: uppercase;">Plating Job</div>
<div class="fp-job-sticker-id">
<span t-esc="job.name"/>
</div>
</div>
<img class="fp-job-sticker-qr" t-if="_qr_src" t-att-src="_qr_src"/>
</div>
<div class="fp-job-sticker-row">
<span class="fp-job-sticker-label">Customer:</span>
<span t-esc="job.partner_id.name"/>
</div>
<div class="fp-job-sticker-row" t-if="job.sale_order_id">
<span class="fp-job-sticker-label">SO:</span>
<span t-esc="job.sale_order_id.name"/>
</div>
<div class="fp-job-sticker-row">
<span class="fp-job-sticker-label">Qty:</span>
<strong><span t-esc="int(job.qty) if job.qty == int(job.qty) else job.qty"/></strong>
</div>
<div class="fp-job-sticker-row" t-if="job.date_deadline">
<span class="fp-job-sticker-label">Due:</span>
<span t-esc="job.date_deadline.strftime('%b %d, %Y')"/>
</div>
<div class="fp-job-sticker-row" t-if="job.recipe_id">
<span class="fp-job-sticker-label">Recipe:</span>
<span t-esc="job.recipe_id.name"/>
</div>
<div class="fp-job-sticker-row">
<span class="fp-job-sticker-label">Steps:</span>
<span t-esc="job.step_done_count"/> / <span t-esc="job.step_count"/>
</div>
</div>
<!-- Defaults block initialises every var the inner
reads (so `_so or ...` doesn't NameError). We
then override the ones we have data for. -->
<t t-call="fusion_plating_reports.report_fp_wo_sticker_defaults"/>
<!-- Pre-resolve the variables the shared inner template
expects, sourcing them from fp.job's native fields. -->
<t t-set="_order_id" t-value="job.name"/>
<t t-set="_scan_id" t-value="job.id"/>
<t t-set="_scan_path" t-value="'/fp/job/'"/>
<t t-set="_mo" t-value="False"/>
<t t-set="_so" t-value="job.sale_order_id"/>
<t t-set="_line" t-value="job.sale_order_line_ids[:1]"/>
<t t-set="_part" t-value="('part_catalog_id' in job._fields and job.part_catalog_id) or False"/>
<t t-set="_coating" t-value="('coating_config_id' in job._fields and job.coating_config_id) or False"/>
<t t-set="_process" t-value="job.recipe_id or False"/>
<t t-set="_due" t-value="job.date_deadline or False"/>
<t t-set="_qty" t-value="job.qty"/>
<t t-set="_partner_name" t-value="job.partner_id.name"/>
<!-- The fp.job's own name (WH/JOB/00033) is already
printed in the header as "WO #...", so suppress
the muted "(WH/MO/...)" suffix on the PO row. -->
<t t-set="_mo_ref" t-value="''"/>
<t t-call="fusion_plating_reports.report_fp_wo_sticker_inner"/>
</t>
</t>
</template>