[IMP] account : invoice layout improvement
Modifies the invoice layout according to the mockup provided in the task. This enables to remove the blank space that occured in the middle of the invoices
Add the possibility to add the total amount of an invoice in words. This feature can be enabled by activating a boolean setting in Accounting settings.
Task: 3097097
Pr: 107714
Part-of: odoo/odoo#107714
This commit is contained in:
@@ -105,6 +105,12 @@ You could use this simplified accounting in case you work with an (external) acc
|
||||
'account/static/tests/helpers/*.js',
|
||||
'account/static/tests/*.js',
|
||||
],
|
||||
'web.report_assets_common': [
|
||||
'account/static/src/css/report_invoice.css',
|
||||
],
|
||||
'web.report_assets_pdf': [
|
||||
'account/static/src/css/report_invoice.css',
|
||||
],
|
||||
},
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
|
||||
@@ -449,6 +449,10 @@ class AccountMove(models.Model):
|
||||
copy=False,
|
||||
tracking=True,
|
||||
)
|
||||
amount_total_words = fields.Char(
|
||||
string="Amount total in words",
|
||||
compute="_compute_amount_total_words",
|
||||
)
|
||||
|
||||
# === Reverse feature fields === #
|
||||
reversed_entry_id = fields.Many2one(
|
||||
@@ -1425,12 +1429,17 @@ class AccountMove(models.Model):
|
||||
|
||||
@api.depends('company_id')
|
||||
def _compute_display_qr_code(self):
|
||||
for record in self:
|
||||
record.display_qr_code = (
|
||||
record.move_type in ('out_invoice', 'out_receipt', 'in_invoice', 'in_receipt')
|
||||
and record.company_id.qr_code
|
||||
for move in self:
|
||||
move.display_qr_code = (
|
||||
move.move_type in ('out_invoice', 'out_receipt', 'in_invoice', 'in_receipt')
|
||||
and move.company_id.qr_code
|
||||
)
|
||||
|
||||
@api.depends('amount_total', 'currency_id')
|
||||
def _compute_amount_total_words(self):
|
||||
for move in self:
|
||||
move.amount_total_words = move.currency_id.amount_to_text(move.amount_total).replace(',', '')
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# INVERSE METHODS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@@ -102,6 +102,7 @@ class ResCompany(models.Model):
|
||||
|
||||
invoice_is_email = fields.Boolean('Email by default', default=True)
|
||||
invoice_is_print = fields.Boolean('Print by default', default=True)
|
||||
display_invoice_amount_total_words = fields.Boolean(string='Total amount of invoice in letters')
|
||||
account_use_credit_limit = fields.Boolean(
|
||||
string='Sales Credit Limit', help='Enable the use of credit limit on partners.')
|
||||
|
||||
|
||||
@@ -133,6 +133,11 @@ class ResConfigSettings(models.TransientModel):
|
||||
readonly=False)
|
||||
terms_type = fields.Selection(
|
||||
related='company_id.terms_type', readonly=False)
|
||||
display_invoice_amount_total_words = fields.Boolean(
|
||||
string="Total amount of invoice in letters",
|
||||
related='company_id.display_invoice_amount_total_words',
|
||||
readonly=False
|
||||
)
|
||||
preview_ready = fields.Boolean(string="Display preview button", compute='_compute_terms_preview')
|
||||
|
||||
use_invoice_terms = fields.Boolean(
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#payment_terms_note_id > p {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.avoid-page-break-inside {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.justify-text {
|
||||
text-align:justify;
|
||||
text-justify:inter-word;
|
||||
}
|
||||
|
||||
#qrcode_odoo_logo {
|
||||
-webkit-transform:translate(-50%,-50%);
|
||||
height:18%;
|
||||
width:18%;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="150" height="150" fill="white"/>
|
||||
<path d="M75 150C60.1664 150 45.666 145.601 33.3323 137.36C20.9986 129.119 11.3856 117.406 5.70907 103.701C0.032495 89.9968 -1.45275 74.9168 1.44114 60.3683C4.33503 45.8197 11.4781 32.456 21.967 21.967C32.456 11.4781 45.8197 4.33503 60.3683 1.44114C74.9168 -1.45275 89.9968 0.032495 103.701 5.70907C117.406 11.3856 129.119 20.9986 137.36 33.3323C145.601 45.666 150 60.1664 150 75C150 94.8913 142.098 113.968 128.033 128.033C113.968 142.098 94.8913 150 75 150V150ZM75 119C83.7024 119 92.2094 116.419 99.4451 111.585C106.681 106.75 112.32 99.8781 115.651 91.8381C118.981 83.7982 119.852 74.9512 118.155 66.4161C116.457 57.8809 112.266 50.0408 106.113 43.8873C99.9592 37.7338 92.1192 33.5432 83.584 31.8455C75.0488 30.1477 66.2019 31.0191 58.162 34.3493C50.122 37.6796 43.2502 43.3192 38.4154 50.555C33.5806 57.7907 31 66.2977 31 75C31 86.6696 35.6357 97.8611 43.8873 106.113C52.1389 114.364 63.3305 119 75 119V119Z" fill="#714B67"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -49,7 +49,7 @@
|
||||
</t>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<div class="page">
|
||||
<div class="page mb-4">
|
||||
<h2>
|
||||
<span t-if="o.move_type == 'out_invoice' and o.state == 'posted'">Invoice</span>
|
||||
<span t-elif="o.move_type == 'out_invoice' and o.state == 'draft'">Draft Invoice</span>
|
||||
@@ -61,28 +61,27 @@
|
||||
<span t-elif="o.move_type == 'in_invoice'">Vendor Bill</span>
|
||||
<span t-if="o.name != '/'" t-field="o.name"/>
|
||||
</h2>
|
||||
|
||||
<div id="informations" class="row mt-4 mb-4">
|
||||
<div class="col-auto col-3 mw-100 mb-2" t-if="o.invoice_date" name="invoice_date">
|
||||
<div id="informations" class="row mt-3 mb-2">
|
||||
<div t-attf-class="#{'col-auto col-3 mw-100' if report_type != 'html' else 'col'} mb-2" t-if="o.invoice_date" name="invoice_date">
|
||||
<t t-if="o.move_type == 'out_invoice'"><strong>Invoice Date:</strong></t>
|
||||
<t t-elif="o.move_type == 'out_refund'"><strong>Credit Note Date:</strong></t>
|
||||
<t t-elif="o.move_type == 'out_receipt'"><strong>Receipt Date:</strong></t>
|
||||
<t t-else=""><strong>Date:</strong></t>
|
||||
<p class="m-0" t-field="o.invoice_date"/>
|
||||
</div>
|
||||
<div class="col-auto col-3 mw-100 mb-2" t-if="o.invoice_date_due and o.move_type == 'out_invoice' and o.state == 'posted'" name="due_date">
|
||||
<div t-attf-class="#{'col-auto col-3 mw-100' if report_type != 'html' else 'col'} mb-2" t-if="o.invoice_date_due and o.move_type == 'out_invoice' and o.state == 'posted'" name="due_date">
|
||||
<strong>Due Date:</strong>
|
||||
<p class="m-0" t-field="o.invoice_date_due"/>
|
||||
</div>
|
||||
<div class="col-auto col-3 mw-100 mb-2" t-if="o.invoice_origin" name="origin">
|
||||
<div t-attf-class="#{'col-auto col-3 mw-100' if report_type != 'html' else 'col'} mb-2" t-if="o.invoice_origin" name="origin">
|
||||
<strong>Source:</strong>
|
||||
<p class="m-0" t-field="o.invoice_origin"/>
|
||||
</div>
|
||||
<div class="col-auto col-3 mw-100 mb-2" t-if="o.partner_id.ref" name="customer_code">
|
||||
<div t-attf-class="#{'col-auto col-3 mw-100' if report_type != 'html' else 'col'} mb-2" t-if="o.partner_id.ref" name="customer_code">
|
||||
<strong>Customer Code:</strong>
|
||||
<p class="m-0" t-field="o.partner_id.ref"/>
|
||||
</div>
|
||||
<div class="col-auto col-3 mw-100 mb-2" t-if="o.ref" name="reference">
|
||||
<div t-attf-class="#{'col-auto col-3 mw-100' if report_type != 'html' else 'col'} mb-2" t-if="o.ref" name="reference">
|
||||
<strong>Reference:</strong>
|
||||
<p class="m-0" t-field="o.ref"/>
|
||||
</div>
|
||||
@@ -163,11 +162,11 @@
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="clearfix mb-4">
|
||||
<div id="total" class="row">
|
||||
<div t-attf-class="#{'col-6' if report_type != 'html' else 'col-sm-7 col-md-6'} ms-auto">
|
||||
<table class="table table-sm table-borderless" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
<div id="right-elements" t-attf-class="#{'col-5' if report_type != 'html' else 'col-12 col-md-5'} ms-5 d-inline-block float-end">
|
||||
<div id="total" class="clearfix row mb-2">
|
||||
<div class="ms-auto">
|
||||
<table class="table table-sm table-borderless avoid-page-break-inside">
|
||||
|
||||
<!--Tax totals-->
|
||||
<t t-set="tax_totals" t-value="o.tax_totals"/>
|
||||
@@ -194,64 +193,79 @@
|
||||
<span t-field="o.amount_residual"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<p class="text-end lh-sm" t-if="o.company_id.display_invoice_amount_total_words">
|
||||
Total amount in words: <br/>
|
||||
<small class="text-muted lh-sm"><span t-field="o.amount_total_words"/></small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p t-if="o.move_type in ('out_invoice', 'in_refund') and o.payment_reference" name="payment_communication" class="mt-4">
|
||||
Please use the following communication for your payment : <b><span t-field="o.payment_reference"/></b>
|
||||
</p>
|
||||
<t t-set="payment_term_details" t-value="o.payment_term_details"/>
|
||||
<div t-field="o.invoice_payment_term_id.note" name="payment_term"/>
|
||||
<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" class="row">
|
||||
<div t-attf-class="#{'col-10' if report_type != 'html' else 'col-sm-10 col-md-9'}">
|
||||
<t t-if="len(payment_term_details) == 1 and payment_term_details[0].get('discount_date')">
|
||||
<td>
|
||||
<span t-options='{"widget": "monetary", "display_currency": o.currency_id}'
|
||||
t-out="payment_term_details[0].get('discount_amount_currency')"/> due if paid before
|
||||
<span t-out="payment_term_details[0].get('discount_date')"/>
|
||||
</td>
|
||||
</t>
|
||||
|
||||
<t t-set="i" t-value="1"/>
|
||||
<t t-if="len(payment_term_details) > 1" t-foreach="payment_term_details" t-as="term">
|
||||
<tr>
|
||||
<span t-out="i"/> - Installment of
|
||||
<td t-options='{"widget": "monetary", "display_currency": o.currency_id}' t-out="term.get('amount')" class="text-end"/>
|
||||
<span> due on </span>
|
||||
<td t-out="term.get('date')" class="text-start"/>
|
||||
<td t-if="term.get('discount_date')" class="text-end">(
|
||||
<div>
|
||||
<div class="justify-text">
|
||||
<p t-if="not is_html_empty(o.fiscal_position_id.note)" name="note" class="mb-2">
|
||||
<span t-field="o.fiscal_position_id.note"/>
|
||||
</p>
|
||||
</div>
|
||||
<t t-set="payment_term_details" t-value="o.payment_term_details"/>
|
||||
<div class="mb-3">
|
||||
<div id="payment_terms_note_id" t-field="o.invoice_payment_term_id.note" name="payment_term"/>
|
||||
<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" class="row">
|
||||
<div t-attf-class="#{'col-10' if report_type != 'html' else 'col-sm-10 col-md-9'}">
|
||||
<t t-if="len(payment_term_details) == 1 and payment_term_details[0].get('discount_date')">
|
||||
<span t-options='{"widget": "monetary", "display_currency": o.currency_id}'
|
||||
t-out="term.get('discount_amount_currency')"/> if paid before
|
||||
<span t-out="term.get('discount_date')"/>)
|
||||
</td>
|
||||
<br/>
|
||||
</tr>
|
||||
<t t-set="i" t-value="i+1"/>
|
||||
</t>
|
||||
t-out="payment_term_details[0].get('discount_amount_currency')"/> due if paid before
|
||||
<span t-out="payment_term_details[0].get('discount_date')"/>
|
||||
</t>
|
||||
<t t-elif="len(payment_term_details) > 1" t-foreach="payment_term_details" t-as="term">
|
||||
<div>
|
||||
<span t-out="term_index + 1"/> - Installment of
|
||||
<t t-options='{"widget": "monetary", "display_currency": o.currency_id}' t-out="term.get('amount')" class="text-end"/>
|
||||
<span> due on </span>
|
||||
<t t-out="term.get('date')" class="text-start"/>
|
||||
<t t-if="term.get('discount_date')" class="text-end">(
|
||||
<span t-options='{"widget": "monetary", "display_currency": o.currency_id}'
|
||||
t-out="term.get('discount_amount_currency')"/> if paid before
|
||||
<span t-out="term.get('discount_date')"/>)
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
<div class="mb-3" t-if="o.move_type in ('out_invoice', 'in_refund') and o.payment_reference">
|
||||
<p name="payment_communication">
|
||||
Payment Communication: <span class="fw-bold" t-field="o.payment_reference"/>
|
||||
</p>
|
||||
</div>
|
||||
<div id="qrcode" class="d-flex mb-3 avoid-page-break-inside" t-if="o.display_qr_code and o.amount_residual > 0">
|
||||
<div class="qrcode me-3" id="qrcode_image">
|
||||
<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 class="d-inline text-muted lh-sm fst-italic" id="qrcode_info" t-if="qr_code_url">
|
||||
<p>Scan this QR Code to<br/>pay with your mobile</p>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
</t>
|
||||
<div t-if="not is_html_empty(o.narration)" name="comment">
|
||||
<span t-field="o.narration"/>
|
||||
</div>
|
||||
<p t-if="not is_html_empty(o.fiscal_position_id.note)" name="note">
|
||||
<span t-field="o.fiscal_position_id.note"/>
|
||||
</p>
|
||||
<p t-if="o.invoice_incoterm_id" name="incoterm">
|
||||
<strong>Incoterm: </strong><span t-field="o.invoice_incoterm_id.code"/> - <span t-field="o.invoice_incoterm_id.name"/>
|
||||
</p>
|
||||
<div id="qrcode" t-if="o.display_qr_code and o.amount_residual > 0">
|
||||
<t t-set="qr_code_url" t-value="o._generate_qr_code(silent_errors=True)"/>
|
||||
<p t-if="qr_code_url">
|
||||
<strong class="text-center">Scan me with your banking app.</strong><br/><br/>
|
||||
<img class="border border-dark rounded" t-att-src="qr_code_url"/>
|
||||
<!--terms and conditions-->
|
||||
<div class="text-muted mb-3" t-attf-style="#{'text-align:justify;text-justify:inter-word;' if o.company_id.terms_type != 'html' else ''}" t-if="not is_html_empty(o.narration)" name="comment">
|
||||
<span t-field="o.narration"/>
|
||||
</div>
|
||||
<p t-if="o.invoice_incoterm_id" name="incoterm">
|
||||
<strong>Incoterm: </strong><t t-out="o.invoice_incoterm_id.code"/> - <t t-out="o.invoice_incoterm_id.name"/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -177,6 +177,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</setting>
|
||||
<setting id="total_amount_words" help="Display the total amount of an invoice in letters">
|
||||
<field name="display_invoice_amount_total_words" widget="upgrade_boolean"/>
|
||||
</setting>
|
||||
</block>
|
||||
<block title="Customer Payments" id="pay_invoice_online_setting_container">
|
||||
<setting help="Let your customers pay their invoices online">
|
||||
|
||||
Reference in New Issue
Block a user