changes
This commit is contained in:
1
.claude/scheduled_tasks.lock
Normal file
1
.claude/scheduled_tasks.lock
Normal file
@@ -0,0 +1 @@
|
||||
{"sessionId":"995b3836-6e56-40fa-aec9-e8cfae013a0b","pid":70631,"acquiredAt":1776733239341}
|
||||
1
fusion_reports_templates/__init__.py
Normal file
1
fusion_reports_templates/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
48
fusion_reports_templates/__manifest__.py
Normal file
48
fusion_reports_templates/__manifest__.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
{
|
||||
'name': 'Fusion Reports — Templates',
|
||||
'version': '19.0.1.0.0',
|
||||
'category': 'Tools/Reports',
|
||||
'summary': 'Branded PDF templates for Quotation, Sales Order, Invoice, Delivery, Purchase Order, and Payment Receipt.',
|
||||
'description': """
|
||||
Fusion Reports Templates
|
||||
========================
|
||||
Replaces Odoo's default PDF layouts for the customer-facing quote-to-cash
|
||||
documents with a consistent NEXA Systems branded design. The customer-facing
|
||||
mail templates are redirected to the new reports so emails always send the
|
||||
branded PDF, not the stock Odoo one.
|
||||
|
||||
Reports included (each in portrait + landscape):
|
||||
* Quotation / Sales Order
|
||||
* Customer Invoice / Credit Note
|
||||
* Delivery / Packing Slip
|
||||
* Purchase Order / RFQ
|
||||
* Payment Receipt
|
||||
""",
|
||||
'author': 'Nexa Systems Inc.',
|
||||
'website': 'https://nexasystems.ca',
|
||||
'depends': [
|
||||
'sale',
|
||||
'account',
|
||||
'stock',
|
||||
'purchase',
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'report/report_base_styles.xml',
|
||||
'report/report_actions.xml',
|
||||
'report/report_sale.xml',
|
||||
'report/report_invoice.xml',
|
||||
'report/report_delivery.xml',
|
||||
'report/report_purchase.xml',
|
||||
'report/report_receipt.xml',
|
||||
'data/mail_template_override.xml',
|
||||
'data/hide_default_reports.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': False,
|
||||
'auto_install': False,
|
||||
'license': 'OPL-1',
|
||||
}
|
||||
96
fusion_reports_templates/data/hide_default_reports.xml
Normal file
96
fusion_reports_templates/data/hide_default_reports.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
Remove Odoo's default PDF reports from each model's Print dropdown
|
||||
so users can't accidentally send the unbranded version. Setting
|
||||
`binding_model_id` to False leaves the underlying report intact;
|
||||
an admin can re-enable any of these from Settings → Technical →
|
||||
Actions → Reports.
|
||||
|
||||
Loaded last so it overrides the binding declarations shipped by
|
||||
the base modules.
|
||||
-->
|
||||
<odoo noupdate="0">
|
||||
|
||||
<!-- sale.order -->
|
||||
<record id="sale.action_report_saleorder" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
|
||||
<!-- account.move -->
|
||||
<record id="account.account_invoices" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
<record id="account.account_invoices_without_payment" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
|
||||
<!-- stock.picking -->
|
||||
<record id="stock.action_report_delivery" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
|
||||
<!-- purchase.order: PO + RFQ -->
|
||||
<record id="purchase.action_report_purchase_order" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
<record id="purchase.report_purchase_quotation" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
|
||||
<!-- sale.order: pro-forma -->
|
||||
<record id="sale.action_report_pro_forma_invoice" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
|
||||
<!-- account.payment -->
|
||||
<record id="account.action_report_payment_receipt" model="ir.actions.report">
|
||||
<field name="binding_model_id" eval="False"/>
|
||||
<field name="binding_type">action</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
Print-menu sequencing — pin Fusion reports to the top.
|
||||
Portrait = 10 (primary), Landscape = 15 (secondary).
|
||||
================================================================ -->
|
||||
<record id="fusion_reports_templates.action_report_fr_sale_portrait" model="ir.actions.report">
|
||||
<field name="sequence" eval="10"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_sale_landscape" model="ir.actions.report">
|
||||
<field name="sequence" eval="15"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_invoice_portrait" model="ir.actions.report">
|
||||
<field name="sequence" eval="10"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_invoice_landscape" model="ir.actions.report">
|
||||
<field name="sequence" eval="15"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_delivery_portrait" model="ir.actions.report">
|
||||
<field name="sequence" eval="10"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_delivery_landscape" model="ir.actions.report">
|
||||
<field name="sequence" eval="15"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_purchase_portrait" model="ir.actions.report">
|
||||
<field name="sequence" eval="10"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_purchase_landscape" model="ir.actions.report">
|
||||
<field name="sequence" eval="15"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_receipt_portrait" model="ir.actions.report">
|
||||
<field name="sequence" eval="10"/>
|
||||
</record>
|
||||
<record id="fusion_reports_templates.action_report_fr_receipt_landscape" model="ir.actions.report">
|
||||
<field name="sequence" eval="15"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
80
fusion_reports_templates/data/mail_template_override.xml
Normal file
80
fusion_reports_templates/data/mail_template_override.xml
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
Re-point the stock "Send by Email" mail templates so the attached PDF
|
||||
uses Fusion Reports branded design instead of Odoo's default layout.
|
||||
|
||||
`report_template_ids` is Many2many on mail.template; replacing with a
|
||||
`[(6, 0, [...])]` op swaps the attached reports atomically.
|
||||
|
||||
noupdate="0" so upgrades re-apply the binding (counter-acts any manual
|
||||
edit a user may have made in Settings → Technical → Email Templates).
|
||||
-->
|
||||
<odoo noupdate="0">
|
||||
|
||||
<!-- Sales: Send Quotation -->
|
||||
<record id="sale.email_template_edi_sale" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_sale_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Sales: Order Confirmation (confirmed SO) -->
|
||||
<record id="sale.mail_template_sale_confirmation" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_sale_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Invoice: Send -->
|
||||
<record id="account.email_template_edi_invoice" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_invoice_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Credit Note: Send -->
|
||||
<record id="account.email_template_edi_credit_note" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_invoice_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Payment: Receipt -->
|
||||
<record id="account.mail_template_data_payment_receipt" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_receipt_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Stock: Delivery confirmation -->
|
||||
<record id="stock.mail_template_data_delivery_confirmation" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_delivery_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Purchase: RFQ -->
|
||||
<record id="purchase.email_template_edi_purchase" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_purchase_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Purchase: Confirmed PO -->
|
||||
<record id="purchase.email_template_edi_purchase_done" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_purchase_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Purchase: Vendor Reminder -->
|
||||
<record id="purchase.email_template_edi_purchase_reminder" model="mail.template">
|
||||
<field name="report_template_ids" eval="[(6, 0, [
|
||||
ref('fusion_reports_templates.action_report_fr_purchase_portrait')
|
||||
])]"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
1
fusion_reports_templates/models/__init__.py
Normal file
1
fusion_reports_templates/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import ir_actions_report
|
||||
42
fusion_reports_templates/models/ir_actions_report.py
Normal file
42
fusion_reports_templates/models/ir_actions_report.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
"""Sort the Print-menu report bindings by `sequence`.
|
||||
|
||||
Odoo 19 returns `ir.actions.report` bindings in raw insertion order, which
|
||||
pushes third-party reports to the bottom even when they are the primary
|
||||
customer-facing document. Adding a sequence field and sorting inside
|
||||
`ir.actions.actions._get_bindings` restores the expected ordering.
|
||||
"""
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools import frozendict
|
||||
|
||||
|
||||
class IrActionsReport(models.Model):
|
||||
_inherit = 'ir.actions.report'
|
||||
|
||||
sequence = fields.Integer(
|
||||
default=100,
|
||||
help='Order in which this report appears in the Print menu '
|
||||
'(lower = higher in the list).',
|
||||
)
|
||||
|
||||
|
||||
class IrActionsActions(models.Model):
|
||||
_inherit = 'ir.actions.actions'
|
||||
|
||||
@api.model
|
||||
def _get_bindings(self, model_name):
|
||||
result = super()._get_bindings(model_name)
|
||||
if not result.get('report'):
|
||||
return result
|
||||
sorted_reports = tuple(sorted(
|
||||
result['report'],
|
||||
key=lambda vals: (
|
||||
vals.get('sequence', 100),
|
||||
(vals.get('name') or '').lower(),
|
||||
),
|
||||
))
|
||||
new_result = dict(result)
|
||||
new_result['report'] = sorted_reports
|
||||
return frozendict(new_result)
|
||||
139
fusion_reports_templates/report/report_actions.xml
Normal file
139
fusion_reports_templates/report/report_actions.xml
Normal file
@@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
ir.actions.report records for every Fusion Reports template.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Quotation / Sales Order -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fr_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_reports_templates.report_fr_sale_portrait</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_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_fr_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_reports_templates.report_fr_sale_landscape</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_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_fr_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Invoice / Credit Note / Vendor Bill -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fr_invoice_portrait" model="ir.actions.report">
|
||||
<field name="name">Invoice (Portrait)</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_reports_templates.report_fr_invoice_portrait</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_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_fr_invoice_landscape" model="ir.actions.report">
|
||||
<field name="name">Invoice (Landscape)</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_reports_templates.report_fr_invoice_landscape</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_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_fr_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Delivery Slip / Receipt / Transfer -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fr_delivery_portrait" model="ir.actions.report">
|
||||
<field name="name">Delivery Slip (Portrait)</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_reports_templates.report_fr_delivery_portrait</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_delivery_portrait</field>
|
||||
<field name="print_report_name">'Delivery - %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_fr_delivery_landscape" model="ir.actions.report">
|
||||
<field name="name">Delivery Slip (Landscape)</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_reports_templates.report_fr_delivery_landscape</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_delivery_landscape</field>
|
||||
<field name="print_report_name">'Delivery - %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_fr_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Purchase Order / RFQ -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fr_purchase_portrait" model="ir.actions.report">
|
||||
<field name="name">Purchase Order (Portrait)</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_reports_templates.report_fr_purchase_portrait</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_purchase_portrait</field>
|
||||
<field name="print_report_name">(object.state in ('draft', 'sent', 'to approve') and 'RFQ - %s' % object.name) or 'PO - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="purchase.model_purchase_order"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_fr_purchase_landscape" model="ir.actions.report">
|
||||
<field name="name">Purchase Order (Landscape)</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">fusion_reports_templates.report_fr_purchase_landscape</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_purchase_landscape</field>
|
||||
<field name="print_report_name">(object.state in ('draft', 'sent', 'to approve') and 'RFQ - %s' % object.name) or 'PO - %s' % object.name</field>
|
||||
<field name="binding_model_id" ref="purchase.model_purchase_order"/>
|
||||
<field name="binding_type">report</field>
|
||||
<field name="paperformat_id" ref="paperformat_fr_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Payment Receipt -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="action_report_fr_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_reports_templates.report_fr_receipt_portrait</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_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_fr_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_reports_templates.report_fr_receipt_landscape</field>
|
||||
<field name="report_file">fusion_reports_templates.report_fr_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_fr_a4_landscape"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
105
fusion_reports_templates/report/report_base_styles.xml
Normal file
105
fusion_reports_templates/report/report_base_styles.xml
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
Shared CSS + paper format for all Fusion Reports templates
|
||||
(portrait + landscape).
|
||||
|
||||
The primary colour is driven by the active company's
|
||||
res.company.primary_color field (Settings → Company → Report Layout),
|
||||
falling back to #1d1f1e when unset.
|
||||
|
||||
Apply `.fr-header-primary` to any `<th>` or `<td>` that should render
|
||||
as a primary-coloured section banner.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Landscape Paper Format -->
|
||||
<!-- ============================================================= -->
|
||||
<record id="paperformat_fr_a4_landscape" model="report.paperformat">
|
||||
<field name="name">A4 Landscape (Fusion Reports)</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="format">A4</field>
|
||||
<field name="orientation">Landscape</field>
|
||||
<field name="margin_top">20</field>
|
||||
<field name="margin_bottom">20</field>
|
||||
<field name="margin_left">7</field>
|
||||
<field name="margin_right">7</field>
|
||||
<field name="header_line" eval="False"/>
|
||||
<field name="header_spacing">20</field>
|
||||
<field name="dpi">90</field>
|
||||
</record>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Portrait Styles -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="fr_portrait_styles">
|
||||
<t t-set="_fr_company" t-value="doc.company_id if doc and 'company_id' in doc._fields else (company if company else user.company_id)"/>
|
||||
<t t-set="fr_primary" t-value="(_fr_company.primary_color if _fr_company else False) or '#1d1f1e'"/>
|
||||
<style>
|
||||
.fr-report { font-family: Arial, sans-serif; font-size: 10pt; color: #000; }
|
||||
.fr-report table { width: 100%; border-collapse: collapse; margin-bottom: 10px; }
|
||||
.fr-report table.bordered, .fr-report table.bordered th, .fr-report table.bordered td { border: 1px solid #000; }
|
||||
.fr-report th { background-color: <t t-out="fr_primary"/>; color: white; padding: 6px 8px; font-weight: bold; text-align: center; font-size: 9pt; }
|
||||
.fr-report td { padding: 6px 8px; vertical-align: top; font-size: 10pt; }
|
||||
.fr-report .text-center { text-align: center; }
|
||||
.fr-report .text-end { text-align: right; }
|
||||
.fr-report .text-start { text-align: left; }
|
||||
.fr-report .section-row { background-color: #f0f0f0; font-weight: bold; }
|
||||
.fr-report .note-row { font-style: italic; color: #555; font-size: 9pt; }
|
||||
.fr-report h4 { color: <t t-out="fr_primary"/>; margin: 0 0 15px 0; font-size: 16pt; }
|
||||
.fr-report .totals-table { border: 1px solid #000; border-collapse: collapse; }
|
||||
.fr-report .totals-table td { border: 1px solid #000; padding: 6px 8px; }
|
||||
.fr-report .info-header { background-color: #f5f5f5; color: #333; }
|
||||
.fr-report .highlight-box { border: 2px solid <t t-out="fr_primary"/>; background-color: #eaf2f8; padding: 10px; margin: 10px 0; }
|
||||
.fr-report .fr-header-primary { background-color: <t t-out="fr_primary"/>; color: white; }
|
||||
.fr-report .paid-stamp { color: #28a745; font-size: 36pt; font-weight: bold; border: 4px solid #28a745; padding: 10px 20px; transform: rotate(-8deg); display: inline-block; }
|
||||
.fr-report .status-ok { color: #2e7d32; font-weight: bold; }
|
||||
.fr-report .status-warning { color: #f57f17; font-weight: bold; }
|
||||
.fr-report .status-fail { color: #c62828; font-weight: bold; }
|
||||
.fr-report .sig-line { border-bottom: 1px solid #000; height: 60px; margin-bottom: 4px; }
|
||||
.fr-report .small-muted { font-size: 8pt; color: #666; }
|
||||
.fr-report .fr-cell-mid { vertical-align: middle !important; }
|
||||
.fr-report .fr-keep-together { page-break-inside: avoid; break-inside: avoid; }
|
||||
.fr-report table tr { page-break-inside: avoid; break-inside: avoid; }
|
||||
</style>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- Landscape Styles -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="fr_landscape_styles">
|
||||
<t t-set="_fr_company" t-value="doc.company_id if doc and 'company_id' in doc._fields else (company if company else user.company_id)"/>
|
||||
<t t-set="fr_primary" t-value="(_fr_company.primary_color if _fr_company else False) or '#1d1f1e'"/>
|
||||
<style>
|
||||
.fr-landscape { font-family: Arial, sans-serif; font-size: 10pt; color: #000; }
|
||||
.fr-landscape table { width: 100%; border-collapse: collapse; margin-bottom: 6px; }
|
||||
.fr-landscape table.bordered, .fr-landscape table.bordered th, .fr-landscape table.bordered td { border: 1px solid #000; }
|
||||
.fr-landscape th { background-color: <t t-out="fr_primary"/>; color: white; padding: 4px 8px; font-weight: bold; font-size: 9pt; }
|
||||
.fr-landscape td { padding: 4px 8px; vertical-align: top; font-size: 9.5pt; }
|
||||
.fr-landscape .text-center { text-align: center; }
|
||||
.fr-landscape .text-end { text-align: right; }
|
||||
.fr-landscape .text-start { text-align: left; }
|
||||
.fr-landscape .section-row { background-color: #f0f0f0; font-weight: bold; }
|
||||
.fr-landscape .note-row { font-style: italic; color: #555; }
|
||||
.fr-landscape h2 { color: <t t-out="fr_primary"/>; margin: 4px 0; font-size: 18pt; }
|
||||
.fr-landscape .info-table td { padding: 8px 12px; font-size: 11pt; }
|
||||
.fr-landscape .info-table th { background-color: #f5f5f5; color: #333; font-size: 10pt; padding: 6px 12px; }
|
||||
.fr-landscape .totals-table { border: 1px solid #000; }
|
||||
.fr-landscape .totals-table td { border: 1px solid #000; padding: 8px 12px; font-size: 11pt; }
|
||||
.fr-landscape .highlight-box { border: 2px solid <t t-out="fr_primary"/>; background-color: #eaf2f8; padding: 6px 10px; margin: 6px 0; font-size: 9pt; }
|
||||
.fr-landscape .fr-header-primary { background-color: <t t-out="fr_primary"/>; color: white; }
|
||||
.fr-landscape .paid-stamp { color: #28a745; font-size: 42pt; font-weight: bold; border: 4px solid #28a745; padding: 10px 20px; transform: rotate(-8deg); display: inline-block; }
|
||||
.fr-landscape .status-ok { color: #2e7d32; font-weight: bold; }
|
||||
.fr-landscape .status-warning { color: #f57f17; font-weight: bold; }
|
||||
.fr-landscape .status-fail { color: #c62828; font-weight: bold; }
|
||||
.fr-landscape .sig-line { border-bottom: 1px solid #000; height: 45px; margin-bottom: 3px; }
|
||||
.fr-landscape .small-muted { font-size: 9pt; color: #666; }
|
||||
.fr-landscape .fr-cell-mid { vertical-align: middle !important; }
|
||||
.fr-landscape table tr { page-break-inside: avoid; break-inside: avoid; }
|
||||
</style>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
255
fusion_reports_templates/report/report_delivery.xml
Normal file
255
fusion_reports_templates/report/report_delivery.xml
Normal file
@@ -0,0 +1,255 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Delivery / Packing Slip — portrait + landscape.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_delivery_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_reports_templates.fr_portrait_styles"/>
|
||||
<div class="fr-report">
|
||||
<div class="page">
|
||||
|
||||
<h4>
|
||||
<t t-if="doc.picking_type_id.code == 'outgoing'">Delivery Slip </t>
|
||||
<t t-elif="doc.picking_type_id.code == 'incoming'">Receipt </t>
|
||||
<t t-else="">Transfer </t>
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">FROM</th>
|
||||
<th style="width: 50%;">TO</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px;">
|
||||
<strong><span t-field="doc.location_id.display_name"/></strong><br/>
|
||||
<span t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 70px;">
|
||||
<t t-if="doc.partner_id">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<strong><span t-field="doc.location_dest_id.display_name"/></strong>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 25%;">SCHEDULED DATE</th>
|
||||
<th class="info-header" style="width: 25%;">ORDER</th>
|
||||
<th class="info-header" style="width: 25%;">CARRIER</th>
|
||||
<th class="info-header" style="width: 25%;">TRACKING #</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.carrier_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.carrier_tracking_ref or '-'"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 15%;">SKU</th>
|
||||
<th class="text-start" style="width: 55%;">PRODUCT</th>
|
||||
<th style="width: 15%;">QTY DONE</th>
|
||||
<th style="width: 15%;">UOM</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.display_name"/>
|
||||
<t t-if="move.description_picking and move.description_picking != move.product_id.display_name">
|
||||
<br/><span class="small-muted" t-esc="move.description_picking"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="doc.state == 'done'">
|
||||
<span t-esc="int(move.quantity) if move.quantity == int(move.quantity) else move.quantity"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span t-esc="int(move.product_uom_qty) if move.product_uom_qty == int(move.product_uom_qty) else move.product_uom_qty"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="move.product_uom"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="row" style="margin-top: 30px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Shipper Signature / Date</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Receiver Signature / Date</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_delivery_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_reports_templates.fr_landscape_styles"/>
|
||||
<div class="fr-landscape">
|
||||
<div class="page">
|
||||
|
||||
<h2>
|
||||
<t t-if="doc.picking_type_id.code == 'outgoing'">Delivery Slip </t>
|
||||
<t t-elif="doc.picking_type_id.code == 'incoming'">Receipt </t>
|
||||
<t t-else="">Transfer </t>
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">FROM</th>
|
||||
<th style="width: 50%;">TO</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.location_id.display_name"/></strong><br/>
|
||||
<span t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
</td>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<t t-if="doc.partner_id">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<strong><span t-field="doc.location_dest_id.display_name"/></strong>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SCHEDULED DATE</th>
|
||||
<th>ORDER</th>
|
||||
<th>CARRIER</th>
|
||||
<th>TRACKING #</th>
|
||||
<th>WEIGHT</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.carrier_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.carrier_tracking_ref or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.weight" t-options="{'widget': 'float', 'precision': 2}"/> <span t-field="doc.weight_uom_name"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 15%;">SKU</th>
|
||||
<th class="text-start" style="width: 55%;">PRODUCT</th>
|
||||
<th style="width: 15%;">QTY</th>
|
||||
<th style="width: 15%;">UOM</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.display_name"/>
|
||||
<t t-if="move.description_picking and move.description_picking != move.product_id.display_name">
|
||||
<br/><span class="small-muted" t-esc="move.description_picking"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<t t-if="doc.state == 'done'">
|
||||
<span t-esc="int(move.quantity) if move.quantity == int(move.quantity) else move.quantity"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span t-esc="int(move.product_uom_qty) if move.product_uom_qty == int(move.product_uom_qty) else move.product_uom_qty"/>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-center"><span t-field="move.product_uom"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="row" style="margin-top: 30px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Shipper Signature / Date</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Receiver Signature / Date</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
359
fusion_reports_templates/report/report_invoice.xml
Normal file
359
fusion_reports_templates/report/report_invoice.xml
Normal file
@@ -0,0 +1,359 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Customer Invoice / Vendor Bill / Credit Note — portrait + landscape.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_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_reports_templates.fr_portrait_styles"/>
|
||||
<div class="fr-report">
|
||||
<div class="page">
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<h4>
|
||||
<t t-if="doc.move_type == 'out_invoice'">Invoice </t>
|
||||
<t t-elif="doc.move_type == 'out_refund'">Credit Note </t>
|
||||
<t t-elif="doc.move_type == 'in_invoice'">Vendor Bill </t>
|
||||
<t t-elif="doc.move_type == 'in_refund'">Vendor Refund </t>
|
||||
<t t-else="">Document </t>
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
<t t-if="doc.payment_state == 'paid'">
|
||||
<div class="paid-stamp">PAID</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">BILL TO</th>
|
||||
<th style="width: 50%;">SHIP TO</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>
|
||||
|
||||
<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%;">REFERENCE</th>
|
||||
<th class="info-header" style="width: 25%;">PAYMENT TERMS</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-esc="doc.ref or doc.invoice_origin or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_payment_term_id"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<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%;">TAX</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="line.display_type == 'product' or not line.display_type">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td><span t-esc="line.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>
|
||||
|
||||
<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>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.payment_state != 'paid'">
|
||||
<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>
|
||||
|
||||
<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_fr_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_reports_templates.fr_landscape_styles"/>
|
||||
<div class="fr-landscape">
|
||||
<div class="page">
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<h2>
|
||||
<t t-if="doc.move_type == 'out_invoice'">Invoice </t>
|
||||
<t t-elif="doc.move_type == 'out_refund'">Credit Note </t>
|
||||
<t t-elif="doc.move_type == 'in_invoice'">Vendor Bill </t>
|
||||
<t t-elif="doc.move_type == 'in_refund'">Vendor Refund </t>
|
||||
<t t-else="">Document </t>
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
<t t-if="doc.payment_state == 'paid'">
|
||||
<div class="paid-stamp">PAID</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">BILL TO</th>
|
||||
<th style="width: 50%;">SHIP TO</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>
|
||||
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>INVOICE DATE</th>
|
||||
<th>DUE DATE</th>
|
||||
<th>REFERENCE</th>
|
||||
<th>PAYMENT TERMS</th>
|
||||
<th>SALESPERSON</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-esc="doc.ref or doc.invoice_origin or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_payment_term_id"/></td>
|
||||
<td class="text-center"><span t-field="doc.invoice_user_id"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<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%;">TAX</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="line.display_type == 'product' or not line.display_type">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td><span t-esc="line.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>
|
||||
|
||||
<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>
|
||||
<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-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>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.payment_state != 'paid'">
|
||||
<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>
|
||||
|
||||
<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>
|
||||
317
fusion_reports_templates/report/report_purchase.xml
Normal file
317
fusion_reports_templates/report/report_purchase.xml
Normal file
@@ -0,0 +1,317 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Purchase Order / RFQ — portrait + landscape.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_purchase_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_reports_templates.fr_portrait_styles"/>
|
||||
<div class="fr-report">
|
||||
<div class="page">
|
||||
|
||||
<h4>
|
||||
<t t-if="doc.state in ['draft', 'sent', 'to approve']">Request for Quotation </t>
|
||||
<t t-else="">Purchase Order </t>
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">VENDOR</th>
|
||||
<th style="width: 50%;">SHIP TO</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.dest_address_id">
|
||||
<div t-field="doc.dest_address_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone'], 'no_marker': True}"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<span t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 25%;">ORDER DATE</th>
|
||||
<th class="info-header" style="width: 25%;">EXPECTED</th>
|
||||
<th class="info-header" style="width: 25%;">BUYER</th>
|
||||
<th class="info-header" style="width: 25%;">VENDOR REF</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.date_planned" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-field="doc.user_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.partner_ref or '-'"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<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%;">TAX</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-else="">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td><span t-esc="line.name"/></td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(line.product_qty) if line.product_qty == int(line.product_qty) else line.product_qty"/>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<t t-if="doc.notes">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.notes"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_purchase_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_reports_templates.fr_landscape_styles"/>
|
||||
<div class="fr-landscape">
|
||||
<div class="page">
|
||||
|
||||
<h2>
|
||||
<t t-if="doc.state in ['draft', 'sent', 'to approve']">Request for Quotation </t>
|
||||
<t t-else="">Purchase Order </t>
|
||||
<span t-field="doc.name"/>
|
||||
</h2>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">VENDOR</th>
|
||||
<th style="width: 50%;">SHIP TO</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.dest_address_id">
|
||||
<div t-field="doc.dest_address_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone'], 'no_marker': True}"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<span t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone'], 'no_marker': True}"/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ORDER DATE</th>
|
||||
<th>EXPECTED ARRIVAL</th>
|
||||
<th>BUYER</th>
|
||||
<th>VENDOR REF</th>
|
||||
<th>PAYMENT TERMS</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.date_planned" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="text-center"><span t-field="doc.user_id"/></td>
|
||||
<td class="text-center"><span t-esc="doc.partner_ref or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.payment_term_id"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<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%;">TAX</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-else="">
|
||||
<tr>
|
||||
<td class="text-center"><span t-esc="line.product_id.default_code or ''"/></td>
|
||||
<td><span t-esc="line.name"/></td>
|
||||
<td class="text-center">
|
||||
<span t-esc="int(line.product_qty) if line.product_qty == int(line.product_qty) else line.product_qty"/>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<t t-if="doc.notes">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Notes:</strong>
|
||||
<div t-field="doc.notes"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
271
fusion_reports_templates/report/report_receipt.xml
Normal file
271
fusion_reports_templates/report/report_receipt.xml
Normal file
@@ -0,0 +1,271 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Payment Receipt — portrait + landscape.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_receipt_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 if doc.partner_id else 'en_US')"/>
|
||||
<t t-call="fusion_reports_templates.fr_portrait_styles"/>
|
||||
<div class="fr-report">
|
||||
<div class="page">
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<h4>
|
||||
Payment Receipt <span t-field="doc.name"/>
|
||||
</h4>
|
||||
<div class="paid-stamp">RECEIPT</div>
|
||||
</div>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">
|
||||
<t t-if="doc.payment_type == 'inbound'">RECEIVED FROM</t>
|
||||
<t t-else="">PAID TO</t>
|
||||
</th>
|
||||
<th style="width: 50%;">
|
||||
<t t-if="doc.payment_type == 'inbound'">PAID TO</t>
|
||||
<t t-else="">PAID BY</t>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px;">
|
||||
<t t-if="doc.partner_id">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</t>
|
||||
</td>
|
||||
<td style="height: 70px;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<span t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 25%;">PAYMENT DATE</th>
|
||||
<th class="info-header" style="width: 25%;">REFERENCE</th>
|
||||
<th class="info-header" style="width: 25%;">METHOD</th>
|
||||
<th class="info-header" style="width: 25%;">JOURNAL</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-esc="doc.ref or doc.memo or '-'"/></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>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<tr>
|
||||
<td class="fr-header-primary text-center" style="width: 50%; font-size: 14pt; padding: 14px;">
|
||||
<strong>AMOUNT</strong>
|
||||
</td>
|
||||
<td class="text-center" style="width: 50%; font-size: 18pt; padding: 14px;">
|
||||
<strong>
|
||||
<span t-field="doc.amount" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<t t-if="doc.reconciled_invoice_ids">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Applied to:</strong>
|
||||
<table class="bordered" style="margin-top: 6px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 30%;">DOCUMENT</th>
|
||||
<th style="width: 25%;">DATE</th>
|
||||
<th style="width: 25%;">ORIGINAL AMT</th>
|
||||
<th style="width: 20%;">OUTSTANDING</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>
|
||||
<td class="text-end">
|
||||
<span t-field="inv.amount_residual" t-options='{"widget": "monetary", "display_currency": inv.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-if="doc.memo">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Memo:</strong>
|
||||
<span t-field="doc.memo"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="row" style="margin-top: 40px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Authorized Signature / Date</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_receipt_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 if doc.partner_id else 'en_US')"/>
|
||||
<t t-call="fusion_reports_templates.fr_landscape_styles"/>
|
||||
<div class="fr-landscape">
|
||||
<div class="page">
|
||||
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<h2>Payment Receipt <span t-field="doc.name"/></h2>
|
||||
<div class="paid-stamp">RECEIPT</div>
|
||||
</div>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;">
|
||||
<t t-if="doc.payment_type == 'inbound'">RECEIVED FROM</t>
|
||||
<t t-else="">PAID TO</t>
|
||||
</th>
|
||||
<th style="width: 50%;">
|
||||
<t t-if="doc.payment_type == 'inbound'">PAID TO</t>
|
||||
<t t-else="">PAID BY</t>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<t t-if="doc.partner_id">
|
||||
<div t-field="doc.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['name', 'address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</t>
|
||||
</td>
|
||||
<td style="height: 70px; font-size: 12pt;">
|
||||
<strong><span t-field="doc.company_id.name"/></strong><br/>
|
||||
<span t-field="doc.company_id.partner_id"
|
||||
t-options="{'widget': 'contact', 'fields': ['address', 'phone', 'email'], 'no_marker': True}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PAYMENT DATE</th>
|
||||
<th>REFERENCE</th>
|
||||
<th>METHOD</th>
|
||||
<th>JOURNAL</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-esc="doc.ref or doc.memo or '-'"/></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>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<tr>
|
||||
<td class="fr-header-primary text-center" style="width: 50%; font-size: 16pt; padding: 18px;">
|
||||
<strong>AMOUNT</strong>
|
||||
</td>
|
||||
<td class="text-center" style="width: 50%; font-size: 22pt; padding: 18px;">
|
||||
<strong>
|
||||
<span t-field="doc.amount" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<t t-if="doc.reconciled_invoice_ids">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Applied to:</strong>
|
||||
<table class="bordered" style="margin-top: 6px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 30%;">DOCUMENT</th>
|
||||
<th style="width: 25%;">DATE</th>
|
||||
<th style="width: 25%;">ORIGINAL AMT</th>
|
||||
<th style="width: 20%;">OUTSTANDING</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>
|
||||
<td class="text-end">
|
||||
<span t-field="inv.amount_residual" t-options='{"widget": "monetary", "display_currency": inv.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-if="doc.memo">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Memo:</strong>
|
||||
<span t-field="doc.memo"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="row" style="margin-top: 40px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Authorized Signature / Date</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
355
fusion_reports_templates/report/report_sale.xml
Normal file
355
fusion_reports_templates/report/report_sale.xml
Normal file
@@ -0,0 +1,355 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2026 Nexa Systems Inc.
|
||||
License OPL-1 (Odoo Proprietary License v1.0)
|
||||
Quotation / Sales Order — portrait + landscape.
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- PORTRAIT -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_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_reports_templates.fr_portrait_styles"/>
|
||||
<div class="fr-report">
|
||||
<div class="page">
|
||||
|
||||
<h4>
|
||||
<span t-if="doc.state in ['draft','sent']">Quotation </span>
|
||||
<span t-else="">Sales Order </span>
|
||||
<span t-field="doc.name"/>
|
||||
</h4>
|
||||
|
||||
<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>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="info-header" style="width: 25%;">ORDER DATE</th>
|
||||
<th class="info-header" style="width: 25%;">EXPIRATION</th>
|
||||
<th class="info-header" style="width: 25%;">SALESPERSON</th>
|
||||
<th class="info-header" style="width: 25%;">CUSTOMER REF</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.client_order_ref or '-'"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table class="bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 12%;">SKU</th>
|
||||
<th class="text-start" style="width: 38%;">DESCRIPTION</th>
|
||||
<th style="width: 8%;">QTY</th>
|
||||
<th style="width: 8%;">UOM</th>
|
||||
<th style="width: 14%;">UNIT PRICE</th>
|
||||
<th style="width: 8%;">TAX</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 or line.display_type == 'product'">
|
||||
<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_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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Terms and Conditions:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="row" style="margin-top: 25px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Customer Acceptance (Signature / Date)</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<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>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<!-- ============================================================= -->
|
||||
<!-- LANDSCAPE -->
|
||||
<!-- ============================================================= -->
|
||||
<template id="report_fr_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_reports_templates.fr_landscape_styles"/>
|
||||
<div class="fr-landscape">
|
||||
<div class="page">
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<table class="bordered info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ORDER DATE</th>
|
||||
<th>EXPIRATION</th>
|
||||
<th>SALESPERSON</th>
|
||||
<th>CUSTOMER REF</th>
|
||||
<th>PAYMENT TERMS</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.client_order_ref or '-'"/></td>
|
||||
<td class="text-center"><span t-field="doc.payment_term_id"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<t t-set="has_discount" t-value="any(l.discount for l in doc.order_line)"/>
|
||||
<t t-set="col_count" t-value="8 if has_discount else 7"/>
|
||||
<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 t-if="has_discount" style="width: 10%;">DISCOUNT</th>
|
||||
<th style="width: 10%;">TAX</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 t-att-colspan="col_count"><strong t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="line.display_type == 'line_note'">
|
||||
<tr class="note-row"><td t-att-colspan="col_count"><span t-field="line.name"/></td></tr>
|
||||
</t>
|
||||
<t t-elif="not line.display_type or line.display_type == 'product'">
|
||||
<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_id"/></td>
|
||||
<td class="text-end">
|
||||
<span t-field="line.price_unit" t-options='{"widget": "monetary", "display_currency": doc.currency_id}'/>
|
||||
</td>
|
||||
<td t-if="has_discount" 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>
|
||||
|
||||
<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>
|
||||
</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>
|
||||
|
||||
<t t-if="doc.note">
|
||||
<div style="margin-top: 15px;">
|
||||
<strong>Terms and Conditions:</strong>
|
||||
<div t-field="doc.note"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div class="row" style="margin-top: 25px;">
|
||||
<div class="col-6">
|
||||
<div class="sig-line"/>
|
||||
<div class="small-muted">Customer Acceptance (Signature / Date)</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<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>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
1
fusion_reports_templates/security/ir.model.access.csv
Normal file
1
fusion_reports_templates/security/ir.model.access.csv
Normal file
@@ -0,0 +1 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
|
Reference in New Issue
Block a user