diff --git a/addons/account/models/account.py b/addons/account/models/account.py
index f77eee4d956..e8323f7536e 100644
--- a/addons/account/models/account.py
+++ b/addons/account/models/account.py
@@ -1173,7 +1173,8 @@ class AccountTax(models.Model):
str(invoice_tax_val['account_id']) + '-' + \
str(invoice_tax_val['account_analytic_id']) + '-' + \
str(invoice_tax_val.get('analytic_tag_ids', [])) + '-' + \
- str(invoice_tax_val.get('tax_ids') or [])
+ str(invoice_tax_val.get('tax_ids') or []) + '-' + \
+ str(invoice_tax_val.get('tag_ids') or [])
def _compute_amount(self, base_amount, price_unit, quantity=1.0, product=None, partner=None):
""" Returns the amount of a single tax. base_amount is the actual amount on which the tax is applied, which is
@@ -1391,12 +1392,22 @@ class AccountTax(models.Model):
if tax.price_include and not total_included_checkpoints.get(i):
cumulated_tax_included_amount += tax_amount
+ # If the tax affects the base of subsequent taxes, its tax move lines must
+ # receive the base tags of these taxes, so that the tax report computes
+ # the right total
+ additional_tags = self.env['account.account.tag']
+ if tax.include_base_amount:
+ next_taxes_rep = taxes[i+1:].mapped(is_refund and 'refund_repartition_line_ids' or 'invoice_repartition_line_ids')
+ additional_tags += next_taxes_rep.filtered(lambda x: x.repartition_type == 'base').mapped('tag_ids')
+
+ # Compute the tax lines
tax_repartition_lines = is_refund and tax.refund_repartition_line_ids or tax.invoice_repartition_line_ids
repartition_lines_to_treat = len(tax_repartition_lines)
total_amount = 0
for repartition_line in tax_repartition_lines.filtered(lambda x: x.repartition_type == 'tax'):
# In case some rounding error occurs, we compensate for it on the last line
line_amount = round(sign * tax_amount * repartition_line.factor if repartition_lines_to_treat != 1 else tax_amount - total_amount, prec)
+
taxes_vals.append({
'id': tax.id,
'name': partner and tax.with_context(lang=partner.lang).name or tax.name,
@@ -1408,7 +1419,7 @@ class AccountTax(models.Model):
'price_include': tax.price_include,
'tax_exigibility': tax.tax_exigibility,
'tax_repartition_line_id': repartition_line.id,
- 'tag_ids': [(6, False, repartition_line.tag_ids.ids)],
+ 'tag_ids': [(6, False, (repartition_line.tag_ids + additional_tags).ids)],
})
total_amount += line_amount
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 4dff98dd9ae..b76eb0c6886 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -1098,6 +1098,7 @@ class AccountInvoice(models.Model):
'analytic_tag_ids': tax['analytic'] and line.analytic_tag_ids.ids or False,
'tax_ids': tax_ids and [(6, None, tax_ids)] or False,
'tax_repartition_line_id': tax.get('tax_repartition_line_id'), # For base amount, we let this field empty
+ 'tag_ids': tax['tag_ids'],
}
# If the taxes generate moves on the same financial account as the invoice line,
@@ -1265,7 +1266,6 @@ class AccountInvoice(models.Model):
def tax_line_move_line_get(self):
self.ensure_one()
-
res = []
# loop the invoice.tax.line in reversal sequence
for tax_line in sorted(self.tax_line_ids, key=lambda x: -x.sequence):
@@ -1285,7 +1285,8 @@ class AccountInvoice(models.Model):
'invoice_id': self.id,
'tax_ids': tax_line.tax_ids and [(6, 0, tax_line.tax_ids.ids)] or False, # We don't pass an empty recordset here, as it would reset the tax_exibility of the line, due to the condition in account.move.line's create
'tax_repartition_line_id': tax_line.tax_repartition_line_id.id,
- 'tag_ids': [(6, 0, tax_line.tax_repartition_line_id.tag_ids.ids)],
+ 'tag_ids': [(6, 0, tax_line.tag_ids.ids)],
+ 'tax_base_amount': tax_line.base,
})
return res
@@ -2145,8 +2146,8 @@ class AccountInvoiceTax(models.Model):
company_id = fields.Many2one('res.company', string='Company', related='account_id.company_id', store=True, readonly=True)
currency_id = fields.Many2one('res.currency', related='invoice_id.currency_id', store=True, readonly=True)
base = fields.Monetary(string='Base')
- tax_ids = fields.Many2many('account.tax', string='Affecting Base Taxes',
- help='Taxes affecting the tax base amount applied before this one.')
+ tax_ids = fields.Many2many('account.tax', string='Affecting Base Taxes', help='Taxes affecting the tax base amount applied before this one.')
+ tag_ids = fields.Many2many(string="Tags", comodel_name='account.account.tag', help="The taxes that will be applied on the move line generated for this tax entry")
@api.depends('amount', 'amount_rounding')
def _compute_amount_total(self):
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 22c45f3feed..4c17e8f5129 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -289,6 +289,7 @@ class AccountMove(models.Model):
'company_currency_id': self.company_id.currency_id.id,
'tax_repartition_line_id': line_vals['tax_repartition_line_id'],
'tag_ids': line_vals['tag_ids'],
+ 'tax_base_amount': line_vals['base'],
}
# N.B. currency_id/amount_currency are not set because if we have two lines with the same tax
# and different currencies, we have no idea which currency set on this line.
@@ -619,15 +620,6 @@ class AccountMoveLine(models.Model):
move_line.credit_cash_basis = move_line.credit
move_line.balance_cash_basis = move_line.debit_cash_basis - move_line.credit_cash_basis
- @api.depends('move_id.line_ids', 'move_id.line_ids.tax_line_id', 'move_id.line_ids.debit', 'move_id.line_ids.credit')
- def _compute_tax_base_amount(self):
- for move_line in self:
- if move_line.tax_line_id:
- base_lines = move_line.move_id.line_ids.filtered(lambda line: move_line.tax_line_id in line.tax_ids)
- move_line.tax_base_amount = abs(sum(base_lines.mapped('balance')))
- else:
- move_line.tax_base_amount = 0
-
@api.depends('move_id')
def _compute_parent_state(self):
for record in self.filtered('move_id'):
@@ -655,7 +647,7 @@ class AccountMoveLine(models.Model):
help="The residual amount on a journal item expressed in the company currency.")
amount_residual_currency = fields.Monetary(compute='_amount_residual', string='Residual Amount in Currency', store=True,
help="The residual amount on a journal item expressed in its currency (possibly not the company currency).")
- tax_base_amount = fields.Monetary(string="Base Amount", compute='_compute_tax_base_amount', currency_field='company_currency_id', store=True)
+ tax_base_amount = fields.Monetary(string="Base Amount", currency_field='company_currency_id')
account_id = fields.Many2one('account.account', string='Account', required=True, index=True,
ondelete="cascade", domain=[('deprecated', '=', False)], default=lambda self: self._context.get('account_id', False))
move_id = fields.Many2one('account.move', string='Journal Entry', ondelete="cascade",
@@ -1725,6 +1717,7 @@ class AccountPartialReconcile(models.Model):
'move_id': newly_created_move.id,
'partner_id': line.partner_id.id,
'tax_repartition_line_id': line.tax_repartition_line_id.id,
+ 'tax_base_amount': line.tax_base_amount,
'tag_ids': [(6, 0, line.tag_ids.ids)],
})
if line.account_id.reconcile:
@@ -1750,6 +1743,7 @@ class AccountPartialReconcile(models.Model):
'amount_currency': self.amount_currency and line.currency_id.round(line.amount_currency * amount / line.balance) or 0.0,
'partner_id': line.partner_id.id,
'tax_repartition_line_id': line.tax_repartition_line_id.id,
+ 'tax_base_amount': line.tax_base_amount,
'tag_ids': [(6, 0, line.tag_ids.ids)],
})
self.env['account.move.line'].with_context(check_move_validity=False).create({
diff --git a/addons/account/models/product.py b/addons/account/models/product.py
index aa1c2bd8922..74122687dbe 100644
--- a/addons/account/models/product.py
+++ b/addons/account/models/product.py
@@ -81,4 +81,5 @@ class ProductProduct(models.Model):
'analytic_tag_ids': line.get('analytic_tag_ids', False),
'tax_repartition_line_id': line.get('tax_repartition_line_id'),
'tag_ids': line.get('tag_ids'),
+ 'tax_base_amount': line.get('tax_base_amount'),
}
diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py
index 67e2ae40478..01eb2c80c9c 100644
--- a/addons/account/tests/test_reconciliation.py
+++ b/addons/account/tests/test_reconciliation.py
@@ -1304,6 +1304,7 @@ class TestReconciliationExec(TestReconciliation):
'debit': 16.67,
'move_id': purchase_move.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
+ 'tax_base_amount': 83.33,
})
purchase_move.post()
@@ -1422,6 +1423,7 @@ class TestReconciliationExec(TestReconciliation):
'debit': 5,
'move_id': purchase_move.id,
'tax_repartition_line_id': tax_cash_basis10percent.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
+ 'tax_base_amount': 50,
})
AccountMoveLine.create({
'name': 'expenseTaxed 20%',
@@ -1436,6 +1438,7 @@ class TestReconciliationExec(TestReconciliation):
'debit': 16.67,
'move_id': purchase_move.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
+ 'tax_base_amount': 83.33,
})
purchase_move.post()
@@ -1646,6 +1649,7 @@ class TestReconciliationExec(TestReconciliation):
'currency_id': self.currency_usd_id,
'amount_currency': 848.16,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
+ 'tax_base_amount': 106841.65,
})
purchase_payable_line0 = aml_obj.create({
'name': 'Payable',
@@ -1816,6 +1820,7 @@ class TestReconciliationExec(TestReconciliation):
'debit': 17094.66,
'move_id': purchase_move.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
+ 'tax_base_amount': 106841.65,
'currency_id': self.currency_usd_id,
'amount_currency': 848.16,
})
@@ -1975,6 +1980,7 @@ class TestReconciliationExec(TestReconciliation):
'debit': 5,
'move_id': purchase_move.id,
'tax_repartition_line_id': tax_cash_basis10percent.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
+ 'tax_base_amount': 50,
})
AccountMoveLine.create({
'name': 'expenseTaxed 20%',
@@ -1989,6 +1995,7 @@ class TestReconciliationExec(TestReconciliation):
'debit': 20,
'move_id': purchase_move.id,
'tax_repartition_line_id': self.tax_cash_basis.invoice_repartition_line_ids.filtered(lambda x: x.repartition_type == 'tax').id,
+ 'tax_base_amount': 100,
})
purchase_move.post()
diff --git a/addons/account/views/account_invoice_view.xml b/addons/account/views/account_invoice_view.xml
index c575dc42560..6dd9552541b 100644
--- a/addons/account/views/account_invoice_view.xml
+++ b/addons/account/views/account_invoice_view.xml
@@ -366,6 +366,7 @@
+
@@ -634,6 +635,7 @@
+
diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml
index 2f88e9ea33d..73f6dd8105c 100644
--- a/addons/account/views/account_move_views.xml
+++ b/addons/account/views/account_move_views.xml
@@ -360,6 +360,7 @@
+
diff --git a/addons/account/wizard/wizard_tax_adjustments.py b/addons/account/wizard/wizard_tax_adjustments.py
index 52d674f00fe..6afa83d9bbb 100644
--- a/addons/account/wizard/wizard_tax_adjustments.py
+++ b/addons/account/wizard/wizard_tax_adjustments.py
@@ -37,6 +37,7 @@ class TaxAdjustments(models.TransientModel):
'credit': not is_debit and abs(self.amount) or 0,
'account_id': is_debit and self.debit_account_id.id or self.credit_account_id.id,
'tax_repartition_line_id': repartition_line.id,
+ 'tax_base_amount': tax_vals['base'],
'tag_ids': [(6, False, repartition_line.tag_ids.ids)],
}))
diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py
index d70ab25c388..9ea4c4753b0 100644
--- a/addons/hr_expense/models/hr_expense.py
+++ b/addons/hr_expense/models/hr_expense.py
@@ -325,6 +325,7 @@ class HrExpense(models.Model):
'amount_currency': amount_currency if different_currency else 0.0,
'account_id': tax['account_id'] or move_line_src['account_id'],
'tax_repartition_line_id': tax['tax_repartition_line_id'],
+ 'tax_base_amount': tax['base'],
'expense_id': expense.id,
'partner_id': partner_id,
'currency_id': expense.currency_id.id if different_currency else False,
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index 52dc13a0a0f..bf13410b137 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -326,6 +326,7 @@ class PosOrder(models.Model):
'partner_id': partner_id,
'order_id': order.id,
'tax_repartition_line_id': tax['tax_repartition_line_id'],
+ 'tax_base_amount': tax['base'],
'tag_ids': tax['tag_ids'],
}
if currency_id != cur_company: