fix: invoice template - Bill To address, contrast fix, remove tax-exempt notice

- Suppress base template's centered address (set address=False for all
  three shipping cases) to avoid duplication
- Add proper left-aligned "Bill To" section with full partner address
  using the contact widget before the title bar
- Replace opacity-based dimming in title bar with explicit colors
  (#94a3b8 for labels, #b0bec5 for invoice number sub-line)
- Remove amber tax-exempt notice block

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
metatroncubeswdev 2026-05-18 15:58:13 -04:00
parent 4b37c198b7
commit 2e1af13715

View File

@ -7,20 +7,54 @@
Tax handling
────────────
Current: Under the $30k small-supplier threshold — no HST/GST registered.
When no tax lines are present, an amber "Tax Exempt" notice is shown.
Future: Once incorporated and HST-registered, add tax lines to invoices as
normal. The totals block (account.document_tax_totals) will
automatically render each tax group with its registration number.
Remove/disable the amber notice at that point.
-->
<template id="report_invoice_document_mcs_modern"
inherit_id="account.report_invoice_document">
<!--
Suppress the base template's centered address rendering (set via the
address variable consumed by web.external_layout). We display the
customer address ourselves in a proper "Bill To" section below.
-->
<xpath expr="//div[@name='no_shipping']" position="replace">
<div class="offset-col-6 col-6" name="no_shipping">
<t t-set="address" t-value="False"/>
</div>
</xpath>
<xpath expr="//div[@name='address_same_as_shipping']" position="replace">
<div class="offset-col-6 col-6" name="address_same_as_shipping">
<t t-set="address" t-value="False"/>
</div>
</xpath>
<xpath expr="//div[@name='address_not_same_as_shipping']" position="replace">
<div class="col-6" name="address_not_same_as_shipping">
<t t-set="address" t-value="False"/>
</div>
</xpath>
<!-- ━━━ Main content replacement ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<xpath expr="//div[@class='mt-5 clearfix']" position="replace">
<div class="mt-3">
<div class="page mb-4">
<!-- ━━━ INVOICE TITLE BAR ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<!-- ━━━ BILL TO ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<table style="width:100%;border-collapse:collapse;margin-bottom:16px;">
<tr>
<td style="width:50%;vertical-align:top;padding-right:20px;">
<div style="font-size:9px;font-weight:700;color:#6b7280;letter-spacing:1.2px;text-transform:uppercase;margin-bottom:5px;">Bill To</div>
<div style="font-size:12.5px;color:#1a2e4a;line-height:1.65;">
<div t-field="o.partner_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
</div>
</td>
<td style="width:50%;vertical-align:top;"/>
</tr>
</table>
<!-- ━━━ INVOICE TITLE BAR ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<table style="width:100%;background:#1a2e4a;color:#fff;border-radius:4px;margin-bottom:20px;border-collapse:collapse;">
<tr>
<td style="padding:14px 20px;vertical-align:middle;">
@ -37,35 +71,35 @@
</t>
<t t-else="">PROFORMA INVOICE</t>
</div>
<div t-if="o.name != '/'" style="font-size:12.5px;opacity:.70;margin-top:3px;letter-spacing:.3px;">
<div t-if="o.name != '/'" style="font-size:12.5px;color:#b0bec5;margin-top:3px;letter-spacing:.3px;">
<span t-field="o.name"/>
</div>
</td>
<td style="padding:14px 20px;vertical-align:middle;text-align:right;font-size:12px;white-space:nowrap;">
<div t-if="o.invoice_date">
<span style="opacity:.65;">Invoice Date</span>&#160;
<span style="color:#94a3b8;">Invoice Date</span>&#160;
<strong><span t-field="o.invoice_date"/></strong>
</div>
<div t-if="o.invoice_date_due and o.move_type == 'out_invoice' and o.state == 'posted'"
style="margin-top:5px;">
<span style="opacity:.65;">Due Date</span>&#160;
<span style="color:#94a3b8;">Due Date</span>&#160;
<strong><span t-field="o.invoice_date_due"/></strong>
</div>
<div t-if="o.ref" style="margin-top:5px;">
<span style="opacity:.65;">Reference</span>&#160;
<span style="color:#94a3b8;">Reference</span>&#160;
<span t-field="o.ref"/>
</div>
<div t-if="o.invoice_origin" style="margin-top:5px;">
<span style="opacity:.65;">Source</span>&#160;
<span style="color:#94a3b8;">Source</span>&#160;
<span t-field="o.invoice_origin"/>
</div>
<div t-if="o.invoice_incoterm_id" style="margin-top:5px;">
<span style="opacity:.65;">Incoterm</span>&#160;
<span style="color:#94a3b8;">Incoterm</span>&#160;
<span t-field="o.invoice_incoterm_id.code"/>
<t t-if="o.incoterm_location">&#160;<span t-field="o.incoterm_location"/></t>
</div>
<div t-if="o.partner_id.ref" style="margin-top:5px;">
<span style="opacity:.65;">Client Code</span>&#160;
<span style="color:#94a3b8;">Client Code</span>&#160;
<span t-field="o.partner_id.ref"/>
</div>
</td>
@ -74,7 +108,7 @@
<div class="oe_structure"/>
<!-- ━━━ LINE ITEMS TABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<!-- ━━━ LINE ITEMS TABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<t t-set="display_discount" t-value="any(l.discount for l in o.invoice_line_ids)"/>
<t t-set="lines" t-value="o.invoice_line_ids.sorted(key=lambda l: (-l.sequence, l.date, l.move_name, -l.id), reverse=True)"/>
@ -166,26 +200,12 @@
</tbody>
</table>
<!-- ━━━ BOTTOM SECTION ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<!-- ━━━ BOTTOM SECTION ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
<table style="width:100%;border-collapse:collapse;margin-top:18px;">
<tr>
<!-- ── LEFT: notes, HST notice, payment terms ── -->
<!-- ── LEFT: payment terms, narration, QR ── -->
<td style="width:54%;vertical-align:top;padding-right:20px;">
<!-- Tax-exempt / HST notice -->
<t t-set="has_any_tax" t-value="any(line.tax_ids for line in o.invoice_line_ids)"/>
<div t-if="not has_any_tax"
style="background:#fffbeb;border:1px solid #fcd34d;border-left:4px solid #f59e0b;padding:9px 12px;border-radius:4px;margin-bottom:12px;font-size:11.5px;color:#78350f;line-height:1.55;">
<!--
FUTURE: Once HST-registered after incorporation, remove this block
and add the appropriate tax to each invoice line instead.
The totals section below will then display the HST breakdown
and registration number automatically.
-->
<strong>Tax Exempt</strong> — Metatroncube Software Solutions is not
currently registered for HST/GST. No sales tax is applicable on this invoice.
</div>
<!-- Fiscal position note -->
<div t-if="not is_html_empty(o.fiscal_position_id.note)"
style="font-size:12px;color:#4b5563;margin-bottom:8px;">
@ -240,7 +260,7 @@
<span t-field="o.narration"/>
</div>
<!-- QR code (EPC / payment) -->
<!-- QR code -->
<t t-set="show_qr" t-value="o.display_qr_code and o.amount_residual > 0"/>
<div t-if="not show_qr" name="qr_code_placeholder" class="oe_structure"/>
<div id="qrcode" class="avoid-page-break-inside"
@ -267,11 +287,9 @@
<table class="table table-sm table-borderless avoid-page-break-inside"
style="margin:0;font-size:12.5px;width:100%;">
<!-- Subtotal / tax lines / grand total -->
<t t-set="tax_totals" t-value="o.tax_totals or {}"/>
<t t-call="account.document_tax_totals"/>
<!-- Payments already applied (invoice-with-payments variant) -->
<t t-if="print_with_payments">
<t t-if="o.payment_state != 'invoicing_legacy'">
<t t-set="payments_vals"
@ -306,7 +324,6 @@
</table>
</div>
<!-- Amount in words -->
<div t-if="o.company_id.display_invoice_amount_total_words"
style="font-size:10.5px;color:#9ca3af;text-align:right;margin-top:5px;font-style:italic;">
<span t-field="o.amount_total_words"/>