[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
This commit is contained in:
@@ -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'),
|
||||
|
||||
@@ -107,11 +107,7 @@
|
||||
<span t-esc="', '.join(map(lambda x: (x.description or x.name), line.invoice_line_tax_ids))"/>
|
||||
</td>
|
||||
<td t-if="display_taxamount and type_is_out" class="text-right d-none d-md-table-cell">
|
||||
<t t-set="taxes"
|
||||
t-value="line.invoice_line_tax_ids.compute_all(line.price_unit, line.currency_id, line.quantity)"/>
|
||||
<t t-set="tax_amount"
|
||||
t-value="taxes and (taxes['total_included'] - taxes['base']) or 0.0"/>
|
||||
<span t-esc="tax_amount" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
<span t-esc="line.price_tax" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span
|
||||
@@ -164,7 +160,7 @@
|
||||
<span t-field="o.amount_untaxed" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<t t-foreach="o._get_tax_amount_by_group()" t-as="amount_by_group">
|
||||
<t t-foreach="o.amount_by_group" t-as="amount_by_group">
|
||||
<tr style="border-bottom:1px solid #dddddd;">
|
||||
<t t-if="len(o.tax_line_ids) == 1 and o.amount_untaxed == amount_by_group[2]">
|
||||
<td>
|
||||
|
||||
+45
-16
@@ -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:
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<t t-foreach="doc._get_tax_amount_by_group()" t-as="amount_by_group">
|
||||
<t t-foreach="doc.amount_by_group" t-as="amount_by_group">
|
||||
<tr style="border-bottom:1px solid #dddddd;">
|
||||
<t t-if="amount_by_group[3] == 1 and doc.amount_untaxed == amount_by_group[2]">
|
||||
<td>
|
||||
|
||||
@@ -326,7 +326,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb4">
|
||||
<t t-set="tax_groups" t-value="order._get_tax_amount_by_group()"/>
|
||||
<t t-set="tax_groups" t-value="order.amount_by_group"/>
|
||||
<t t-foreach="tax_groups" t-as="amount_by_group">
|
||||
<t t-if="len(tax_groups) == 1 and order.amount_untaxed == amount_by_group[2]">
|
||||
<div class="col-lg-9 col-8 text-right"><span t-esc="amount_by_group[0]"/></div>
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<t t-foreach="quotation._get_tax_amount_by_group()" t-as="amount_by_group">
|
||||
<t t-foreach="quotation.amount_by_group" t-as="amount_by_group">
|
||||
<tr style="border-bottom:1px solid #dddddd;">
|
||||
<t t-if="amount_by_group[3] == 1 and quotation.amount_untaxed == amount_by_group[2]">
|
||||
<td>
|
||||
|
||||
Reference in New Issue
Block a user