[FIX] account: process duplicate tax lines when creating CABA entries

- Enable cash basis (Accounting>Settings>Taxes)
- Enable analytic accounting  (Accounting>Settings>Analytics)
- Have a sale tax:
  - Based on payment (Account 10100 Current Assets)
  - Included in Analytic Cost
- Create a [DEMO] product with such tax
- Create an invoice with 2 lines:
  - One line with product DEMO and whatever analytic account
  - One line with product DEMO but no analytic account
-Confirm and receive payment

CABA entry will consider only 1 tax line, because the
2 entries are equal beside the analytic account which is not considered
in the grouping keys

opw-2507417

closes odoo/odoo#71556

X-original-commit: 2a8f777c04bdbdce77dc44d92e099612f158cbef
Signed-off-by: oco-odoo <oco-odoo@users.noreply.github.com>
This commit is contained in:
Andrea Grazioso (agr-odoo)
2021-06-01 13:24:33 +00:00
committed by oco-odoo
parent efce576e56
commit 85c8a47844
3 changed files with 87 additions and 26 deletions
+13 -6
View File
@@ -4540,12 +4540,19 @@ class AccountMoveLine(models.Model):
if line.tax_repartition_line_id:
# Tax line.
grouping_key = self.env['account.partial.reconcile']._get_cash_basis_tax_line_grouping_key_from_record(line)
account_vals_to_fix[grouping_key] = {
**vals,
'account_id': line.account_id.id,
'tax_base_amount': line.tax_base_amount,
'tax_repartition_line_id': line.tax_repartition_line_id.id,
}
if grouping_key in account_vals_to_fix:
account_vals_to_fix[grouping_key].update({
'debit': account_vals_to_fix[grouping_key]['debit'] + vals['debit'],
'credit': account_vals_to_fix[grouping_key]['credit'] + vals['credit'],
'tax_base_amount': account_vals_to_fix[grouping_key]['tax_base_amount'] + line.tax_base_amount,
})
else:
account_vals_to_fix[grouping_key] = {
**vals,
'account_id': line.account_id.id,
'tax_base_amount': line.tax_base_amount,
'tax_repartition_line_id': line.tax_repartition_line_id.id,
}
elif line.tax_ids:
# Base line.
account_to_fix = line.company_id.account_cash_basis_base_account_id
@@ -427,33 +427,35 @@ class AccountPartialReconcile(models.Model):
if line.tax_repartition_line_id:
# Tax line.
cb_tax_line_vals = self._prepare_cash_basis_tax_line_vals(line, balance, amount_currency)
grouping_key = self._get_cash_basis_tax_line_grouping_key_from_vals(cb_tax_line_vals)
partial_lines_to_create[grouping_key] = {
'tax_line': line,
'vals': cb_tax_line_vals,
}
cb_line_vals = self._prepare_cash_basis_tax_line_vals(line, balance, amount_currency)
grouping_key = self._get_cash_basis_tax_line_grouping_key_from_vals(cb_line_vals)
elif line.tax_ids:
# Base line.
cb_base_line_vals = self._prepare_cash_basis_base_line_vals(line, balance, amount_currency)
grouping_key = self._get_cash_basis_base_line_grouping_key_from_vals(cb_base_line_vals)
cb_line_vals = self._prepare_cash_basis_base_line_vals(line, balance, amount_currency)
grouping_key = self._get_cash_basis_base_line_grouping_key_from_vals(cb_line_vals)
if grouping_key in partial_lines_to_create:
aggregated_vals = partial_lines_to_create[grouping_key]['vals']
balance = aggregated_vals['debit'] - aggregated_vals['credit']
balance += cb_base_line_vals['debit'] - cb_base_line_vals['credit']
if grouping_key in partial_lines_to_create:
aggregated_vals = partial_lines_to_create[grouping_key]['vals']
aggregated_vals.update({
'debit': aggregated_vals['debit'] + cb_line_vals['debit'],
'credit': aggregated_vals['credit'] + cb_line_vals['credit'],
'amount_currency': aggregated_vals['amount_currency'] + cb_line_vals['amount_currency'],
})
if line.tax_repartition_line_id:
aggregated_vals.update({
'debit': balance if balance > 0.0 else 0.0,
'credit': -balance if balance < 0.0 else 0.0,
'tax_base_amount': aggregated_vals['tax_base_amount'] + cb_line_vals['tax_base_amount'],
})
partial_lines_to_create[grouping_key]['tax_line'] += line
else:
partial_lines_to_create[grouping_key] = {
'vals': cb_line_vals,
}
if line.tax_repartition_line_id:
partial_lines_to_create[grouping_key].update({
'tax_line': line,
})
aggregated_vals['amount_currency'] += cb_base_line_vals['amount_currency']
else:
partial_lines_to_create[grouping_key] = {
'vals': cb_base_line_vals,
}
# ==========================================================================
# Create the counterpart journal items.
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests import tagged
from odoo.tests.common import Form
from odoo import fields
@tagged('post_install', '-at_install')
@@ -2076,6 +2078,56 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
# Check full reconciliation
self.assertTrue(all(line.full_reconcile_id for line in lines_to_reconcile), "All tax lines should be fully reconciled")
def test_caba_double_tax(self):
""" Test the CABA entries generated from an invoice with almost
equal lines, different only on analytic accounting
"""
# Make the tax account reconcilable
self.tax_account_1.reconcile = True
# Create an invoice with a CABA tax using 'Include in analytic cost'
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice', account_predictive_bills_disable_prediction=True))
move_form.invoice_date = fields.Date.from_string('2019-01-01')
move_form.partner_id = self.partner_a
self.cash_basis_tax_a_third_amount.analytic = True
test_analytic_account = self.env['account.analytic.account'].create({'name': 'test_analytic_account'})
tax = self.cash_basis_tax_a_third_amount
# line with analytic account, will generate 2 lines in CABA move
with move_form.invoice_line_ids.new() as line_form:
line_form.name = "test line with analytic account"
line_form.product_id = self.product_a
line_form.tax_ids.clear()
line_form.tax_ids.add(tax)
line_form.analytic_account_id = test_analytic_account
line_form.price_unit = 100
# line with analytic account, will generate other 2 lines in CABA move
# even if the tax is the same
with move_form.invoice_line_ids.new() as line_form:
line_form.name = "test line"
line_form.product_id = self.product_a
line_form.tax_ids.clear()
line_form.tax_ids.add(tax)
line_form.price_unit = 100
rslt = move_form.save()
rslt.action_post()
pmt_wizard = self.env['account.payment.register'].with_context(active_model='account.move', active_ids=rslt.ids).create({
'amount': rslt.amount_total,
'payment_date': rslt.date,
'journal_id': self.company_data['default_journal_bank'].id,
'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id,
})
pmt_wizard._create_payments()
partial_rec = rslt.mapped('line_ids.matched_debit_ids')
caba_move = self.env['account.move'].search([('tax_cash_basis_rec_id', '=', partial_rec.id)])
self.assertEqual(len(caba_move.line_ids), 4, "All lines should be there")
self.assertEqual(caba_move.line_ids.filtered(lambda x: x.tax_line_id).balance, 66.66, "Tax amount should take into account both lines")
def test_caba_dest_acc_reconciliation_partial_pmt(self):
""" Test the reconciliation of tax lines (when using a reconcilable tax account)
for partially paid invoices with cash basis taxes.