feat: add mcs_invoice_currency_display addon with modern invoice template
- Suppresses CAD company currency block on foreign-currency invoices - Modern dark navy invoice layout with clean line items table - Amber tax-exempt notice for pre-HST invoices (under $30k threshold) - Structured for easy HST enablement after incorporation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6ef5b53c75
commit
4b37c198b7
1
addons/mcs_invoice_currency_display/__init__.py
Normal file
1
addons/mcs_invoice_currency_display/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import models
|
||||
14
addons/mcs_invoice_currency_display/__manifest__.py
Normal file
14
addons/mcs_invoice_currency_display/__manifest__.py
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
'name': 'MCS Invoice Currency Display Fix',
|
||||
'version': '17.0.1.0.0',
|
||||
'summary': 'Hides the company currency (CAD) totals block on foreign currency invoices',
|
||||
'author': 'Metatroncube Software Solutions',
|
||||
'depends': ['account'],
|
||||
'data': [
|
||||
'views/report_invoice_currency.xml',
|
||||
'views/report_invoice_template.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
1
addons/mcs_invoice_currency_display/models/__init__.py
Normal file
1
addons/mcs_invoice_currency_display/models/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import mcs_invoice_currency_display
|
||||
@ -0,0 +1,10 @@
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class McsInvoiceCurrencyDisplay(models.Model):
|
||||
_name = 'mcs.invoice.currency.display'
|
||||
_description = 'MCS Invoice Currency Display Fix'
|
||||
|
||||
name = fields.Char(string='Name', required=True)
|
||||
active = fields.Boolean(default=True)
|
||||
notes = fields.Text(string='Notes')
|
||||
@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_mcs_invoice_currency_display_user,access.mcs.invoice.currency.display,model_mcs_invoice_currency_display,base.group_user,1,1,1,0
|
||||
|
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="mcs_invoice_currency_display_view_form" model="ir.ui.view">
|
||||
<field name="name">mcs_invoice_currency_display.form</field>
|
||||
<field name="model">mcs.invoice.currency.display</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="MCS Invoice Currency Display Fix">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
<group string="Notes">
|
||||
<field name="notes" nolabel="1"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mcs_invoice_currency_display_view_list" model="ir.ui.view">
|
||||
<field name="name">mcs_invoice_currency_display.list</field>
|
||||
<field name="model">mcs.invoice.currency.display</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="MCS Invoice Currency Display Fix">
|
||||
<field name="name"/>
|
||||
<field name="active"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
13
addons/mcs_invoice_currency_display/views/menus.xml
Normal file
13
addons/mcs_invoice_currency_display/views/menus.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<menuitem id="menu_mcs_invoice_currency_display_root" name="MCS Invoice Currency Display Fix" sequence="100"/>
|
||||
<menuitem id="menu_mcs_invoice_currency_display_main" name="MCS Invoice Currency Display Fix"
|
||||
parent="menu_mcs_invoice_currency_display_root" sequence="10"
|
||||
action="action_mcs_invoice_currency_display"/>
|
||||
|
||||
<record id="action_mcs_invoice_currency_display" model="ir.actions.act_window">
|
||||
<field name="name">MCS Invoice Currency Display Fix</field>
|
||||
<field name="res_model">mcs.invoice.currency.display</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!--
|
||||
Override the company currency block on customer invoices.
|
||||
When the invoice currency differs from the company currency (e.g. USD invoice
|
||||
for a CAD company), Odoo normally adds a second "Taxes CAD / Total" block.
|
||||
This module hides that block so the invoice only shows amounts in the
|
||||
invoice currency, which is the correct display for international clients.
|
||||
-->
|
||||
<template id="document_tax_totals_company_currency_template"
|
||||
inherit_id="account.document_tax_totals_company_currency_template">
|
||||
<xpath expr="//t[@t-set='show_company_taxes']" position="replace">
|
||||
<t t-set="show_company_taxes" t-value="False"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
@ -0,0 +1,327 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!--
|
||||
Modern invoice layout — Metatroncube Software Solutions
|
||||
Overrides the content area of account.report_invoice_document.
|
||||
|
||||
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">
|
||||
|
||||
<xpath expr="//div[@class='mt-5 clearfix']" position="replace">
|
||||
<div class="mt-3">
|
||||
<div class="page mb-4">
|
||||
|
||||
<!-- ━━━ 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;">
|
||||
<div style="font-size:22px;font-weight:700;letter-spacing:1.5px;line-height:1.15;">
|
||||
<t t-if="not proforma">
|
||||
<t t-if="o.move_type == 'out_invoice' and o.state == 'posted'">INVOICE</t>
|
||||
<t t-elif="o.move_type == 'out_invoice' and o.state == 'draft'">DRAFT INVOICE</t>
|
||||
<t t-elif="o.move_type == 'out_invoice' and o.state == 'cancel'">CANCELLED INVOICE</t>
|
||||
<t t-elif="o.move_type == 'out_refund' and o.state == 'posted'">CREDIT NOTE</t>
|
||||
<t t-elif="o.move_type == 'out_refund' and o.state == 'draft'">DRAFT CREDIT NOTE</t>
|
||||
<t t-elif="o.move_type == 'out_refund' and o.state == 'cancel'">CANCELLED CREDIT NOTE</t>
|
||||
<t t-elif="o.move_type == 'in_refund'">VENDOR CREDIT NOTE</t>
|
||||
<t t-elif="o.move_type == 'in_invoice'">VENDOR BILL</t>
|
||||
</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;">
|
||||
<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> 
|
||||
<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> 
|
||||
<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> 
|
||||
<span t-field="o.ref"/>
|
||||
</div>
|
||||
<div t-if="o.invoice_origin" style="margin-top:5px;">
|
||||
<span style="opacity:.65;">Source</span> 
|
||||
<span t-field="o.invoice_origin"/>
|
||||
</div>
|
||||
<div t-if="o.invoice_incoterm_id" style="margin-top:5px;">
|
||||
<span style="opacity:.65;">Incoterm</span> 
|
||||
<span t-field="o.invoice_incoterm_id.code"/>
|
||||
<t t-if="o.incoterm_location"> <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> 
|
||||
<span t-field="o.partner_id.ref"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="oe_structure"/>
|
||||
|
||||
<!-- ━━━ 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)"/>
|
||||
|
||||
<table style="width:100%;border-collapse:collapse;font-size:12.5px;" name="invoice_line_table">
|
||||
<thead>
|
||||
<tr style="background:#243f5c;color:#fff;">
|
||||
<th name="th_description" style="padding:9px 12px;text-align:left;font-weight:600;border:none;">Description</th>
|
||||
<th name="th_quantity" style="padding:9px 8px;text-align:right;font-weight:600;border:none;white-space:nowrap;">Qty</th>
|
||||
<th name="th_priceunit" style="padding:9px 8px;text-align:right;font-weight:600;border:none;white-space:nowrap;">Unit Price</th>
|
||||
<th t-if="display_discount" name="th_discount"
|
||||
style="padding:9px 8px;text-align:right;font-weight:600;border:none;">Disc.%</th>
|
||||
<th name="th_taxes" style="padding:9px 8px;text-align:center;font-weight:600;border:none;white-space:nowrap;">Tax</th>
|
||||
<th name="th_subtotal" style="padding:9px 12px;text-align:right;font-weight:600;border:none;white-space:nowrap;">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="invoice_tbody">
|
||||
<t t-set="current_subtotal" t-value="0"/>
|
||||
<t t-set="current_section" t-value="None"/>
|
||||
|
||||
<t t-foreach="lines" t-as="line">
|
||||
<t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal"/>
|
||||
|
||||
<tr t-att-class="'fw-bold o_line_section' if line.display_type == 'line_section' else 'o_line_note' if line.display_type == 'line_note' else ''"
|
||||
t-att-style="'background:#f4f7fb;' if line_index % 2 != 0 else 'background:#ffffff;'">
|
||||
|
||||
<!-- ── Product line ── -->
|
||||
<t t-if="line.display_type == 'product'" name="account_invoice_line_accountable">
|
||||
<td name="account_invoice_line_name"
|
||||
style="padding:9px 12px;border-top:1px solid #e8ecf0;vertical-align:top;">
|
||||
<span t-if="line.name" t-field="line.name" t-options="{'widget': 'text'}"/>
|
||||
</td>
|
||||
<td name="td_quantity"
|
||||
style="padding:9px 8px;border-top:1px solid #e8ecf0;text-align:right;vertical-align:top;white-space:nowrap;">
|
||||
<span t-field="line.quantity"/>
|
||||
<span t-field="line.product_uom_id" groups="uom.group_uom"
|
||||
style="font-size:10px;color:#9ca3af;"/>
|
||||
</td>
|
||||
<td name="td_price_unit"
|
||||
style="padding:9px 8px;border-top:1px solid #e8ecf0;text-align:right;vertical-align:top;white-space:nowrap;">
|
||||
<span t-field="line.price_unit"/>
|
||||
</td>
|
||||
<td t-if="display_discount" name="td_discount"
|
||||
style="padding:9px 8px;border-top:1px solid #e8ecf0;text-align:right;vertical-align:top;">
|
||||
<span t-field="line.discount"/>
|
||||
</td>
|
||||
<t t-set="taxes" t-value="', '.join([(tax.invoice_label or tax.name) for tax in line.tax_ids])"/>
|
||||
<td name="td_taxes"
|
||||
style="padding:9px 8px;border-top:1px solid #e8ecf0;text-align:center;vertical-align:top;font-size:11px;color:#6b7280;white-space:nowrap;">
|
||||
<span t-if="taxes" t-out="taxes" id="line_tax_ids"/>
|
||||
<span t-else="" style="color:#d1d5db;">—</span>
|
||||
</td>
|
||||
<td name="td_subtotal"
|
||||
style="padding:9px 12px;border-top:1px solid #e8ecf0;text-align:right;vertical-align:top;font-weight:500;white-space:nowrap;">
|
||||
<span t-field="line.price_subtotal"/>
|
||||
</td>
|
||||
</t>
|
||||
|
||||
<!-- ── Section header ── -->
|
||||
<t t-elif="line.display_type == 'line_section'">
|
||||
<td colspan="99"
|
||||
style="padding:8px 12px;border-top:2px solid #1a2e4a;background:#eef2f7;font-weight:700;color:#1a2e4a;font-size:11px;text-transform:uppercase;letter-spacing:.6px;">
|
||||
<span t-if="line.name" t-field="line.name" t-options="{'widget': 'text'}"/>
|
||||
</td>
|
||||
<t t-set="current_section" t-value="line"/>
|
||||
<t t-set="current_subtotal" t-value="0"/>
|
||||
</t>
|
||||
|
||||
<!-- ── Note line ── -->
|
||||
<t t-elif="line.display_type == 'line_note'">
|
||||
<td colspan="99"
|
||||
style="padding:4px 12px;border-top:1px solid #f3f4f6;color:#9ca3af;font-size:11.5px;font-style:italic;">
|
||||
<span t-if="line.name" t-field="line.name" t-options="{'widget': 'text'}"/>
|
||||
</td>
|
||||
</t>
|
||||
</tr>
|
||||
|
||||
<!-- Section subtotal row -->
|
||||
<t t-if="current_section and (line_last or lines[line_index+1].display_type == 'line_section')">
|
||||
<tr>
|
||||
<td colspan="99"
|
||||
style="text-align:right;padding:5px 12px;border-top:1px solid #d1d9e0;font-size:12px;color:#374151;background:#f9fbfc;">
|
||||
<span style="margin-right:12px;font-style:italic;">Section Subtotal</span>
|
||||
<strong t-out="current_subtotal"
|
||||
t-options="{'widget':'monetary','display_currency':o.currency_id}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- ━━━ BOTTOM SECTION ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -->
|
||||
<table style="width:100%;border-collapse:collapse;margin-top:18px;">
|
||||
<tr>
|
||||
<!-- ── LEFT: notes, HST notice, payment terms ── -->
|
||||
<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;">
|
||||
<span t-field="o.fiscal_position_id.note"/>
|
||||
</div>
|
||||
|
||||
<!-- Payment term note -->
|
||||
<div t-if="o.invoice_payment_term_id.note"
|
||||
style="font-size:12px;color:#374151;margin-bottom:6px;">
|
||||
<span t-field="o.invoice_payment_term_id.note" name="payment_term"/>
|
||||
</div>
|
||||
|
||||
<!-- Installment schedule -->
|
||||
<t t-set="payment_term_details" t-value="o.payment_term_details"/>
|
||||
<t t-if="o.invoice_payment_term_id.display_on_invoice and payment_term_details">
|
||||
<div t-if="o.show_payment_term_details"
|
||||
id="total_payment_term_details_table"
|
||||
style="font-size:11.5px;color:#374151;margin-bottom:8px;">
|
||||
<t t-if="o._is_eligible_for_early_payment_discount(o.currency_id, o.invoice_date)">
|
||||
<div>
|
||||
<span t-options="{'widget':'monetary','display_currency':o.currency_id}"
|
||||
t-out="o.invoice_payment_term_id._get_amount_due_after_discount(o.amount_total, o.amount_tax)"/>
|
||||
due if paid before
|
||||
<span t-out="o.invoice_payment_term_id._get_last_discount_date_formatted(o.invoice_date)"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="len(payment_term_details) > 1" t-foreach="payment_term_details" t-as="term">
|
||||
<div>
|
||||
Instalment <span t-out="term_index + 1"/>: 
|
||||
<strong t-options="{'widget':'monetary','display_currency':o.currency_id}"
|
||||
t-out="term.get('amount')"/>
|
||||
due <span t-out="term.get('date')"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Payment reference + bank account -->
|
||||
<div t-if="o.move_type in ('out_invoice','in_refund') and o.payment_reference"
|
||||
style="font-size:12px;color:#374151;margin-bottom:6px;" name="payment_communication">
|
||||
<strong>Payment Reference:</strong> 
|
||||
<span class="fw-bold" t-field="o.payment_reference"/>
|
||||
<t t-if="o.partner_bank_id">
|
||||
<br/>Account: <span t-field="o.partner_bank_id" class="fw-bold"/>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<!-- Terms & conditions / narration -->
|
||||
<div t-if="not is_html_empty(o.narration)"
|
||||
style="font-size:11px;color:#6b7280;margin-top:8px;border-top:1px solid #f0f0f0;padding-top:8px;"
|
||||
name="comment">
|
||||
<span t-field="o.narration"/>
|
||||
</div>
|
||||
|
||||
<!-- QR code (EPC / payment) -->
|
||||
<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"
|
||||
style="display:flex;align-items:center;margin-top:14px;" t-else="">
|
||||
<div id="qrcode_image" style="margin-right:10px;">
|
||||
<t t-set="qr_code_url" t-value="o._generate_qr_code(silent_errors=True)"/>
|
||||
<p t-if="qr_code_url" class="position-relative mb-0">
|
||||
<img t-att-src="qr_code_url"/>
|
||||
<img src="/account/static/src/img/Odoo_logo_O.svg"
|
||||
id="qrcode_odoo_logo"
|
||||
class="top-50 start-50 position-absolute bg-white border border-white border-3 rounded-circle"/>
|
||||
</p>
|
||||
</div>
|
||||
<div t-if="qr_code_url"
|
||||
style="font-size:11px;color:#9ca3af;font-style:italic;" id="qrcode_info">
|
||||
Scan to pay with your mobile
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- ── RIGHT: totals box ── -->
|
||||
<td style="width:46%;vertical-align:top;">
|
||||
<div style="border:1px solid #dde3ea;border-radius:6px;overflow:hidden;">
|
||||
<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"
|
||||
t-value="o.sudo().invoice_payments_widget and o.sudo().invoice_payments_widget['content'] or []"/>
|
||||
<t t-foreach="payments_vals" t-as="payment_vals">
|
||||
<tr t-if="payment_vals['is_exchange'] == 0"
|
||||
style="font-size:11.5px;color:#6b7280;">
|
||||
<td style="padding:5px 12px;">
|
||||
<i class="oe_form_field oe_payment_label">
|
||||
Paid on
|
||||
<t t-out="payment_vals['date']"
|
||||
t-options="{'widget':'date'}"/>
|
||||
</i>
|
||||
</td>
|
||||
<td class="text-end" style="padding:5px 12px;white-space:nowrap;">
|
||||
<span t-out="payment_vals['amount']"
|
||||
t-options="{'widget':'monetary','display_currency':o.currency_id}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<t t-if="len(payments_vals) > 0">
|
||||
<tr style="background:#1a2e4a;color:#fff;font-weight:700;font-size:13px;"
|
||||
class="border-black fw-bold">
|
||||
<td style="padding:10px 12px;">Amount Due</td>
|
||||
<td class="text-end" style="padding:10px 12px;white-space:nowrap;">
|
||||
<span t-field="o.amount_residual"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</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"/>
|
||||
</div>
|
||||
|
||||
<!-- CAD block suppressed by report_invoice_currency.xml override -->
|
||||
<t t-call="account.document_tax_totals_company_currency_template"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="oe_structure"/>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
|
||||
</template>
|
||||
</odoo>
|
||||
Loading…
x
Reference in New Issue
Block a user