feat(fusion_plating): quote-to-cash infra, notifications, wizards, Tier 1 plating features
Quote-to-cash PDF reports (portrait + landscape variants, 16 new actions): - Quotation / Sales Order, Work Order Traveller, Packing Slip, Bill of Lading, Certificate of Conformance (portrait added), Invoice, Payment Receipt - Shared fp_portrait_styles + fp_landscape_styles base templates Workflow gap fixes (fusion_plating_bridge_mrp): - Auto-assign recipe from SO coating config in MrpProduction.action_confirm - Auto-create draft CoC (fp.certificate) on MrpProduction.button_mark_done Notifications overhaul (fusion_plating_notifications v2.0): - Expanded TRIGGER_EVENTS to 7 (added quote_sent, mo_complete, shipped, payment_received) - Shared _dispatch method replaces three duplicated send helpers - Auto-attach PDF reports per template config (quote, SO, CoC, invoice, receipt, BoL) - Rebuilt 7 email templates with fusion_claims accent-bar design (info/success color-coded, theme-safe, 600px max-width) - New hooks: MrpProduction done, FpDelivery mark_delivered, AccountPayment post, SaleOrder action_quotation_send Wizards (fusion_plating_configurator): - fp.direct.order.wizard — skip quotation for repeat customers with PO in hand; optional new-revision drawing upload bumps fp.part.catalog revision and links new rev to the SO; creates + confirms the SO in one step - fp.part.catalog.import.wizard — 3-step CSV import with dry-run preview, tolerant parsing (customer by name/email/xmlid, human-readable selections), duplicate detection, create-missing-customers option, single transaction commit - Partner form stat buttons: Direct Order, Import Parts - CSV template download button Tier 1 practical plating features: - T1.1 Hydrogen bake window enforcement (fp.coating.config.requires_bake_relief, auto-create fusion.plating.bake.window on plating WO finish, FpDelivery lockout when window is open) - T1.2 Bath replenishment rules + pending suggestion queue (fusion.plating.bath.replenishment.rule + .suggestion, hook on bath log line create, operator Apply / Dismiss actions) - T1.3 Rack/fixture library (fusion.plating.rack with MTO counter, strip schedule, lifecycle: active → needs_strip → stripping → retired) - T1.4 Rework / strip-and-replate MOs (x_fc_is_rework, x_fc_original_production_id, Create Rework stat button on completed MOs) - T1.5 Parts location (x_fc_current_location computed on mrp.production — "In progress: Alkaline Clean" / "Queued: Bake Oven" / "Ready to Ship") Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,21 +3,28 @@
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
{
|
||||
'name': 'Fusion Plating — Reports',
|
||||
'version': '19.0.1.0.0',
|
||||
'version': '19.0.2.0.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'PDF reports for all Fusion Plating models: CoC, NCR, CAPA, bath logs, calibration, and more.',
|
||||
'summary': 'PDF reports for Fusion Plating: quote, SO, WO, packing, BoL, CoC, invoice, receipt, quality + compliance.',
|
||||
'depends': [
|
||||
'sale',
|
||||
'account',
|
||||
'stock',
|
||||
'mrp',
|
||||
'fusion_plating',
|
||||
'fusion_plating_quality',
|
||||
'fusion_plating_compliance',
|
||||
'fusion_plating_safety',
|
||||
'fusion_plating_portal',
|
||||
'fusion_plating_configurator',
|
||||
'fusion_plating_bridge_mrp',
|
||||
'fusion_plating_logistics',
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'report/report_base_styles.xml',
|
||||
'report/report_actions.xml',
|
||||
# Quality + compliance reports
|
||||
'report/report_coc.xml',
|
||||
'report/report_ncr.xml',
|
||||
'report/report_capa.xml',
|
||||
@@ -30,6 +37,13 @@
|
||||
'report/report_waste_manifest.xml',
|
||||
'report/report_discharge_sample.xml',
|
||||
'report/report_wo_margin.xml',
|
||||
# Quote-to-cash reports (portrait + landscape)
|
||||
'report/report_fp_sale.xml',
|
||||
'report/report_fp_work_order.xml',
|
||||
'report/report_fp_packing_slip.xml',
|
||||
'report/report_fp_bol.xml',
|
||||
'report/report_fp_invoice.xml',
|
||||
'report/report_fp_receipt.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': False,
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 1. Certificate of Conformance (Portal Job) -->
|
||||
<!-- 1. Certificate of Conformance (Portal Job) — Landscape -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_coc" model="ir.actions.report">
|
||||
<field name="name">Certificate of Conformance</field>
|
||||
<field name="name">Certificate of Conformance (Landscape)</field>
|
||||
<field name="model">fusion.plating.portal.job</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_coc</field>
|
||||
@@ -38,6 +38,18 @@
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- Certificate of Conformance — Portrait -->
|
||||
<record id="action_report_coc_portrait" model="ir.actions.report">
|
||||
<field name="name">Certificate of Conformance (Portrait)</field>
|
||||
<field name="model">fusion.plating.portal.job</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_coc_portrait</field>
|
||||
<field name="report_file">fusion_plating_reports.report_coc_portrait</field>
|
||||
<field name="print_report_name">'CoC - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="fusion_plating_portal.model_fusion_plating_portal_job"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 2. Non-Conformance Report -->
|
||||
<!-- ============================================================= -->
|
||||
@@ -202,4 +214,160 @@
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 13. Quotation / Sales Order (Portrait + Landscape) -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fp_sale_portrait" model="ir.actions.report">
|
||||
<field name="name">Quotation / Order (Portrait)</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_sale_portrait</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_sale_portrait</field>
|
||||
<field name="print_report_name">(object.state in ('draft', 'sent') and 'Quotation - %s' % object.name) or 'Order - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="sale.model_sale_order"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_fp_sale_landscape" model="ir.actions.report">
|
||||
<field name="name">Quotation / Order (Landscape)</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_sale_landscape</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_sale_landscape</field>
|
||||
<field name="print_report_name">(object.state in ('draft', 'sent') and 'Quotation - %s' % object.name) or 'Order - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="sale.model_sale_order"/>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 14. Work Order Traveller (Portrait + Landscape) -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fp_work_order_portrait" model="ir.actions.report">
|
||||
<field name="name">Work Order Traveller (Portrait)</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_work_order_portrait</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_work_order_portrait</field>
|
||||
<field name="print_report_name">'WO - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="mrp.model_mrp_workorder"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_fp_work_order_landscape" model="ir.actions.report">
|
||||
<field name="name">Work Order Traveller (Landscape)</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_work_order_landscape</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_work_order_landscape</field>
|
||||
<field name="print_report_name">'WO - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="mrp.model_mrp_workorder"/>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 15. Packing Slip (Portrait + Landscape) -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fp_packing_slip_portrait" model="ir.actions.report">
|
||||
<field name="name">Packing Slip (Portrait)</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<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="binding_model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_fp_packing_slip_landscape" model="ir.actions.report">
|
||||
<field name="name">Packing Slip (Landscape)</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<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="binding_model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 16. Bill of Lading (Portrait + Landscape) -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fp_bol_portrait" model="ir.actions.report">
|
||||
<field name="name">Bill of Lading (Portrait)</field>
|
||||
<field name="model">fusion.plating.delivery</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_bol_portrait</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_bol_portrait</field>
|
||||
<field name="print_report_name">'BoL - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="fusion_plating_logistics.model_fusion_plating_delivery"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_fp_bol_landscape" model="ir.actions.report">
|
||||
<field name="name">Bill of Lading (Landscape)</field>
|
||||
<field name="model">fusion.plating.delivery</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_bol_landscape</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_bol_landscape</field>
|
||||
<field name="print_report_name">'BoL - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="fusion_plating_logistics.model_fusion_plating_delivery"/>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 17. Invoice (Portrait + Landscape) -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fp_invoice_portrait" model="ir.actions.report">
|
||||
<field name="name">Invoice — Plating (Portrait)</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_invoice_portrait</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_invoice_portrait</field>
|
||||
<field name="print_report_name">'Invoice - %s' % (object.name or '')</field>
|
||||
<field name="binding_model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_fp_invoice_landscape" model="ir.actions.report">
|
||||
<field name="name">Invoice — Plating (Landscape)</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_invoice_landscape</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_invoice_landscape</field>
|
||||
<field name="print_report_name">'Invoice - %s' % (object.name or '')</field>
|
||||
<field name="binding_model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- 18. Payment Receipt (Portrait + Landscape) -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fp_receipt_portrait" model="ir.actions.report">
|
||||
<field name="name">Payment Receipt (Portrait)</field>
|
||||
<field name="model">account.payment</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_receipt_portrait</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_receipt_portrait</field>
|
||||
<field name="print_report_name">'Receipt - %s' % (object.name or '')</field>
|
||||
<field name="binding_model_id" ref="account.model_account_payment"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_fp_receipt_landscape" model="ir.actions.report">
|
||||
<field name="name">Payment Receipt (Landscape)</field>
|
||||
<field name="model">account.payment</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_plating_reports.report_fp_receipt_landscape</field>
|
||||
<field name="report_file">fusion_plating_reports.report_fp_receipt_landscape</field>
|
||||
<field name="print_report_name">'Receipt - %s' % (object.name or '')</field>
|
||||
<field name="binding_model_id" ref="account.model_account_payment"/>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fp_a4_landscape"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -3,12 +3,48 @@
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Part of the Fusion Plating product family.
|
||||
Shared landscape CSS for all Fusion Plating reports.
|
||||
Shared CSS for all Fusion Plating reports (portrait + landscape).
|
||||
-->
|
||||
<odoo>
|
||||
<!-- ============================================================= -->
|
||||
<!-- Portrait Styles -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="fp_portrait_styles">
|
||||
<style>
|
||||
.fp-report { font-family: Arial, sans-serif; font-size: 10pt; color: #000; }
|
||||
.fp-report table { width: 100%; border-collapse: collapse; margin-bottom: 10px; }
|
||||
.fp-report table.bordered, .fp-report table.bordered th, .fp-report table.bordered td { border: 1px solid #000; }
|
||||
.fp-report th { background-color: #0066a1; color: white; padding: 6px 8px; font-weight: bold; text-align: center; font-size: 9pt; }
|
||||
.fp-report td { padding: 6px 8px; vertical-align: top; font-size: 10pt; }
|
||||
.fp-report .text-center { text-align: center; }
|
||||
.fp-report .text-end { text-align: right; }
|
||||
.fp-report .text-start { text-align: left; }
|
||||
.fp-report .adp-bg { background-color: #e3f2fd; }
|
||||
.fp-report .client-bg { background-color: #fff3e0; }
|
||||
.fp-report .section-row { background-color: #f0f0f0; font-weight: bold; }
|
||||
.fp-report .note-row { font-style: italic; color: #555; font-size: 9pt; }
|
||||
.fp-report h4 { color: #0066a1; margin: 0 0 15px 0; font-size: 16pt; }
|
||||
.fp-report .totals-table { border: 1px solid #000; border-collapse: collapse; }
|
||||
.fp-report .totals-table td { border: 1px solid #000; padding: 6px 8px; }
|
||||
.fp-report .info-header { background-color: #f5f5f5; color: #333; }
|
||||
.fp-report .adp-header { background-color: #e3f2fd; color: #333; }
|
||||
.fp-report .highlight-box { border: 2px solid #0066a1; background-color: #eaf2f8; padding: 10px; margin: 10px 0; }
|
||||
.fp-report .paid-stamp { color: #28a745; font-size: 36pt; font-weight: bold; border: 4px solid #28a745; padding: 10px 20px; transform: rotate(-8deg); display: inline-block; }
|
||||
.fp-report .status-ok { color: #2e7d32; font-weight: bold; }
|
||||
.fp-report .status-warning { color: #f57f17; font-weight: bold; }
|
||||
.fp-report .status-fail { color: #c62828; font-weight: bold; }
|
||||
.fp-report .sig-box { border: 1px solid #000; padding: 12px; min-height: 70px; }
|
||||
.fp-report .sig-line { border-bottom: 1px solid #000; min-height: 28px; }
|
||||
.fp-report .small-muted { font-size: 8pt; color: #666; }
|
||||
</style>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Landscape Styles -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="fp_landscape_styles">
|
||||
<style>
|
||||
.fp-landscape { font-family: Arial, sans-serif; font-size: 11pt; }
|
||||
.fp-landscape { font-family: Arial, sans-serif; font-size: 11pt; color: #000; }
|
||||
.fp-landscape table { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
|
||||
.fp-landscape table.bordered, .fp-landscape table.bordered th, .fp-landscape table.bordered td { border: 1px solid #000; }
|
||||
.fp-landscape th { background-color: #0066a1; color: white; padding: 8px 10px; font-weight: bold; font-size: 10pt; }
|
||||
@@ -19,15 +55,20 @@
|
||||
.fp-landscape .adp-bg { background-color: #e3f2fd; }
|
||||
.fp-landscape .client-bg { background-color: #fff3e0; }
|
||||
.fp-landscape .section-row { background-color: #f0f0f0; font-weight: bold; }
|
||||
.fp-landscape .note-row { font-style: italic; }
|
||||
.fp-landscape .note-row { font-style: italic; color: #555; }
|
||||
.fp-landscape h2 { color: #0066a1; margin: 10px 0; font-size: 18pt; }
|
||||
.fp-landscape .info-table td { padding: 8px 12px; font-size: 11pt; }
|
||||
.fp-landscape .info-table th { background-color: #f5f5f5; color: #333; font-size: 10pt; padding: 6px 12px; }
|
||||
.fp-landscape .totals-table { border: 1px solid #000; }
|
||||
.fp-landscape .totals-table td { border: 1px solid #000; padding: 8px 12px; font-size: 11pt; }
|
||||
.fp-landscape .highlight-box { border: 2px solid #0066a1; background-color: #eaf2f8; padding: 10px; margin: 10px 0; }
|
||||
.fp-landscape .paid-stamp { color: #28a745; font-size: 42pt; font-weight: bold; border: 4px solid #28a745; padding: 10px 20px; transform: rotate(-8deg); display: inline-block; }
|
||||
.fp-landscape .status-ok { color: #2e7d32; font-weight: bold; }
|
||||
.fp-landscape .status-warning { color: #f57f17; font-weight: bold; }
|
||||
.fp-landscape .status-fail { color: #c62828; font-weight: bold; }
|
||||
.fp-landscape .sig-box { border: 1px solid #000; padding: 12px; min-height: 70px; }
|
||||
.fp-landscape .sig-line { border-bottom: 1px solid #000; min-height: 28px; }
|
||||
.fp-landscape .small-muted { font-size: 9pt; color: #666; }
|
||||
</style>
|
||||
</template>
|
||||
</odoo>
|
||||
|
||||
@@ -2,9 +2,132 @@
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Certificate of Conformance — Portal Job
|
||||
Certificate of Conformance — Portal Job (Portrait + Landscape).
|
||||
The original `report_coc` id is kept as the landscape variant so existing
|
||||
bindings keep working; a new `report_coc_portrait` variant is added.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_coc_portrait">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_portrait_styles"/>
|
||||
<div class="fp-report">
|
||||
<div class="page">
|
||||
|
||||
<h4>
|
||||
Certificate of Conformance —
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<!-- Job info -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 25%;">JOB REF</th>
|
||||
<th class="info-header" style="width: 25%;">QTY</th>
|
||||
<th class="info-header" style="width: 25%;">RECEIVED</th>
|
||||
<th class="info-header" style="width: 25%;">SHIP DATE</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.name"/></td>
|
||||
<td class="text-center"><span t-field="doc.quantity"/></td>
|
||||
<td class="text-center"><span t-field="doc.received_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-field="doc.actual_ship_date" t-options="{'widget': 'date'}"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Customer block -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr><th colspan="2" style="background-color: #0066a1; color: white;">CUSTOMER</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 30%; background-color: #f5f5f5; font-weight: bold;">Name</td>
|
||||
<td><span t-field="doc.partner_id.name"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Address</td>
|
||||
<td>
|
||||
<span t-field="doc.partner_id" t-options="{'widget': 'contact', 'fields': ['address'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Tracking Reference</td>
|
||||
<td><span t-esc="doc.tracking_ref or '-'"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Processes -->
|
||||
<t t-if="doc.process_type_ids">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr><th style="background-color: #0066a1; color: white;">PROCESSES APPLIED</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<t t-foreach="doc.process_type_ids" t-as="pt">
|
||||
<span t-out="pt.name"/>
|
||||
<t t-if="not pt_last">, </t>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Certification statement -->
|
||||
<div class="highlight-box">
|
||||
This certifies that the above items were processed in accordance with
|
||||
applicable specifications and meet all requirements as stated in the
|
||||
purchase order. All work was performed in compliance with the quality
|
||||
management system.
|
||||
</div>
|
||||
|
||||
<!-- Notes -->
|
||||
<t t-if="doc.notes">
|
||||
<table class="bordered">
|
||||
<tr class="section-row"><td>NOTES</td></tr>
|
||||
<tr><td><t t-out="doc.notes"/></td></tr>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Signature block -->
|
||||
<div class="row" style="margin-top: 30px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Quality Manager (Signature)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Date</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE (legacy id `report_coc` kept for existing bindings) -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_coc">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
@@ -111,4 +234,5 @@
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
380
fusion_plating/fusion_plating_reports/report/report_fp_bol.xml
Normal file
380
fusion_plating/fusion_plating_reports/report/report_fp_bol.xml
Normal file
@@ -0,0 +1,380 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Fusion Plating — Bill of Lading (Portrait + Landscape).
|
||||
Binds to fusion.plating.delivery. Includes shipper, consignee, carrier,
|
||||
cargo description, special instructions, and sign-off lines.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_bol_portrait">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_portrait_styles"/>
|
||||
<div class="fp-report">
|
||||
<div class="page">
|
||||
|
||||
<h4 class="text-center" style="text-align: center;">
|
||||
BILL OF LADING
|
||||
</h4>
|
||||
<div class="text-center" style="text-align: center; margin-bottom: 10px;">
|
||||
<strong>BoL #: <span t-field="doc.name"/></strong>
|
||||
</div>
|
||||
|
||||
<!-- Shipper / Consignee -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">SHIPPER</th>
|
||||
<th style="width: 50%;">CONSIGNEE</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 90px;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<t t-if="doc.source_facility_id">
|
||||
<em t-field="doc.source_facility_id.name"/><br/>
|
||||
</t>
|
||||
<div t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 90px;">
|
||||
<strong><span t-field="doc.partner_id.name"/></strong><br/>
|
||||
<t t-set="dest" t-value="doc.delivery_address_id or doc.partner_id"/>
|
||||
<div t-field="dest"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
<t t-if="doc.contact_name">
|
||||
<strong>Attn: </strong><span t-field="doc.contact_name"/><br/>
|
||||
</t>
|
||||
<t t-if="doc.contact_phone">
|
||||
<strong>Phone: </strong><span t-field="doc.contact_phone"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Shipment info -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 33%;">SHIP DATE</th>
|
||||
<th class="info-header" style="width: 33%;">DRIVER</th>
|
||||
<th class="info-header" style="width: 34%;">VEHICLE</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.scheduled_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center">
|
||||
<t t-if="doc.assigned_driver_id">
|
||||
<span t-field="doc.assigned_driver_id.name"/>
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="doc.vehicle_id">
|
||||
<span t-field="doc.vehicle_id"/>
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Job ref / TDG -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 50%;">JOB REFERENCE</th>
|
||||
<th class="info-header" style="width: 50%;">DANGEROUS GOODS (TDG)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="doc.job_ref or '-'"/></td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.tdg_required" class="status-warning">TDG REQUIRED</span>
|
||||
<span t-else="" class="status-ok">No TDG</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Cargo description -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="4" style="background-color: #0066a1; color: white;">CARGO DESCRIPTION</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width: 12%;">PACKAGES</th>
|
||||
<th class="text-start" style="width: 58%;">DESCRIPTION OF GOODS</th>
|
||||
<th style="width: 15%;">WEIGHT</th>
|
||||
<th style="width: 15%;">CLASS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">1</td>
|
||||
<td>
|
||||
Plated parts — Job <span t-esc="doc.job_ref or doc.name"/>
|
||||
<t t-if="doc.notes">
|
||||
<br/><span t-field="doc.notes"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-center">—</td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.tdg_required">TDG</span>
|
||||
<span t-else="">NON-HAZ</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Certificate + Packing list refs -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 50%;">CoC ATTACHED</th>
|
||||
<th class="info-header" style="width: 50%;">PACKING LIST</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.coc_attachment_id" class="status-ok">✓ Attached</span>
|
||||
<span t-else="">—</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.packing_list_attachment_id" class="status-ok">✓ Attached</span>
|
||||
<span t-else="">—</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Certification statement -->
|
||||
<div class="highlight-box" style="margin-top: 10px;">
|
||||
This is to certify that the above-named materials are properly classified,
|
||||
packaged, marked, and labelled, and are in proper condition for transportation
|
||||
according to the applicable regulations of the Department of Transportation.
|
||||
</div>
|
||||
|
||||
<!-- Sign off -->
|
||||
<div class="row" style="margin-top: 20px;">
|
||||
<div class="col-4">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Shipper (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Carrier / Driver (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Consignee (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_bol_landscape">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_landscape_styles"/>
|
||||
<div class="fp-landscape">
|
||||
<div class="page">
|
||||
|
||||
<h2 style="text-align: center;">BILL OF LADING</h2>
|
||||
<div class="text-center" style="text-align: center; margin-bottom: 10px;">
|
||||
<strong>BoL #: <span t-field="doc.name"/></strong>
|
||||
</div>
|
||||
|
||||
<!-- Shipper / Consignee -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">SHIPPER</th>
|
||||
<th style="width: 50%;">CONSIGNEE</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 100px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<t t-if="doc.source_facility_id">
|
||||
<em t-field="doc.source_facility_id.name"/><br/>
|
||||
</t>
|
||||
<div t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 100px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.partner_id.name"/></strong><br/>
|
||||
<t t-set="dest" t-value="doc.delivery_address_id or doc.partner_id"/>
|
||||
<div t-field="dest"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
<t t-if="doc.contact_name">
|
||||
<strong>Attn: </strong><span t-field="doc.contact_name"/><br/>
|
||||
</t>
|
||||
<t t-if="doc.contact_phone">
|
||||
<strong>Phone: </strong><span t-field="doc.contact_phone"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Shipment info (wide) -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SHIP DATE</th>
|
||||
<th>DRIVER</th>
|
||||
<th>VEHICLE</th>
|
||||
<th>JOB REFERENCE</th>
|
||||
<th>TDG</th>
|
||||
<th>STATUS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.scheduled_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center">
|
||||
<t t-if="doc.assigned_driver_id"><span t-field="doc.assigned_driver_id.name"/></t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="doc.vehicle_id"><span t-field="doc.vehicle_id"/></t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
<td class="text-center"><span t-esc="doc.job_ref or '-'"/></td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.tdg_required" class="status-warning">REQUIRED</span>
|
||||
<span t-else="" class="status-ok">None</span>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="doc.state"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Cargo description -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="6" style="background-color: #0066a1; color: white;">CARGO DESCRIPTION</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width: 10%;">PACKAGES</th>
|
||||
<th class="text-start" style="width: 40%;">DESCRIPTION OF GOODS</th>
|
||||
<th style="width: 12%;">QTY</th>
|
||||
<th style="width: 12%;">WEIGHT</th>
|
||||
<th style="width: 12%;">CLASS</th>
|
||||
<th style="width: 14%;">SPECIAL HANDLING</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">1</td>
|
||||
<td>
|
||||
Plated parts — Job <span t-esc="doc.job_ref or doc.name"/>
|
||||
<t t-if="doc.notes">
|
||||
<br/><span t-field="doc.notes"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-center">—</td>
|
||||
<td class="text-center">—</td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.tdg_required">TDG</span>
|
||||
<span t-else="">NON-HAZ</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.tdg_required" class="status-warning">TDG HANDLING</span>
|
||||
<span t-else="">Standard</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Attachment refs -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>CoC</th>
|
||||
<th>PACKING LIST</th>
|
||||
<th>CUSTODY EVENTS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.coc_attachment_id" class="status-ok">✓ Attached</span>
|
||||
<span t-else="">—</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.packing_list_attachment_id" class="status-ok">✓ Attached</span>
|
||||
<span t-else="">—</span>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="doc.custody_event_count"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Certification -->
|
||||
<div class="highlight-box" style="margin-top: 10px;">
|
||||
This is to certify that the above-named materials are properly classified,
|
||||
packaged, marked, and labelled, and are in proper condition for transportation
|
||||
according to the applicable regulations of the Department of Transportation.
|
||||
</div>
|
||||
|
||||
<!-- Sign off -->
|
||||
<div class="row" style="margin-top: 20px;">
|
||||
<div class="col-4">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Shipper (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Carrier / Driver (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Consignee (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,420 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Fusion Plating — Invoice (Portrait + Landscape).
|
||||
Binds to account.move. Includes invoice strategy, deposit context,
|
||||
payment details, and amount due.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_invoice_portrait">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)"/>
|
||||
<t t-call="fusion_plating_reports.fp_portrait_styles"/>
|
||||
<div class="fp-report">
|
||||
<div class="page">
|
||||
|
||||
<h4>
|
||||
<span t-if="doc.move_type == 'out_invoice' and doc.state == 'posted'">Invoice </span>
|
||||
<span t-elif="doc.move_type == 'out_invoice' and doc.state == 'draft'">Draft Invoice </span>
|
||||
<span t-elif="doc.move_type == 'out_refund'">Credit Note </span>
|
||||
<span t-elif="doc.move_type == 'in_invoice'">Vendor Bill </span>
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<!-- Billing / Shipping -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">BILLING ADDRESS</th>
|
||||
<th style="width: 50%;">DELIVERY ADDRESS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px;">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 70px;">
|
||||
<t t-if="doc.partner_shipping_id">
|
||||
<div t-field="doc.partner_shipping_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone'], 'no_marker': True}"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address'], 'no_marker': True}"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Invoice info -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 25%;">INVOICE DATE</th>
|
||||
<th class="info-header" style="width: 25%;">DUE DATE</th>
|
||||
<th class="info-header" style="width: 25%;">SOURCE</th>
|
||||
<th class="info-header" style="width: 25%;">SALES REP</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.invoice_date"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_date_due"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_origin"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_user_id"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Lines -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 12%;">SKU</th>
|
||||
<th class="text-start" style="width: 40%;">DESCRIPTION</th>
|
||||
<th style="width: 8%;">QTY</th>
|
||||
<th style="width: 8%;">UOM</th>
|
||||
<th style="width: 12%;">UNIT PRICE</th>
|
||||
<th style="width: 8%;">TAXES</th>
|
||||
<th style="width: 12%;">AMOUNT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.invoice_line_ids" t-as="line">
|
||||
<t t-if="line.display_type == 'line_section'">
|
||||
<tr class="section-row"><td colspan="7"><strong t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="line.display_type == 'line_note'">
|
||||
<tr class="note-row"><td colspan="7"><span t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="not line.display_type">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td>
|
||||
<t t-set="clean_name" t-value="line.name"/>
|
||||
<t t-if="line.name and '] ' in line.name">
|
||||
<t t-set="clean_name" t-value="line.name.split('] ', 1)[1]"/>
|
||||
</t>
|
||||
<span t-esc="clean_name"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(line.quantity) if line.quantity == int(line.quantity) else line.quantity"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="line.product_uom_id"/></td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_unit" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-esc="', '.join([(tax.invoice_label or tax.name) for tax in line.tax_ids]) or '-'"/>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_subtotal" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Terms + Totals -->
|
||||
<div class="row" style="margin-top: 15px;">
|
||||
<div class="col-6">
|
||||
<t t-if="doc.invoice_payment_term_id.note">
|
||||
<strong>Payment Terms:</strong><br/>
|
||||
<span t-field="doc.invoice_payment_term_id.note"/>
|
||||
</t>
|
||||
<t t-if="doc.payment_reference">
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Payment Reference:</strong>
|
||||
<span t-field="doc.payment_reference"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-6" style="text-align: right;">
|
||||
<table class="totals-table" style="width: auto; margin-left: auto;">
|
||||
<tr>
|
||||
<td style="min-width: 150px;">Subtotal</td>
|
||||
<td class="text-end" style="min-width: 110px;">
|
||||
<span t-field="doc.amount_untaxed" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taxes</td>
|
||||
<td class="text-end">
|
||||
<span t-field="doc.amount_tax" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="background-color: #eaf2f8;">
|
||||
<td><strong>Grand Total</strong></td>
|
||||
<td class="text-end"><strong>
|
||||
<span t-field="doc.amount_total" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
<t t-if="doc.amount_residual and doc.amount_residual != doc.amount_total">
|
||||
<tr>
|
||||
<td><strong>Amount Due</strong></td>
|
||||
<td class="text-end"><strong>
|
||||
<span t-field="doc.amount_residual" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Paid stamp -->
|
||||
<t t-if="doc.payment_state == 'paid'">
|
||||
<div style="margin-top: 15px; text-align: center;">
|
||||
<span class="paid-stamp">PAID</span>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Notes -->
|
||||
<t t-if="doc.narration">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.narration"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_invoice_landscape">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)"/>
|
||||
<t t-call="fusion_plating_reports.fp_landscape_styles"/>
|
||||
<div class="fp-landscape">
|
||||
<div class="page">
|
||||
|
||||
<h2 style="text-align: left;">
|
||||
<span t-if="doc.move_type == 'out_invoice' and doc.state == 'posted'">Invoice </span>
|
||||
<span t-elif="doc.move_type == 'out_invoice' and doc.state == 'draft'">Draft Invoice </span>
|
||||
<span t-elif="doc.move_type == 'out_refund'">Credit Note </span>
|
||||
<span t-elif="doc.move_type == 'in_invoice'">Vendor Bill </span>
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
|
||||
<!-- Billing / Shipping -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">BILLING ADDRESS</th>
|
||||
<th style="width: 50%;">DELIVERY ADDRESS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<t t-if="doc.partner_shipping_id">
|
||||
<div t-field="doc.partner_shipping_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone'], 'no_marker': True}"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address'], 'no_marker': True}"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Invoice info (wide) -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>INVOICE DATE</th>
|
||||
<th>DUE DATE</th>
|
||||
<th>SOURCE</th>
|
||||
<th>SALES REP</th>
|
||||
<th>PAYMENT REF</th>
|
||||
<th>CURRENCY</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.invoice_date"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_date_due"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_origin"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_user_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.payment_reference or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.currency_id.name"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Lines -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%;">SKU</th>
|
||||
<th class="text-start" style="width: 32%;">DESCRIPTION</th>
|
||||
<th style="width: 8%;">QTY</th>
|
||||
<th style="width: 8%;">UOM</th>
|
||||
<th style="width: 12%;">UNIT PRICE</th>
|
||||
<th style="width: 10%;">DISCOUNT</th>
|
||||
<th style="width: 10%;">TAXES</th>
|
||||
<th style="width: 10%;">AMOUNT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.invoice_line_ids" t-as="line">
|
||||
<t t-if="line.display_type == 'line_section'">
|
||||
<tr class="section-row"><td colspan="8"><strong t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="line.display_type == 'line_note'">
|
||||
<tr class="note-row"><td colspan="8"><span t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="not line.display_type">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td>
|
||||
<t t-set="clean_name" t-value="line.name"/>
|
||||
<t t-if="line.name and '] ' in line.name">
|
||||
<t t-set="clean_name" t-value="line.name.split('] ', 1)[1]"/>
|
||||
</t>
|
||||
<span t-esc="clean_name"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(line.quantity) if line.quantity == int(line.quantity) else line.quantity"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="line.product_uom_id"/></td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_unit" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="line.discount"><span t-esc="line.discount"/>%</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-esc="', '.join([(tax.invoice_label or tax.name) for tax in line.tax_ids]) or '-'"/>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_subtotal" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Terms + Totals -->
|
||||
<div class="row" style="margin-top: 15px;">
|
||||
<div class="col-7">
|
||||
<t t-if="doc.invoice_payment_term_id.note">
|
||||
<strong>Payment Terms:</strong><br/>
|
||||
<span t-field="doc.invoice_payment_term_id.note"/>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-5" style="text-align: right;">
|
||||
<table class="totals-table" style="width: auto; margin-left: auto;">
|
||||
<tr>
|
||||
<td style="min-width: 200px;">Subtotal</td>
|
||||
<td class="text-end" style="min-width: 150px;">
|
||||
<span t-field="doc.amount_untaxed" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taxes</td>
|
||||
<td class="text-end">
|
||||
<span t-field="doc.amount_tax" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="background-color: #eaf2f8;">
|
||||
<td><strong>Grand Total</strong></td>
|
||||
<td class="text-end"><strong>
|
||||
<span t-field="doc.amount_total" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
<t t-if="doc.amount_residual and doc.amount_residual != doc.amount_total">
|
||||
<tr>
|
||||
<td><strong>Amount Due</strong></td>
|
||||
<td class="text-end"><strong>
|
||||
<span t-field="doc.amount_residual" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Paid stamp -->
|
||||
<t t-if="doc.payment_state == 'paid'">
|
||||
<div style="margin-top: 15px; text-align: center;">
|
||||
<span class="paid-stamp">PAID</span>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Payment history -->
|
||||
<t t-if="doc.payment_state != 'invoicing_legacy'">
|
||||
<t t-set="payments_vals" t-value="doc.sudo().invoice_payments_widget and doc.sudo().invoice_payments_widget.get('content') or []"/>
|
||||
<t t-if="payments_vals">
|
||||
<table class="bordered" style="margin-top: 15px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="3" style="background-color: #28a745; color: white;">
|
||||
<t t-if="doc.payment_state == 'paid'">✓ PAYMENT DETAILS — PAID IN FULL</t>
|
||||
<t t-elif="doc.payment_state == 'partial'">PAYMENT DETAILS — PARTIALLY PAID</t>
|
||||
<t t-else="">PAYMENT DETAILS</t>
|
||||
</th>
|
||||
</tr>
|
||||
<tr style="background-color: #f5f5f5;">
|
||||
<th style="width: 30%;">Date</th>
|
||||
<th style="width: 40%;">Payment Method</th>
|
||||
<th style="width: 30%;" class="text-end">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="payments_vals" t-as="pv">
|
||||
<tr t-if="not pv.get('is_exchange')">
|
||||
<td><span t-out="pv.get('date')" t-options='{"widget": "date"}'/></td>
|
||||
<td><span t-out="pv.get('payment_method_name') or '-'"/></td>
|
||||
<td class="text-end">
|
||||
<span t-out="pv.get('amount')" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Notes -->
|
||||
<t t-if="doc.narration">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.narration"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,280 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Fusion Plating — Packing Slip / Shipping Confirmation (Portrait + Landscape).
|
||||
Binds to stock.picking. Shows parts, quantities, lot/serial tracking,
|
||||
and a receiver sign-off.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_packing_slip_portrait">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_portrait_styles"/>
|
||||
<div class="fp-report">
|
||||
<div class="page">
|
||||
|
||||
<h4>
|
||||
Packing Slip —
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<!-- From / To -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">FROM</th>
|
||||
<th style="width: 50%;">SHIP TO</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 80px;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<div t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 80px;">
|
||||
<strong><span t-field="doc.partner_id.name"/></strong><br/>
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Shipment info -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 25%;">SHIP DATE</th>
|
||||
<th class="info-header" style="width: 25%;">SOURCE</th>
|
||||
<th class="info-header" style="width: 25%;">OPERATION</th>
|
||||
<th class="info-header" style="width: 25%;">CARRIER</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.scheduled_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-esc="doc.origin or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.picking_type_id"/></td>
|
||||
<td class="text-center">
|
||||
<t t-if="'carrier_id' in doc._fields and doc.carrier_id">
|
||||
<span t-field="doc.carrier_id"/>
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Products -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 12%;">SKU</th>
|
||||
<th class="text-start" style="width: 44%;">PRODUCT</th>
|
||||
<th style="width: 12%;">QTY</th>
|
||||
<th style="width: 10%;">UOM</th>
|
||||
<th style="width: 22%;">LOT / SERIAL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.move_ids_without_package" t-as="move">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="move.product_id.default_code or ''"/></td>
|
||||
<td><span t-field="move.product_id"/></td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(move.quantity) if move.quantity == int(move.quantity) else move.quantity"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="move.product_uom"/></td>
|
||||
<td>
|
||||
<t t-foreach="move.move_line_ids" t-as="ml">
|
||||
<t t-if="ml.lot_id">
|
||||
<span t-field="ml.lot_id.name"/><br/>
|
||||
</t>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Notes -->
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Sign off -->
|
||||
<div class="row" style="margin-top: 30px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Shipper (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Receiver (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_packing_slip_landscape">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_landscape_styles"/>
|
||||
<div class="fp-landscape">
|
||||
<div class="page">
|
||||
|
||||
<h2 style="text-align: left;">
|
||||
Packing Slip —
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
|
||||
<!-- From / To -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">FROM</th>
|
||||
<th style="width: 50%;">SHIP TO</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 80px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<div t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 80px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.partner_id.name"/></strong><br/>
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Shipment info -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SHIP DATE</th>
|
||||
<th>SOURCE</th>
|
||||
<th>OPERATION</th>
|
||||
<th>CARRIER</th>
|
||||
<th>TRACKING REF</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.scheduled_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-esc="doc.origin or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.picking_type_id"/></td>
|
||||
<td class="text-center">
|
||||
<t t-if="'carrier_id' in doc._fields and doc.carrier_id">
|
||||
<span t-field="doc.carrier_id"/>
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="'carrier_tracking_ref' in doc._fields">
|
||||
<span t-esc="doc.carrier_tracking_ref or '-'"/>
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Products -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%;">SKU</th>
|
||||
<th class="text-start" style="width: 34%;">PRODUCT</th>
|
||||
<th style="width: 10%;">ORDERED</th>
|
||||
<th style="width: 10%;">DONE</th>
|
||||
<th style="width: 8%;">UOM</th>
|
||||
<th style="width: 14%;">LOT / SERIAL</th>
|
||||
<th style="width: 14%;">NOTES</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.move_ids_without_package" t-as="move">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="move.product_id.default_code or ''"/></td>
|
||||
<td><span t-field="move.product_id"/></td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(move.product_uom_qty) if move.product_uom_qty == int(move.product_uom_qty) else move.product_uom_qty"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(move.quantity) if move.quantity == int(move.quantity) else move.quantity"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="move.product_uom"/></td>
|
||||
<td>
|
||||
<t t-foreach="move.move_line_ids" t-as="ml">
|
||||
<t t-if="ml.lot_id">
|
||||
<span t-field="ml.lot_id.name"/><br/>
|
||||
</t>
|
||||
</t>
|
||||
</td>
|
||||
<td/>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Notes -->
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Sign off -->
|
||||
<div class="row" style="margin-top: 30px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Shipper (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Receiver (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,282 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Fusion Plating — Payment Receipt (Portrait + Landscape).
|
||||
Binds to account.payment. Shows amount paid, method, reference,
|
||||
applied invoices, and a "PAID" stamp.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_receipt_portrait">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_portrait_styles"/>
|
||||
<div class="fp-report">
|
||||
<div class="page">
|
||||
|
||||
<h4 style="text-align: center;">
|
||||
PAYMENT RECEIPT
|
||||
</h4>
|
||||
<div class="text-center" style="text-align: center; margin-bottom: 15px;">
|
||||
<strong>Receipt #: <span t-field="doc.name"/></strong>
|
||||
</div>
|
||||
|
||||
<!-- Paid stamp -->
|
||||
<div class="text-center" style="text-align: center; margin: 20px 0;">
|
||||
<span class="paid-stamp">✓ RECEIVED</span>
|
||||
</div>
|
||||
|
||||
<!-- From / Received by -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">RECEIVED FROM</th>
|
||||
<th style="width: 50%;">RECEIVED BY</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px;">
|
||||
<strong><span t-field="doc.partner_id.name"/></strong><br/>
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 70px;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<div t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Payment details -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2" style="background-color: #0066a1; color: white;">PAYMENT DETAILS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 40%; background-color: #f5f5f5; font-weight: bold;">Payment Date</td>
|
||||
<td><span t-field="doc.date" t-options="{'widget': 'date'}"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Payment Method</td>
|
||||
<td><span t-field="doc.payment_method_line_id"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Journal</td>
|
||||
<td><span t-field="doc.journal_id"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Reference / Memo</td>
|
||||
<td><span t-esc="doc.ref or doc.memo or '-'"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Amount</td>
|
||||
<td style="font-size: 14pt;"><strong>
|
||||
<span t-field="doc.amount" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Applied invoices -->
|
||||
<t t-if="doc.reconciled_invoice_ids">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="3" style="background-color: #0066a1; color: white;">APPLIED TO INVOICES</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width: 34%;">INVOICE #</th>
|
||||
<th style="width: 33%;">DATE</th>
|
||||
<th style="width: 33%;">AMOUNT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.reconciled_invoice_ids" t-as="inv">
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="inv.name"/></td>
|
||||
<td class="text-center"><span t-field="inv.invoice_date"/></td>
|
||||
<td class="text-end">
|
||||
<span t-field="inv.amount_total" t-options='{"widget": "monetary", "display_currency": inv.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Thank you -->
|
||||
<div class="highlight-box" style="margin-top: 20px; text-align: center;">
|
||||
Thank you for your payment. This receipt confirms that payment has
|
||||
been received in full for the amount stated above.
|
||||
</div>
|
||||
|
||||
<!-- Sign off -->
|
||||
<div class="row" style="margin-top: 30px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Received by (Signature)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Date</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_receipt_landscape">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_landscape_styles"/>
|
||||
<div class="fp-landscape">
|
||||
<div class="page">
|
||||
|
||||
<h2 style="text-align: center;">PAYMENT RECEIPT</h2>
|
||||
<div class="text-center" style="text-align: center; margin-bottom: 15px;">
|
||||
<strong>Receipt #: <span t-field="doc.name"/></strong>
|
||||
</div>
|
||||
|
||||
<!-- Paid stamp -->
|
||||
<div class="text-center" style="text-align: center; margin: 20px 0;">
|
||||
<span class="paid-stamp">✓ RECEIVED</span>
|
||||
</div>
|
||||
|
||||
<!-- From / Received by -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">RECEIVED FROM</th>
|
||||
<th style="width: 50%;">RECEIVED BY</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 80px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.partner_id.name"/></strong><br/>
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 80px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<div t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Payment details (wide) -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PAYMENT DATE</th>
|
||||
<th>METHOD</th>
|
||||
<th>JOURNAL</th>
|
||||
<th>REFERENCE</th>
|
||||
<th>CURRENCY</th>
|
||||
<th>AMOUNT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-field="doc.payment_method_line_id"/></td>
|
||||
<td class="text-center"><span t-field="doc.journal_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.ref or doc.memo or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.currency_id.name"/></td>
|
||||
<td class="text-end" style="font-size: 13pt;"><strong>
|
||||
<span t-field="doc.amount" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Applied invoices -->
|
||||
<t t-if="doc.reconciled_invoice_ids">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="5" style="background-color: #0066a1; color: white;">APPLIED TO INVOICES</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width: 20%;">INVOICE #</th>
|
||||
<th style="width: 20%;">DATE</th>
|
||||
<th style="width: 20%;">DUE DATE</th>
|
||||
<th style="width: 20%;">TOTAL</th>
|
||||
<th style="width: 20%;">PAYMENT STATE</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.reconciled_invoice_ids" t-as="inv">
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="inv.name"/></td>
|
||||
<td class="text-center"><span t-field="inv.invoice_date"/></td>
|
||||
<td class="text-center"><span t-field="inv.invoice_date_due"/></td>
|
||||
<td class="text-end">
|
||||
<span t-field="inv.amount_total" t-options='{"widget": "monetary", "display_currency": inv.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-if="inv.payment_state == 'paid'" class="status-ok">Paid</span>
|
||||
<span t-elif="inv.payment_state == 'partial'" class="status-warning">Partial</span>
|
||||
<span t-else=""><span t-field="inv.payment_state"/></span>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Thank you -->
|
||||
<div class="highlight-box" style="margin-top: 20px; text-align: center;">
|
||||
Thank you for your payment. This receipt confirms that payment has
|
||||
been received in full for the amount stated above.
|
||||
</div>
|
||||
|
||||
<!-- Sign off -->
|
||||
<div class="row" style="margin-top: 30px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Received by (Signature)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Date</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
464
fusion_plating/fusion_plating_reports/report/report_fp_sale.xml
Normal file
464
fusion_plating/fusion_plating_reports/report/report_fp_sale.xml
Normal file
@@ -0,0 +1,464 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Fusion Plating — Quotation / Sales Order (Portrait + Landscape)
|
||||
Renders the same sale.order with a title that flips between
|
||||
"Quotation" (draft/sent) and "Sales Order" (confirmed/done).
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_sale_portrait">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)"/>
|
||||
<t t-call="fusion_plating_reports.fp_portrait_styles"/>
|
||||
<div class="fp-report">
|
||||
<div class="page">
|
||||
|
||||
<!-- Title -->
|
||||
<h4>
|
||||
<span t-if="doc.state in ['draft','sent']">Quotation </span>
|
||||
<span t-else="">Sales Order </span>
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<!-- Billing / Shipping -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">BILLING ADDRESS</th>
|
||||
<th style="width: 50%;">SHIPPING ADDRESS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px;">
|
||||
<div t-field="doc.partner_invoice_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 70px;">
|
||||
<div t-field="doc.partner_shipping_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Order info -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 20%;">ORDER DATE</th>
|
||||
<th class="info-header" style="width: 20%;">EXPIRATION</th>
|
||||
<th class="info-header" style="width: 20%;">SALESPERSON</th>
|
||||
<th class="info-header" style="width: 20%;">CUSTOMER PO #</th>
|
||||
<th class="info-header" style="width: 20%;">RUSH</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.date_order" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-field="doc.validity_date"/></td>
|
||||
<td class="text-center"><span t-field="doc.user_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.x_fc_po_number or '-'"/></td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.x_fc_rush_order" class="status-warning">RUSH</span>
|
||||
<span t-else="">Standard</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Plating info -->
|
||||
<t t-if="doc.x_fc_part_catalog_id or doc.x_fc_coating_config_id or doc.x_fc_delivery_method">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 34%;">PART</th>
|
||||
<th class="info-header" style="width: 33%;">COATING CONFIG</th>
|
||||
<th class="info-header" style="width: 33%;">DELIVERY METHOD</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.x_fc_part_catalog_id"/></td>
|
||||
<td class="text-center"><span t-field="doc.x_fc_coating_config_id"/></td>
|
||||
<td class="text-center">
|
||||
<t t-set="dm" t-value="dict(doc._fields['x_fc_delivery_method'].selection).get(doc.x_fc_delivery_method, '-')"/>
|
||||
<span t-esc="dm"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Order lines -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%;">SKU</th>
|
||||
<th class="text-start" style="width: 40%;">DESCRIPTION</th>
|
||||
<th style="width: 8%;">QTY</th>
|
||||
<th style="width: 8%;">UOM</th>
|
||||
<th style="width: 12%;">UNIT PRICE</th>
|
||||
<th style="width: 10%;">TAXES</th>
|
||||
<th style="width: 12%;">AMOUNT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.order_line" t-as="line">
|
||||
<t t-if="line.display_type == 'line_section'">
|
||||
<tr class="section-row"><td colspan="7"><strong t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="line.display_type == 'line_note'">
|
||||
<tr class="note-row"><td colspan="7"><span t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="not line.display_type">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td>
|
||||
<t t-set="clean_name" t-value="line.name"/>
|
||||
<t t-if="line.name and '] ' in line.name">
|
||||
<t t-set="clean_name" t-value="line.name.split('] ', 1)[1]"/>
|
||||
</t>
|
||||
<span t-esc="clean_name"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(line.product_uom_qty) if line.product_uom_qty == int(line.product_uom_qty) else line.product_uom_qty"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="line.product_uom"/></td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_unit" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-esc="', '.join([(tax.invoice_label or tax.name) for tax in line.tax_ids]) or '-'"/>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_subtotal" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Terms + Totals -->
|
||||
<div class="row" style="margin-top: 15px;">
|
||||
<div class="col-6">
|
||||
<t t-if="doc.payment_term_id.note">
|
||||
<strong>Payment Terms:</strong><br/>
|
||||
<span t-field="doc.payment_term_id.note"/>
|
||||
</t>
|
||||
<t t-if="doc.x_fc_invoice_strategy">
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Invoice Strategy: </strong>
|
||||
<t t-set="inv_strat" t-value="dict(doc._fields['x_fc_invoice_strategy'].selection).get(doc.x_fc_invoice_strategy, '-')"/>
|
||||
<span t-esc="inv_strat"/>
|
||||
<t t-if="doc.x_fc_invoice_strategy == 'deposit' and doc.x_fc_deposit_percent">
|
||||
(<span t-esc="doc.x_fc_deposit_percent"/>%)
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-6" style="text-align: right;">
|
||||
<table class="totals-table" style="width: auto; margin-left: auto;">
|
||||
<tr>
|
||||
<td style="min-width: 150px;">Subtotal</td>
|
||||
<td class="text-end" style="min-width: 110px;">
|
||||
<span t-field="doc.amount_untaxed" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taxes</td>
|
||||
<td class="text-end">
|
||||
<span t-field="doc.amount_tax" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="background-color: #eaf2f8;">
|
||||
<td><strong>Grand Total</strong></td>
|
||||
<td class="text-end"><strong>
|
||||
<span t-field="doc.amount_total" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Terms and Conditions -->
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Terms and Conditions:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Signature -->
|
||||
<div class="row" style="margin-top: 25px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Customer Acceptance (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<t t-if="doc.signature">
|
||||
<img t-att-src="image_data_uri(doc.signature)" style="max-height: 3cm; max-width: 8cm;"/><br/>
|
||||
<span t-field="doc.signed_by"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="sig-line"/>
|
||||
</t>
|
||||
<div class="small-muted">Authorized Representative</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_sale_landscape">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)"/>
|
||||
<t t-call="fusion_plating_reports.fp_landscape_styles"/>
|
||||
<div class="fp-landscape">
|
||||
<div class="page">
|
||||
|
||||
<!-- Title -->
|
||||
<h2 style="text-align: left;">
|
||||
<span t-if="doc.state in ['draft','sent']">Quotation </span>
|
||||
<span t-else="">Sales Order </span>
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
|
||||
<!-- Billing / Shipping -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">BILLING ADDRESS</th>
|
||||
<th style="width: 50%;">SHIPPING ADDRESS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<div t-field="doc.partner_invoice_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<div t-field="doc.partner_shipping_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Order info (wide) -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ORDER DATE</th>
|
||||
<th>EXPIRATION</th>
|
||||
<th>SALESPERSON</th>
|
||||
<th>CUSTOMER PO #</th>
|
||||
<th>DELIVERY METHOD</th>
|
||||
<th>RUSH</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.date_order" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-field="doc.validity_date"/></td>
|
||||
<td class="text-center"><span t-field="doc.user_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.x_fc_po_number or '-'"/></td>
|
||||
<td class="text-center">
|
||||
<t t-set="dm" t-value="dict(doc._fields['x_fc_delivery_method'].selection).get(doc.x_fc_delivery_method, '-')"/>
|
||||
<span t-esc="dm"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-if="doc.x_fc_rush_order" class="status-warning">RUSH</span>
|
||||
<span t-else="">Standard</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Plating details -->
|
||||
<t t-if="doc.x_fc_part_catalog_id or doc.x_fc_coating_config_id">
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PART CATALOG</th>
|
||||
<th>COATING CONFIGURATION</th>
|
||||
<th>INVOICE STRATEGY</th>
|
||||
<th>DEPOSIT %</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.x_fc_part_catalog_id"/></td>
|
||||
<td class="text-center"><span t-field="doc.x_fc_coating_config_id"/></td>
|
||||
<td class="text-center">
|
||||
<t t-set="inv_strat" t-value="dict(doc._fields['x_fc_invoice_strategy'].selection).get(doc.x_fc_invoice_strategy, '-')"/>
|
||||
<span t-esc="inv_strat"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="doc.x_fc_deposit_percent">
|
||||
<span t-esc="doc.x_fc_deposit_percent"/>%
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Order lines -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%;">SKU</th>
|
||||
<th class="text-start" style="width: 32%;">DESCRIPTION</th>
|
||||
<th style="width: 8%;">QTY</th>
|
||||
<th style="width: 8%;">UOM</th>
|
||||
<th style="width: 12%;">UNIT PRICE</th>
|
||||
<th style="width: 10%;">DISCOUNT</th>
|
||||
<th style="width: 10%;">TAXES</th>
|
||||
<th style="width: 10%;">AMOUNT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.order_line" t-as="line">
|
||||
<t t-if="line.display_type == 'line_section'">
|
||||
<tr class="section-row"><td colspan="8"><strong t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="line.display_type == 'line_note'">
|
||||
<tr class="note-row"><td colspan="8"><span t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="not line.display_type">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td>
|
||||
<t t-set="clean_name" t-value="line.name"/>
|
||||
<t t-if="line.name and '] ' in line.name">
|
||||
<t t-set="clean_name" t-value="line.name.split('] ', 1)[1]"/>
|
||||
</t>
|
||||
<span t-esc="clean_name"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(line.product_uom_qty) if line.product_uom_qty == int(line.product_uom_qty) else line.product_uom_qty"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="line.product_uom"/></td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_unit" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="line.discount"><span t-esc="line.discount"/>%</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-esc="', '.join([(tax.invoice_label or tax.name) for tax in line.tax_ids]) or '-'"/>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_subtotal" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Terms + Totals -->
|
||||
<div class="row" style="margin-top: 15px;">
|
||||
<div class="col-7">
|
||||
<t t-if="doc.payment_term_id.note">
|
||||
<strong>Payment Terms:</strong><br/>
|
||||
<span t-field="doc.payment_term_id.note"/>
|
||||
</t>
|
||||
<t t-if="doc.x_fc_invoice_strategy">
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Invoice Strategy: </strong>
|
||||
<t t-set="inv_strat" t-value="dict(doc._fields['x_fc_invoice_strategy'].selection).get(doc.x_fc_invoice_strategy, '-')"/>
|
||||
<span t-esc="inv_strat"/>
|
||||
<t t-if="doc.x_fc_invoice_strategy == 'deposit' and doc.x_fc_deposit_percent">
|
||||
(<span t-esc="doc.x_fc_deposit_percent"/>%)
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="col-5" style="text-align: right;">
|
||||
<table class="totals-table" style="width: auto; margin-left: auto;">
|
||||
<tr>
|
||||
<td style="min-width: 200px;">Subtotal</td>
|
||||
<td class="text-end" style="min-width: 150px;">
|
||||
<span t-field="doc.amount_untaxed" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taxes</td>
|
||||
<td class="text-end">
|
||||
<span t-field="doc.amount_tax" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="background-color: #eaf2f8;">
|
||||
<td><strong>Grand Total</strong></td>
|
||||
<td class="text-end"><strong>
|
||||
<span t-field="doc.amount_total" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Terms and Conditions -->
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Terms and Conditions:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Signature block -->
|
||||
<div class="row" style="margin-top: 25px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Customer Acceptance (Signature / Date)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-box">
|
||||
<t t-if="doc.signature">
|
||||
<img t-att-src="image_data_uri(doc.signature)" style="max-height: 3cm; max-width: 8cm;"/><br/>
|
||||
<span t-field="doc.signed_by"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="sig-line"/>
|
||||
</t>
|
||||
<div class="small-muted">Authorized Representative</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,380 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Fusion Plating — Work Order traveller (Portrait + Landscape).
|
||||
Printed shop-floor sheet with step info, bath/tank, chemistry targets,
|
||||
and sign-off rows.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_work_order_portrait">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_portrait_styles"/>
|
||||
<div class="fp-report">
|
||||
<div class="page">
|
||||
|
||||
<h4>
|
||||
Work Order Traveller —
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<!-- Header info -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header">MO #</th>
|
||||
<th class="info-header">STEP</th>
|
||||
<th class="info-header">WORK CENTRE</th>
|
||||
<th class="info-header">PRIORITY</th>
|
||||
<th class="info-header">STATE</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.production_id.name"/></td>
|
||||
<td class="text-center"><span t-esc="doc.x_fc_step_display or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.workcenter_id"/></td>
|
||||
<td class="text-center">
|
||||
<t t-set="prio" t-value="dict(doc._fields['x_fc_priority'].selection).get(doc.x_fc_priority, 'Normal')"/>
|
||||
<span t-esc="prio"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="doc.state"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Customer / Part -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 50%;">CUSTOMER</th>
|
||||
<th class="info-header" style="width: 50%;">PRODUCT</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span t-field="doc.x_fc_customer_id"/></td>
|
||||
<td><span t-field="doc.product_id"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Sale / Portal links -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 33%;">SALE ORDER</th>
|
||||
<th class="info-header" style="width: 34%;">PORTAL JOB</th>
|
||||
<th class="info-header" style="width: 33%;">QTY TO PRODUCE</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="doc.x_fc_sale_order_name or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.x_fc_portal_job_id"/></td>
|
||||
<td class="text-center"><span t-field="doc.qty_production"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Process parameters -->
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr><th colspan="2" style="background-color: #0066a1; color: white;">PROCESS PARAMETERS</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 35%; background-color: #f5f5f5; font-weight: bold;">Bath</td>
|
||||
<td><span t-field="doc.x_fc_bath_id"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Tank</td>
|
||||
<td><span t-field="doc.x_fc_tank_id"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Rack / Fixture Ref</td>
|
||||
<td><span t-esc="doc.x_fc_rack_ref or '-'"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Target Thickness</td>
|
||||
<td>
|
||||
<t t-if="doc.x_fc_thickness_target">
|
||||
<span t-esc="doc.x_fc_thickness_target"/>
|
||||
<span t-esc="dict(doc._fields['x_fc_thickness_uom'].selection).get(doc.x_fc_thickness_uom, '')"/>
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Dwell Time</td>
|
||||
<td>
|
||||
<t t-if="doc.x_fc_dwell_time_minutes">
|
||||
<span t-esc="doc.x_fc_dwell_time_minutes"/> min
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Facility</td>
|
||||
<td><span t-field="doc.x_fc_facility_id"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Expected Duration</td>
|
||||
<td><span t-esc="doc.duration_expected"/> min</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Operation instructions -->
|
||||
<t t-if="doc.operation_id and doc.operation_id.note">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr><th style="background-color: #0066a1; color: white;">OPERATION INSTRUCTIONS</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><div t-field="doc.operation_id.note"/></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Bath chemistry targets snapshot -->
|
||||
<t t-if="doc.x_fc_bath_id and doc.x_fc_bath_id.target_line_ids">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PARAMETER</th>
|
||||
<th>MIN</th>
|
||||
<th>MAX</th>
|
||||
<th>UOM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.x_fc_bath_id.target_line_ids" t-as="p">
|
||||
<tr>
|
||||
<td><span t-field="p.parameter_id"/></td>
|
||||
<td class="text-center"><span t-esc="p.target_min or '-'"/></td>
|
||||
<td class="text-center"><span t-esc="p.target_max or '-'"/></td>
|
||||
<td class="text-center"><span t-esc="p.uom or '-'"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Sign-off -->
|
||||
<div style="margin-top: 20px;">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="3" style="background-color: #0066a1; color: white;">OPERATOR SIGN-OFF</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width: 40%;">OPERATOR</th>
|
||||
<th style="width: 30%;">DATE / TIME</th>
|
||||
<th style="width: 30%;">INITIALS</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/></tr>
|
||||
<tr><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Notes -->
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Notes / Observations:</strong>
|
||||
<div style="border: 1px solid #000; min-height: 80px; margin-top: 5px;"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fp_work_order_landscape">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="doc">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-call="fusion_plating_reports.fp_landscape_styles"/>
|
||||
<div class="fp-landscape">
|
||||
<div class="page">
|
||||
|
||||
<h2 style="text-align: left;">
|
||||
Work Order Traveller —
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
|
||||
<!-- Header info (wide) -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>MO #</th>
|
||||
<th>STEP</th>
|
||||
<th>WORK CENTRE</th>
|
||||
<th>FACILITY</th>
|
||||
<th>PRIORITY</th>
|
||||
<th>STATE</th>
|
||||
<th>EXPECTED DURATION</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center"><span t-field="doc.production_id.name"/></td>
|
||||
<td class="text-center"><span t-esc="doc.x_fc_step_display or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.workcenter_id"/></td>
|
||||
<td class="text-center"><span t-field="doc.x_fc_facility_id"/></td>
|
||||
<td class="text-center">
|
||||
<t t-set="prio" t-value="dict(doc._fields['x_fc_priority'].selection).get(doc.x_fc_priority, 'Normal')"/>
|
||||
<span t-esc="prio"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="doc.state"/></td>
|
||||
<td class="text-center"><span t-esc="doc.duration_expected"/> min</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Customer / Links -->
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>CUSTOMER</th>
|
||||
<th>PRODUCT</th>
|
||||
<th>SALE ORDER</th>
|
||||
<th>PORTAL JOB</th>
|
||||
<th>QTY</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span t-field="doc.x_fc_customer_id"/></td>
|
||||
<td><span t-field="doc.product_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.x_fc_sale_order_name or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.x_fc_portal_job_id"/></td>
|
||||
<td class="text-center"><span t-field="doc.qty_production"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Process Parameters / Chemistry Targets side-by-side -->
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr><th colspan="2" style="background-color: #0066a1; color: white;">PROCESS PARAMETERS</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 40%; background-color: #f5f5f5; font-weight: bold;">Bath</td>
|
||||
<td><span t-field="doc.x_fc_bath_id"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Tank</td>
|
||||
<td><span t-field="doc.x_fc_tank_id"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Rack / Fixture</td>
|
||||
<td><span t-esc="doc.x_fc_rack_ref or '-'"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Target Thickness</td>
|
||||
<td>
|
||||
<t t-if="doc.x_fc_thickness_target">
|
||||
<span t-esc="doc.x_fc_thickness_target"/>
|
||||
<span t-esc="dict(doc._fields['x_fc_thickness_uom'].selection).get(doc.x_fc_thickness_uom, '')"/>
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #f5f5f5; font-weight: bold;">Dwell Time</td>
|
||||
<td>
|
||||
<t t-if="doc.x_fc_dwell_time_minutes">
|
||||
<span t-esc="doc.x_fc_dwell_time_minutes"/> min
|
||||
</t>
|
||||
<t t-else="">-</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<t t-if="doc.x_fc_bath_id and doc.x_fc_bath_id.target_line_ids">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="4" style="background-color: #0066a1; color: white;">CHEMISTRY TARGETS</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PARAM</th>
|
||||
<th>MIN</th>
|
||||
<th>MAX</th>
|
||||
<th>UOM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="doc.x_fc_bath_id.target_line_ids" t-as="p">
|
||||
<tr>
|
||||
<td><span t-field="p.parameter_id"/></td>
|
||||
<td class="text-center"><span t-esc="p.target_min or '-'"/></td>
|
||||
<td class="text-center"><span t-esc="p.target_max or '-'"/></td>
|
||||
<td class="text-center"><span t-esc="p.uom or '-'"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Operation instructions -->
|
||||
<t t-if="doc.operation_id and doc.operation_id.note">
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr><th style="background-color: #0066a1; color: white;">OPERATION INSTRUCTIONS</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><div t-field="doc.operation_id.note"/></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<!-- Sign-off -->
|
||||
<table class="bordered" style="margin-top: 15px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="5" style="background-color: #0066a1; color: white;">OPERATOR SIGN-OFF</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="width: 25%;">OPERATOR</th>
|
||||
<th style="width: 15%;">DATE</th>
|
||||
<th style="width: 15%;">TIME IN</th>
|
||||
<th style="width: 15%;">TIME OUT</th>
|
||||
<th style="width: 30%;">INITIALS / NOTES</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/></tr>
|
||||
<tr><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/><td class="sig-line"/></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user