# -*- coding: utf-8 -*- from odoo.addons.account.tests.common import AccountTestInvoicingCommon from odoo.fields import Command from odoo.tests import tagged @tagged('post_install', '-at_install') class TestTaxTotals(AccountTestInvoicingCommon): @classmethod def setUpClass(cls, chart_template_ref=None): super().setUpClass(chart_template_ref=chart_template_ref) cls.tax_group1 = cls.env['account.tax.group'].create({ 'name': '1', 'sequence': 1 }) cls.tax_group2 = cls.env['account.tax.group'].create({ 'name': '2', 'sequence': 2 }) cls.tax_group_sub1 = cls.env['account.tax.group'].create({ 'name': 'subtotals 1', 'preceding_subtotal': "PRE GROUP 1", 'sequence': 3 }) cls.tax_group_sub2 = cls.env['account.tax.group'].create({ 'name': 'subtotals 2', 'preceding_subtotal': "PRE GROUP 2", 'sequence': 4 }) cls.tax_group_sub3 = cls.env['account.tax.group'].create({ 'name': 'subtotals 3', 'preceding_subtotal': "PRE GROUP 1", # same as sub1, on purpose 'sequence': 5 }) cls.tax_16 = cls.env['account.tax'].create({ 'name': "tax_16", 'amount_type': 'percent', 'amount': 16.0, }) cls.tax_53 = cls.env['account.tax'].create({ 'name': "tax_53", 'amount_type': 'percent', 'amount': 53.0, }) cls.tax_17a = cls.env['account.tax'].create({ 'name': "tax_17a", 'amount_type': 'percent', 'amount': 17.0, }) cls.tax_17b = cls.tax_17a.copy({'name': "tax_17b"}) def assertTaxTotals(self, document, expected_values): main_keys_to_ignore = {'formatted_amount_total', 'formatted_amount_untaxed'} group_keys_to_ignore = {'group_key', 'formatted_tax_group_amount', 'formatted_tax_group_base_amount'} subtotals_keys_to_ignore = {'formatted_amount'} to_compare = document.tax_totals for key in main_keys_to_ignore: del to_compare[key] for key in group_keys_to_ignore: for groups in to_compare['groups_by_subtotal'].values(): for group in groups: del group[key] for key in subtotals_keys_to_ignore: for subtotal in to_compare['subtotals']: del subtotal[key] self.assertEqual(to_compare, expected_values) def _create_document_for_tax_totals_test(self, lines_data): """ Creates and returns a new record of a model defining a tax_totals field and using the related widget. By default, this function creates an invoice, but it is overridden in sale and purchase to create respectively a sale.order or a purchase.order. This way, we can test the invoice_tax_totals from both these models in the same way as account.move's. :param lines_data: a list of tuple (amount, taxes), where amount is a base amount, and taxes a recordset of account.tax objects corresponding to the taxes to apply on this amount. Each element of the list corresponds to a line of the document (invoice line, PO line, SO line). """ invoice_lines_vals = [ (0, 0, { 'name': 'line', 'display_type': 'product', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': amount, 'tax_ids': [(6, 0, taxes.ids)], }) for amount, taxes in lines_data] return self.env['account.move'].create({ 'move_type': 'out_invoice', 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'invoice_line_ids': invoice_lines_vals, }) def test_multiple_tax_lines(self): tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10.0, 'tax_group_id': self.tax_group1.id, }) tax_20 = self.env['account.tax'].create({ 'name': "tax_20", 'amount_type': 'percent', 'amount': 20.0, 'tax_group_id': self.tax_group2.id, }) document = self._create_document_for_tax_totals_test([ (1000, tax_10 + tax_20), (1000, tax_10), (1000, tax_20), ]) self.assertTaxTotals(document, { 'amount_total': 3600, 'amount_untaxed': 3000, 'display_tax_base': True, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 200, 'tax_group_base_amount': 2000, 'tax_group_id': self.tax_group1.id, }, { 'tax_group_name': self.tax_group2.name, 'tax_group_amount': 400, 'tax_group_base_amount': 2000, 'tax_group_id': self.tax_group2.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 3000, } ], 'subtotals_order': ["Untaxed Amount"], }) # Same but both are sharing the same tax group. tax_20.tax_group_id = self.tax_group1 document.invalidate_model(['tax_totals']) self.assertTaxTotals(document, { 'amount_total': 3600, 'amount_untaxed': 3000, 'display_tax_base': False, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 600, 'tax_group_base_amount': 3000, 'tax_group_id': self.tax_group1.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 3000, } ], 'subtotals_order': ["Untaxed Amount"], }) def test_zero_tax_lines(self): tax_0 = self.env['account.tax'].create({ 'name': "tax_0", 'amount_type': 'percent', 'amount': 0.0, }) document = self._create_document_for_tax_totals_test([ (1000, tax_0), ]) self.assertTaxTotals(document, { 'amount_total': 1000, 'amount_untaxed': 1000, 'display_tax_base': False, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': tax_0.tax_group_id.name, 'tax_group_amount': 0, 'tax_group_base_amount': 1000, 'tax_group_id': tax_0.tax_group_id.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 1000, } ], 'subtotals_order': ["Untaxed Amount"], }) def test_tax_affect_base_1(self): tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10.0, 'tax_group_id': self.tax_group1.id, 'price_include': True, 'include_base_amount': True, }) tax_20 = self.env['account.tax'].create({ 'name': "tax_20", 'amount_type': 'percent', 'amount': 20.0, 'tax_group_id': self.tax_group2.id, }) document = self._create_document_for_tax_totals_test([ (1100, tax_10 + tax_20), (1100, tax_10), (1000, tax_20), ]) self.assertTaxTotals(document, { 'amount_total': 3620, 'amount_untaxed': 3000, 'display_tax_base': True, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 200, 'tax_group_base_amount': 2000, 'tax_group_id': self.tax_group1.id, }, { 'tax_group_name': self.tax_group2.name, 'tax_group_amount': 420, 'tax_group_base_amount': 2100, 'tax_group_id': self.tax_group2.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 3000, } ], 'subtotals_order': ["Untaxed Amount"], }) # Same but both are sharing the same tax group. tax_20.tax_group_id = self.tax_group1 document.invalidate_model(['tax_totals']) self.assertTaxTotals(document, { 'amount_total': 3620, 'amount_untaxed': 3000, 'display_tax_base': False, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 620, 'tax_group_base_amount': 3000, 'tax_group_id': self.tax_group1.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 3000, } ], 'subtotals_order': ["Untaxed Amount"], }) def test_tax_affect_base_2(self): tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10.0, 'tax_group_id': self.tax_group1.id, 'include_base_amount': True, }) tax_20 = self.env['account.tax'].create({ 'name': "tax_20", 'amount_type': 'percent', 'amount': 20.0, 'tax_group_id': self.tax_group1.id, }) tax_30 = self.env['account.tax'].create({ 'name': "tax_30", 'amount_type': 'percent', 'amount': 30.0, 'tax_group_id': self.tax_group2.id, 'include_base_amount': True, }) document = self._create_document_for_tax_totals_test([ (1000, tax_10 + tax_20), (1000, tax_30 + tax_10), ]) self.assertTaxTotals(document, { 'amount_total': 2750, 'amount_untaxed': 2000, 'display_tax_base': True, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 450, 'tax_group_base_amount': 2300, 'tax_group_id': self.tax_group1.id, }, { 'tax_group_name': self.tax_group2.name, 'tax_group_amount': 300, 'tax_group_base_amount': 1000, 'tax_group_id': self.tax_group2.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 2000, } ], 'subtotals_order': ["Untaxed Amount"], }) # Same but both are sharing the same tax group. tax_30.tax_group_id = self.tax_group1 document.invalidate_model(['tax_totals']) self.assertTaxTotals(document, { 'amount_total': 2750, 'amount_untaxed': 2000, 'display_tax_base': False, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 750, 'tax_group_base_amount': 2000, 'tax_group_id': self.tax_group1.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 2000, } ], 'subtotals_order': ["Untaxed Amount"], }) def test_subtotals_basic(self): tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10.0, 'tax_group_id': self.tax_group_sub1.id, }) tax_25 = self.env['account.tax'].create({ 'name': "tax_25", 'amount_type': 'percent', 'amount': 25.0, 'tax_group_id': self.tax_group_sub2.id, }) tax_42 = self.env['account.tax'].create({ 'name': "tax_42", 'amount_type': 'percent', 'amount': 42.0, 'tax_group_id': self.tax_group1.id, }) document = self._create_document_for_tax_totals_test([ (1000, tax_10), (1000, tax_25), (100, tax_42), (200, tax_42 + tax_10 + tax_25), ]) self.assertTaxTotals(document, { 'amount_total': 2846, 'amount_untaxed': 2300, 'display_tax_base': True, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 126, 'tax_group_base_amount': 300, 'tax_group_id': self.tax_group1.id, }, ], 'PRE GROUP 1': [ { 'tax_group_name': self.tax_group_sub1.name, 'tax_group_amount': 120, 'tax_group_base_amount': 1200, 'tax_group_id': self.tax_group_sub1.id, }, ], 'PRE GROUP 2': [ { 'tax_group_name': self.tax_group_sub2.name, 'tax_group_amount': 300, 'tax_group_base_amount': 1200, 'tax_group_id': self.tax_group_sub2.id, }, ] }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 2300, }, { 'name': "PRE GROUP 1", 'amount': 2426, }, { 'name': "PRE GROUP 2", 'amount': 2546, }, ], 'subtotals_order': ["Untaxed Amount", "PRE GROUP 1", "PRE GROUP 2"], }) def test_after_total_mix(self): tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10.0, 'tax_group_id': self.tax_group_sub3.id, }) tax_25 = self.env['account.tax'].create({ 'name': "tax_25", 'amount_type': 'percent', 'amount': -25.0, 'tax_group_id': self.tax_group_sub2.id, }) tax_42 = self.env['account.tax'].create({ 'name': "tax_42", 'amount_type': 'percent', 'amount': 42.0, 'tax_group_id': self.tax_group_sub1.id, }) tax_30 = self.env['account.tax'].create({ 'name': "tax_30", 'amount_type': 'percent', 'amount': 30.0, 'tax_group_id': self.tax_group1.id, }) document = self._create_document_for_tax_totals_test([ (100, tax_10), (100, tax_25 + tax_42 + tax_30), (200, tax_10 + tax_25), (1000, tax_30), (100, tax_30 + tax_10) ]) self.assertTaxTotals(document, { 'amount_total': 1867, 'amount_untaxed': 1500, 'display_tax_base': True, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 360, 'tax_group_base_amount': 1200, 'tax_group_id': self.tax_group1.id, }, ], 'PRE GROUP 1': [ { 'tax_group_name': self.tax_group_sub1.name, 'tax_group_amount': 42, 'tax_group_base_amount': 100, 'tax_group_id': self.tax_group_sub1.id, }, { 'tax_group_name': self.tax_group_sub3.name, 'tax_group_amount': 40, 'tax_group_base_amount': 400, 'tax_group_id': self.tax_group_sub3.id, }, ], 'PRE GROUP 2': [ { 'tax_group_name': self.tax_group_sub2.name, 'tax_group_amount': -75, 'tax_group_base_amount': 300, 'tax_group_id': self.tax_group_sub2.id, }, ], }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 1500, }, { 'name': "PRE GROUP 1", 'amount': 1860, }, { 'name': "PRE GROUP 2", 'amount': 1942, }, ], 'subtotals_order': ["Untaxed Amount", "PRE GROUP 1", "PRE GROUP 2"], }) def test_discounted_tax(self): tax_21_exempted = self.env['account.tax'].create({ 'name': "tax_21_exempted", 'amount_type': 'group', 'amount': 2.0, 'tax_group_id': self.tax_group1.id, 'children_tax_ids': [ Command.create({ 'name': "tax_exempt", 'amount_type': 'percent', 'amount': -2.0, 'include_base_amount': True, 'tax_group_id': self.tax_group_sub1.id, 'sequence': 1, }), Command.create({ 'name': "tax_21", 'amount_type': 'percent', 'amount': 21.0, 'tax_group_id': self.tax_group_sub2.id, 'sequence': 2, }), Command.create({ 'name': "tax_reapply", 'amount_type': 'percent', 'amount': 2.0, 'is_base_affected': False, 'tax_group_id': self.tax_group_sub3.id, 'sequence': 3, }), ] }) self.tax_group_sub1.preceding_subtotal = "Tax exemption" self.tax_group_sub2.preceding_subtotal = "Tax application" self.tax_group_sub3.preceding_subtotal = "Reapply amount" document = self._create_document_for_tax_totals_test([ (1000 / 0.98, tax_21_exempted), ]) self.assertTaxTotals(document, { 'amount_total': 1230.41, 'amount_untaxed': 1020.41, 'display_tax_base': True, 'groups_by_subtotal': { "Reapply amount": [{ 'tax_group_name': self.tax_group_sub3.name, 'tax_group_amount': 20.41, 'tax_group_base_amount': 1020.41, 'tax_group_id': self.tax_group_sub3.id, }], "Tax application": [{ 'tax_group_name': self.tax_group_sub2.name, 'tax_group_amount': 210.0, 'tax_group_base_amount': 1000.0, 'tax_group_id': self.tax_group_sub2.id, }], "Tax exemption": [{ 'tax_group_name': self.tax_group_sub1.name, 'tax_group_amount': -20.41, 'tax_group_base_amount': 1020.41, 'tax_group_id': self.tax_group_sub1.id, }], }, 'subtotals': [{ 'name': "Tax exemption", 'amount': 1020.41, }, { 'name': "Tax application", 'amount': 1000.00, }, { 'name': "Reapply amount", 'amount': 1210.00, }], 'subtotals_order': ["Tax exemption", "Tax application", "Reapply amount"], }) def test_invoice_grouped_taxes_with_tax_group(self): """ A tax of type group with a tax_group_id being the same as one of the children tax shouldn't affect the result of the _prepare_tax_totals. """ tax_10_withheld = self.env['account.tax'].create({ 'name': "tax_10_withheld", 'amount_type': 'group', 'tax_group_id': self.tax_group1.id, 'children_tax_ids': [ Command.create({ 'name': "tax_withheld", 'amount_type': 'percent', 'amount': -47, 'tax_group_id': self.tax_group_sub1.id, 'sequence': 1, }), Command.create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10, 'tax_group_id': self.tax_group1.id, 'sequence': 2, }), ] }) self.tax_group_sub1.preceding_subtotal = "Tax withholding" document = self._create_document_for_tax_totals_test([ (100, tax_10_withheld), ]) self.assertTaxTotals(document, { 'amount_total': 63, 'amount_untaxed': 100, 'display_tax_base': True, 'groups_by_subtotal': { 'Untaxed Amount': [{ 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 10, 'tax_group_base_amount': 100, 'tax_group_id': self.tax_group1.id, }], "Tax withholding": [{ 'tax_group_name': self.tax_group_sub1.name, 'tax_group_amount': -47, 'tax_group_base_amount': 100, 'tax_group_id': self.tax_group_sub1.id, }], }, 'subtotals': [{ 'name': "Untaxed Amount", 'amount': 100, }, { 'name': "Tax withholding", 'amount': 110, }], 'subtotals_order': ["Untaxed Amount", "Tax withholding"], }) def test_taxtotals_with_different_tax_rounding_methods(self): def run_case(rounding_line, lines, expected_tax_group_amounts): self.env.company.tax_calculation_rounding_method = rounding_line document = self._create_document_for_tax_totals_test(lines) tax_amounts = document.tax_totals['groups_by_subtotal']['Untaxed Amount'] if len(expected_tax_group_amounts) != len(tax_amounts): self.fail("Wrong number of values to compare.") for tax_amount, expected in zip(tax_amounts, expected_tax_group_amounts): actual = tax_amount['tax_group_amount'] if document.currency_id.compare_amounts(actual, expected) != 0: self.fail(f'{document.currency_id.round(actual)} != {expected}') # one line, two taxes lines = [ (100.41, self.tax_16 + self.tax_53), ] run_case('round_per_line', lines, [69.29]) run_case('round_globally', lines, [69.29]) # two lines, different taxes lines = [ (50.4, self.tax_17a), (47.21, self.tax_17b), ] run_case('round_per_line', lines, [16.60]) run_case('round_globally', lines, [16.60]) # two lines, same tax lines = [ (50.4, self.tax_17a), (47.21, self.tax_17a), ] run_case('round_per_line', lines, [16.60]) run_case('round_globally', lines, [16.59]) def test_invoice_foreign_currency_tax_totals(self): self.env['res.currency.rate'].create({ 'name': '2018-01-01', 'rate': 0.2, 'currency_id': self.currency_data['currency'].id, 'company_id': self.env.company.id, }) tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'amount': 10.0, 'tax_group_id': self.tax_group1.id, }) tax_20 = self.env['account.tax'].create({ 'name': "tax_20", 'amount_type': 'percent', 'amount': 20.0, 'tax_group_id': self.tax_group2.id, }) invoice = self.env['account.move'].create({ 'move_type': 'out_invoice', 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'currency_id': self.currency_data['currency'].id, }) lines_data = [(100, tax_10), (300, tax_20)] invoice_lines_vals = [ Command.create({ 'name': 'line', 'display_type': 'product', 'account_id': self.company_data['default_account_revenue'].id, 'price_unit': amount, 'tax_ids': [Command.set(taxes.ids)], }) for amount, taxes in lines_data ] invoice['invoice_line_ids'] = invoice_lines_vals self.assertTaxTotals(invoice, { 'amount_total': 470, 'amount_untaxed': 400, 'display_tax_base': True, 'groups_by_subtotal': { 'Untaxed Amount': [ { 'tax_group_name': self.tax_group1.name, 'tax_group_amount': 10, 'tax_group_base_amount': 100, 'tax_group_id': self.tax_group1.id, 'tax_group_amount_company_currency': 50, 'tax_group_base_amount_company_currency': 500, }, { 'tax_group_name': self.tax_group2.name, 'tax_group_amount': 60, 'tax_group_base_amount': 300, 'tax_group_id': self.tax_group2.id, 'tax_group_amount_company_currency': 300, 'tax_group_base_amount_company_currency': 1500, } ] }, 'subtotals': [ { 'name': "Untaxed Amount", 'amount': 400, 'amount_company_currency': 2000, } ], 'subtotals_order': ["Untaxed Amount"], }) def test_cash_rounding_amount_total_rounded(self): tax_15 = self.env['account.tax'].create({ 'name': "tax_15", 'amount_type': 'percent', 'tax_group_id': self.tax_group1.id, 'amount': 15.0, }) tax_10 = self.env['account.tax'].create({ 'name': "tax_10", 'amount_type': 'percent', 'tax_group_id': self.tax_group2.id, 'amount': 10.0, }) cash_rounding_biggest_tax = self.env['account.cash.rounding'].create({ 'name': 'biggest tax Rounding HALF-UP', 'rounding': 1, 'strategy': 'biggest_tax', 'rounding_method': 'HALF-UP', }) cash_rounding_add_invoice_line = self.env['account.cash.rounding'].create({ 'name': 'add invoice line Rounding HALF-UP', 'rounding': 1, 'strategy': 'add_invoice_line', 'profit_account_id': self.company_data['default_account_revenue'].id, 'loss_account_id': self.company_data['default_account_expense'].id, 'rounding_method': 'HALF-UP', }) for move_type in ['out_invoice', 'in_invoice']: move = self.env['account.move'].create({ 'move_type': move_type, 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'invoice_line_ids': [ Command.create({ 'name': 'line', 'display_type': 'product', 'price_unit': 378, 'tax_ids': [Command.set(tax_15.ids)], }), Command.create({ 'name': 'line', 'display_type': 'product', 'price_unit': 100, 'tax_ids': [Command.set(tax_10.ids)], }) ], }) move.invoice_cash_rounding_id = cash_rounding_biggest_tax self.assertEqual(move.tax_totals['groups_by_subtotal']['Untaxed Amount'][0]['tax_group_amount'], 57) self.assertEqual(move.tax_totals['groups_by_subtotal']['Untaxed Amount'][1]['tax_group_amount'], 10) self.assertEqual(move.tax_totals['amount_total'], 545) move.invoice_cash_rounding_id = cash_rounding_add_invoice_line self.assertEqual(move.tax_totals['groups_by_subtotal']['Untaxed Amount'][0]['tax_group_amount'], 56.7) self.assertEqual(move.tax_totals['groups_by_subtotal']['Untaxed Amount'][1]['tax_group_amount'], 10) self.assertEqual(move.tax_totals['rounding_amount'], 0.3) self.assertEqual(move.tax_totals['amount_total'], 545) def test_recompute_cash_rounding_lines(self): # if rounding_method is changed then rounding shouldn't be recomputed in posted invoices cash_rounding_add_invoice_line = self.env['account.cash.rounding'].create({ 'name': 'Add invoice line Rounding UP', 'rounding': 1, 'strategy': 'add_invoice_line', 'profit_account_id': self.company_data['default_account_revenue'].id, 'loss_account_id': self.company_data['default_account_expense'].id, 'rounding_method': 'UP', }) moves_rounding = {} moves = self.env['account.move'] for move_type in ['out_invoice', 'in_invoice']: move = self.env['account.move'].create({ 'move_type': move_type, 'partner_id': self.partner_a.id, 'invoice_date': '2019-01-01', 'invoice_cash_rounding_id': cash_rounding_add_invoice_line.id, 'invoice_line_ids': [ Command.create({ 'name': 'line', 'display_type': 'product', 'price_unit': 99.5, }) ], }) moves_rounding[move] = sum(move.line_ids.filtered(lambda line: line.display_type == 'rounding').mapped('balance')) moves += move moves.action_post() cash_rounding_add_invoice_line.rounding_method = 'DOWN' # check if rounding is recomputed moves.to_check = True for move in moves_rounding: self.assertEqual(sum(move.line_ids.filtered(lambda line: line.display_type == 'rounding').mapped('balance')), moves_rounding[move]) def test_cash_rounding_amount_total_rounded_foreign_currency(self): tax_15 = self.env['account.tax'].create({ 'name': "tax_15", 'amount_type': 'percent', 'amount': 15.0, }) cash_rounding = self.env['account.cash.rounding'].create({ 'name': 'Rounding HALF-UP', 'rounding': 10, 'strategy': 'biggest_tax', 'rounding_method': 'HALF-UP', }) self.env['res.currency.rate'].create({ 'name': '2023-01-01', 'rate': 0.2, 'currency_id': self.currency_data['currency'].id, 'company_id': self.env.company.id, }) for move_type in ['out_invoice', 'in_invoice']: move = self.env['account.move'].create({ 'move_type': move_type, 'partner_id': self.partner_a.id, 'invoice_date': '2023-01-01', 'currency_id': self.currency_data['currency'].id, 'invoice_line_ids': [ Command.create({ 'name': 'line', 'display_type': 'product', 'price_unit': 100, 'tax_ids': [tax_15.id], }) ] }) move.invoice_cash_rounding_id = cash_rounding self.assertEqual(move.tax_totals['amount_total'], 120)