From 149eb38b07cace0ec2118d214c56995402008efc Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 25 Jul 2018 12:12:34 +0200 Subject: [PATCH] [IMP] account, sale: convert template python logic into computed field Make simpler report edition in studio * 'amount_by_group' for account.invoice and sale.order * 'price_tax' for account.invoice.line --- addons/account/models/account_invoice.py | 37 ++++++----- addons/account/views/report_invoice.xml | 8 +-- addons/sale/models/sale.py | 61 ++++++++++++++----- addons/sale/report/sale_report_templates.xml | 2 +- addons/sale/views/sale_portal_templates.xml | 2 +- .../views/website_quote_templates.xml | 2 +- 6 files changed, 71 insertions(+), 41 deletions(-) diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 56f1e9c910e..f4fe6810f44 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -302,6 +302,7 @@ class AccountInvoice(models.Model): readonly=True, index=True, ondelete='restrict', copy=False, help="Link to the automatically generated Journal Items.") + amount_by_group = fields.Binary(string="Taxe amount by group", compute='_amount_by_group', help="type: [(name, amount, base, formated amount, formated base)]") amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_compute_amount', track_visibility='always') amount_untaxed_signed = fields.Monetary(string='Untaxed Amount in Company Currency', currency_field='company_currency_id', @@ -1488,22 +1489,21 @@ class AccountInvoice(models.Model): return 'account.mt_invoice_created' return super(AccountInvoice, self)._track_subtype(init_values) - @api.multi - def _get_tax_amount_by_group(self): - self.ensure_one() - currency = self.currency_id or self.company_id.currency_id - fmt = partial(formatLang, self.with_context(lang=self.partner_id.lang).env, currency_obj=currency) - res = {} - for line in self.tax_line_ids: - res.setdefault(line.tax_id.tax_group_id, {'base': 0.0, 'amount': 0.0}) - res[line.tax_id.tax_group_id]['amount'] += line.amount - res[line.tax_id.tax_group_id]['base'] += line.base - res = sorted(res.items(), key=lambda l: l[0].sequence) - res = [( - r[0].name, r[1]['amount'], r[1]['base'], - fmt(r[1]['amount']), fmt(r[1]['base']), - ) for r in res] - return res + def _amount_by_group(self): + for invoice in self: + currency = invoice.currency_id or invoice.company_id.currency_id + fmt = partial(formatLang, invoice.with_context(lang=invoice.partner_id.lang).env, currency_obj=currency) + res = {} + for line in invoice.tax_line_ids: + res.setdefault(line.tax_id.tax_group_id, {'base': 0.0, 'amount': 0.0}) + res[line.tax_id.tax_group_id]['amount'] += line.amount + res[line.tax_id.tax_group_id]['base'] += line.base + res = sorted(res.items(), key=lambda l: l[0].sequence) + invoice.amount_by_group = [( + r[0].name, r[1]['amount'], r[1]['base'], + fmt(r[1]['amount']), fmt(r[1]['base']), + len(res), + ) for r in res] class AccountInvoiceLine(models.Model): @@ -1538,6 +1538,10 @@ class AccountInvoiceLine(models.Model): return journal.default_credit_account_id.id return journal.default_debit_account_id.id + def _get_price_tax(self): + for l in self: + l.price_tax = l.price_total - l.price_subtotal + name = fields.Text(string='Description', required=True) origin = fields.Char(string='Source Document', help="Reference of the document that produced this invoice.") @@ -1561,6 +1565,7 @@ class AccountInvoiceLine(models.Model): price_subtotal_signed = fields.Monetary(string='Amount Signed', currency_field='company_currency_id', store=True, readonly=True, compute='_compute_price', help="Total amount in the currency of the company, negative for credit note.") + price_tax = fields.Monetary(string='Tax Amount', compute='_get_price_tax', store=False) quantity = fields.Float(string='Quantity', digits=dp.get_precision('Product Unit of Measure'), required=True, default=1) discount = fields.Float(string='Discount (%)', digits=dp.get_precision('Discount'), diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml index 31e0417b5a2..fae65fc1c29 100644 --- a/addons/account/views/report_invoice.xml +++ b/addons/account/views/report_invoice.xml @@ -107,11 +107,7 @@ - - - + - + diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index d3ac169e17b..2d6fa9e9cb1 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -4,9 +4,12 @@ import uuid from datetime import datetime, timedelta +from functools import partial +from itertools import groupby from odoo import api, fields, models, _ from odoo.exceptions import UserError, AccessError +from odoo.tools.misc import formatLang from odoo.osv import expression from odoo.tools import float_is_zero, float_compare @@ -146,6 +149,7 @@ class SaleOrder(models.Model): note = fields.Text('Terms and conditions', default=_default_note) amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', track_visibility='onchange', track_sequence=5) + amount_by_group = fields.Binary(string="Taxe amount by group", compute='_amount_by_group', help="type: [(name, amount, base, formated amount, formated base)]") amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all') amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all', track_visibility='always', track_sequence=6) @@ -617,23 +621,48 @@ class SaleOrder(models.Model): }) order.analytic_account_id = analytic - @api.multi - def _get_tax_amount_by_group(self): + def _amount_by_group(self): + for order in self: + currency = order.currency_id or order.company_id.currency_id + fmt = partial(formatLang, self.with_context(lang=order.partner_id.lang).env, currency_obj=currency) + res = {} + for line in self.order_line: + price_reduce = line.price_unit * (1.0 - line.discount / 100.0) + taxes = line.tax_id.compute_all(price_reduce, quantity=line.product_uom_qty, product=line.product_id, partner=self.partner_shipping_id)['taxes'] + for tax in line.tax_id: + group = tax.tax_group_id + res.setdefault(group, {'amount': 0.0, 'base': 0.0}) + for t in taxes: + if t['id'] == tax.id or t['id'] in tax.children_tax_ids.ids: + res[group]['amount'] += t['amount'] + res[group]['base'] += t['base'] + res = sorted(res.items(), key=lambda l: l[0].sequence) + order.amount_by_group = [( + l[0].name, l[1]['amount'], l[1]['base'], + fmt(l[1]['amount']), fmt(l[1]['base']), + len(res), + ) for l in res] + + def order_lines_layouted(self): + """ + Returns this order lines classified by sale_layout_category and separated in + pages according to the category pagebreaks. Used to render the report. + """ self.ensure_one() - res = {} - for line in self.order_line: - price_reduce = line.price_unit * (1.0 - line.discount / 100.0) - taxes = line.tax_id.compute_all(price_reduce, quantity=line.product_uom_qty, product=line.product_id, partner=self.partner_shipping_id)['taxes'] - for tax in line.tax_id: - group = tax.tax_group_id - res.setdefault(group, {'amount': 0.0, 'base': 0.0}) - for t in taxes: - if t['id'] == tax.id or t['id'] in tax.children_tax_ids.ids: - res[group]['amount'] += t['amount'] - res[group]['base'] += t['base'] - res = sorted(res.items(), key=lambda l: l[0].sequence) - res = [(l[0].name, l[1]['amount'], l[1]['base'], len(res)) for l in res] - return res + report_pages = [[]] + for category, lines in groupby(self.order_line, lambda l: l.layout_category_id): + # If last added category induced a pagebreak, this one will be on a new page + if report_pages[-1] and report_pages[-1][-1]['pagebreak']: + report_pages.append([]) + # Append category to current report page + report_pages[-1].append({ + 'name': category and category.name or _('Uncategorized'), + 'subtotal': category and category.subtotal, + 'pagebreak': category and category.pagebreak, + 'lines': list(lines) + }) + + return report_pages def get_portal_confirmation_action(self): if self.company_id.portal_confirmation_sign and not self.signature: diff --git a/addons/sale/report/sale_report_templates.xml b/addons/sale/report/sale_report_templates.xml index ef7916213fb..23ec95c586d 100644 --- a/addons/sale/report/sale_report_templates.xml +++ b/addons/sale/report/sale_report_templates.xml @@ -175,7 +175,7 @@ t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/> - + diff --git a/addons/sale/views/sale_portal_templates.xml b/addons/sale/views/sale_portal_templates.xml index a48cfe4bdf5..b71f4ae9711 100644 --- a/addons/sale/views/sale_portal_templates.xml +++ b/addons/sale/views/sale_portal_templates.xml @@ -326,7 +326,7 @@
- +
diff --git a/addons/website_quote/views/website_quote_templates.xml b/addons/website_quote/views/website_quote_templates.xml index 9b73aaf69f4..28851eb32de 100644 --- a/addons/website_quote/views/website_quote_templates.xml +++ b/addons/website_quote/views/website_quote_templates.xml @@ -140,7 +140,7 @@ /> - +