diff --git a/addons/account/models/account_tax.py b/addons/account/models/account_tax.py index ca4e317be12..ff863ec2fd4 100644 --- a/addons/account/models/account_tax.py +++ b/addons/account/models/account_tax.py @@ -741,7 +741,7 @@ class AccountTax(models.Model): 'amount': sign * line_amount, 'base': float_round(sign * tax_base_amount, precision_rounding=prec), 'sequence': tax.sequence, - 'account_id': repartition_line._get_aml_target_tax_account().id, + 'account_id': repartition_line._get_aml_target_tax_account(force_caba_exigibility=include_caba_tags).id, 'analytic': tax.analytic, 'use_in_tax_closing': repartition_line.use_in_tax_closing, 'price_include': price_include, @@ -825,7 +825,7 @@ class AccountTax(models.Model): } @api.model - def _get_generation_dict_from_base_line(self, line_vals, tax_vals): + def _get_generation_dict_from_base_line(self, line_vals, tax_vals, force_caba_exigibility=False): """ Take a tax results returned by the taxes computation method and return a dictionary representing the way the tax amounts will be grouped together. To do so, the dictionary will be converted into a string key. Then, the existing tax lines sharing the same key will be updated and the missing ones will be created. @@ -835,7 +835,7 @@ class AccountTax(models.Model): :return: A python dict. """ tax_repartition_line = tax_vals['tax_repartition_line'] - tax_account = tax_repartition_line._get_aml_target_tax_account() or line_vals['account'] + tax_account = tax_repartition_line._get_aml_target_tax_account(force_caba_exigibility=force_caba_exigibility) or line_vals['account'] return { 'account_id': tax_account.id, 'currency_id': line_vals['currency'].id, @@ -1129,7 +1129,7 @@ class AccountTax(models.Model): existing_tax_line_map[grouping_key] = line_vals def grouping_key_generator(base_line, tax_values): - return self._get_generation_dict_from_base_line(base_line, tax_values) + return self._get_generation_dict_from_base_line(base_line, tax_values, force_caba_exigibility=include_caba_tags) # Update/create the tax lines. global_tax_details = self._aggregate_taxes(to_process, grouping_key_generator=grouping_key_generator) @@ -1387,13 +1387,13 @@ class AccountTaxRepartitionLine(models.Model): if self.repartition_type == 'base': self.account_id = None - def _get_aml_target_tax_account(self): + def _get_aml_target_tax_account(self, force_caba_exigibility=False): """ Get the default tax account to set on a business line. :return: An account.account record or an empty recordset. """ self.ensure_one() - if self.tax_id.tax_exigibility == 'on_payment' and not self._context.get('caba_no_transition_account'): + if not force_caba_exigibility and self.tax_id.tax_exigibility == 'on_payment' and not self._context.get('caba_no_transition_account'): return self.tax_id.cash_basis_transition_account_id else: return self.account_id diff --git a/addons/account/tests/test_account_move_entry.py b/addons/account/tests/test_account_move_entry.py index a3d5bcedb01..8936f78e3d6 100644 --- a/addons/account/tests/test_account_move_entry.py +++ b/addons/account/tests/test_account_move_entry.py @@ -906,3 +906,62 @@ class TestAccountMove(AccountTestInvoicingCommon): self.assertTrue(exchange_diff) with self.assertRaises(UserError), self.cr.savepoint(): exchange_diff.button_draft() + + def test_always_exigible_caba_account(self): + """ Always exigible misc operations (so, the ones without payable/receivable line) with cash basis + taxes should see their tax lines use the final tax account, not the transition account. + """ + tax_account = self.company_data['default_account_tax_sale'] + + caba_tax = self.env['account.tax'].create({ + 'name': "CABA", + 'amount_type': 'percent', + 'amount': 20.0, + 'tax_exigibility': 'on_payment', + 'cash_basis_transition_account_id': self.safe_copy(tax_account).id, + 'invoice_repartition_line_ids': [ + (0, 0, { + 'repartition_type': 'base', + }), + (0, 0, { + 'repartition_type': 'tax', + 'account_id': tax_account.id, + }), + ], + 'refund_repartition_line_ids': [ + (0, 0, { + 'repartition_type': 'base', + }), + (0, 0, { + 'repartition_type': 'tax', + 'account_id': tax_account.id, + }), + ], + }) + + move_form = Form(self.env['account.move'].with_context(default_move_type='entry')) + + # Create a new account.move.line with debit amount. + income_account = self.company_data['default_account_revenue'] + with move_form.line_ids.new() as debit_line: + debit_line.name = 'debit' + debit_line.account_id = income_account + debit_line.debit = 120 + + with move_form.line_ids.new() as credit_line: + credit_line.name = 'credit' + credit_line.account_id = income_account + credit_line.credit = 100 + credit_line.tax_ids.clear() + credit_line.tax_ids.add(caba_tax) + + move = move_form.save() + + self.assertTrue(move.always_tax_exigible) + + self.assertRecordValues(move.line_ids.sorted(lambda x: -x.balance), [ + # pylint: disable=C0326 + {'name': 'debit', 'debit': 120.0, 'credit': 0.0, 'account_id': income_account.id, 'tax_ids': [], 'tax_line_id': False}, + {'name': 'CABA', 'debit': 0.0, 'credit': 20.0, 'account_id': tax_account.id, 'tax_ids': [], 'tax_line_id': caba_tax.id}, + {'name': 'credit', 'debit': 0.0, 'credit': 100.0, 'account_id': income_account.id, 'tax_ids': caba_tax.ids, 'tax_line_id': False}, + ]) diff --git a/addons/l10n_in/models/account.py b/addons/l10n_in/models/account.py index 43904b8bcd2..225582237f9 100644 --- a/addons/l10n_in/models/account.py +++ b/addons/l10n_in/models/account.py @@ -29,10 +29,10 @@ class AccountTax(models.Model): l10n_in_reverse_charge = fields.Boolean("Reverse charge", help="Tick this if this tax is reverse charge. Only for Indian accounting") @api.model - def _get_generation_dict_from_base_line(self, line_vals, tax_vals): + def _get_generation_dict_from_base_line(self, line_vals, tax_vals, force_caba_exigibility=False): # EXTENDS account # Group taxes also by product. - res = super()._get_generation_dict_from_base_line(line_vals, tax_vals) + res = super()._get_generation_dict_from_base_line(line_vals, tax_vals, force_caba_exigibility=force_caba_exigibility) record = line_vals['record'] if isinstance(record, models.Model)\ and record._name == 'account.move.line'\