diff options
Diffstat (limited to 'addons/account/tests/test_tax.py')
| -rw-r--r-- | addons/account/tests/test_tax.py | 1075 |
1 files changed, 1075 insertions, 0 deletions
diff --git a/addons/account/tests/test_tax.py b/addons/account/tests/test_tax.py new file mode 100644 index 00000000..068031ce --- /dev/null +++ b/addons/account/tests/test_tax.py @@ -0,0 +1,1075 @@ +# -*- coding: utf-8 -*- +from odoo.addons.account.tests.common import AccountTestInvoicingCommon +from odoo.tests import tagged + + +@tagged('post_install', '-at_install') +class TestTaxCommon(AccountTestInvoicingCommon): + + @classmethod + def setUpClass(cls, chart_template_ref=None): + super().setUpClass(chart_template_ref=chart_template_ref) + + # Setup another company having a rounding of 1.0. + cls.currency_data['currency'].rounding = 1.0 + cls.currency_no_decimal = cls.currency_data['currency'] + cls.company_data_2 = cls.setup_company_data('company_2', currency_id=cls.currency_no_decimal.id) + cls.env.user.company_id = cls.company_data['company'] + + cls.fixed_tax = cls.env['account.tax'].create({ + 'name': "Fixed tax", + 'amount_type': 'fixed', + 'amount': 10, + 'sequence': 1, + }) + cls.fixed_tax_bis = cls.env['account.tax'].create({ + 'name': "Fixed tax bis", + 'amount_type': 'fixed', + 'amount': 15, + 'sequence': 2, + }) + cls.percent_tax = cls.env['account.tax'].create({ + 'name': "Percent tax", + 'amount_type': 'percent', + 'amount': 10, + 'sequence': 3, + }) + cls.percent_tax_bis = cls.env['account.tax'].create({ + 'name': "Percent tax bis", + 'amount_type': 'percent', + 'amount': 10, + 'sequence': 4, + }) + cls.division_tax = cls.env['account.tax'].create({ + 'name': "Division tax", + 'amount_type': 'division', + 'amount': 10, + 'sequence': 4, + }) + cls.group_tax = cls.env['account.tax'].create({ + 'name': "Group tax", + 'amount_type': 'group', + 'amount': 0, + 'sequence': 5, + 'children_tax_ids': [ + (4, cls.fixed_tax.id, 0), + (4, cls.percent_tax.id, 0) + ] + }) + cls.group_tax_bis = cls.env['account.tax'].create({ + 'name': "Group tax bis", + 'amount_type': 'group', + 'amount': 0, + 'sequence': 6, + 'children_tax_ids': [ + (4, cls.fixed_tax.id, 0), + (4, cls.percent_tax.id, 0) + ] + }) + cls.group_tax_percent = cls.env['account.tax'].create({ + 'name': "Group tax percent", + 'amount_type': 'group', + 'amount': 0, + 'sequence': 6, + 'children_tax_ids': [ + (4, cls.percent_tax.id, 0), + (4, cls.percent_tax_bis.id, 0) + ] + }) + cls.group_of_group_tax = cls.env['account.tax'].create({ + 'name': "Group of group tax", + 'amount_type': 'group', + 'amount': 0, + 'sequence': 7, + 'children_tax_ids': [ + (4, cls.group_tax.id, 0), + (4, cls.group_tax_bis.id, 0) + ] + }) + cls.tax_with_no_account = cls.env['account.tax'].create({ + 'name': "Tax with no account", + 'amount_type': 'fixed', + 'amount': 0, + 'sequence': 8, + }) + some_account = cls.env['account.account'].search([], limit=1) + cls.tax_with_account = cls.env['account.tax'].create({ + 'name': "Tax with account", + 'amount_type': 'fixed', + 'amount': 0, + 'sequence': 8, + 'invoice_repartition_line_ids': [ + (0,0, { + 'factor_percent': 100, + 'repartition_type': 'base', + }), + + (0,0, { + 'factor_percent': 100, + 'repartition_type': 'tax', + 'account_id': some_account.id, + }), + ], + 'refund_repartition_line_ids': [ + (0,0, { + 'factor_percent': 100, + 'repartition_type': 'base', + }), + + (0,0, { + 'factor_percent': 100, + 'repartition_type': 'tax', + 'account_id': some_account.id, + }), + ], + }) + + cls.tax_0_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({ + 'name': "test_0_percent", + 'amount_type': 'percent', + 'amount': 0, + }) + + cls.tax_5_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({ + 'name': "test_5_percent", + 'amount_type': 'percent', + 'amount': 5, + }) + + cls.tax_8_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({ + 'name': "test_8_percent", + 'amount_type': 'percent', + 'amount': 8, + }) + cls.tax_12_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({ + 'name': "test_12_percent", + 'amount_type': 'percent', + 'amount': 12, + }) + + cls.tax_19_percent = cls.env['account.tax'].with_company(cls.company_data_2['company']).create({ + 'name': "test_19_percent", + 'amount_type': 'percent', + 'amount': 19, + }) + + cls.tax_21_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({ + 'name': "test_21_percent", + 'amount_type': 'percent', + 'amount': 19, + }) + + cls.tax_21_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({ + 'name': "test_rounding_methods_2", + 'amount_type': 'percent', + 'amount': 21, + }) + + cls.bank_journal = cls.company_data['default_journal_bank'] + cls.bank_account = cls.bank_journal.default_account_id + cls.expense_account = cls.company_data['default_account_expense'] + + def _check_compute_all_results(self, total_included, total_excluded, taxes, res): + self.assertAlmostEqual(res['total_included'], total_included) + self.assertAlmostEqual(res['total_excluded'], total_excluded) + for i in range(0, len(taxes)): + self.assertAlmostEqual(res['taxes'][i]['base'], taxes[i][0]) + self.assertAlmostEqual(res['taxes'][i]['amount'], taxes[i][1]) + + +@tagged('post_install', '-at_install') +class TestTax(TestTaxCommon): + + @classmethod + def setUpClass(cls): + super(TestTax, cls).setUpClass() + + def test_tax_group_of_group_tax(self): + self.fixed_tax.include_base_amount = True + res = self.group_of_group_tax.compute_all(200.0) + self._check_compute_all_results( + 263, # 'total_included' + 200, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (200.0, 10.0), # | 1 | 10 | | t + (210.0, 21.0), # | 3 | 10% | | + (210.0, 10.0), # | 1 | 10 | | t + (220.0, 22.0), # | 3 | 10% | | + # --------------------------------------------------- + ], + res + ) + + def test_tax_group(self): + res = self.group_tax.compute_all(200.0) + self._check_compute_all_results( + 230, # 'total_included' + 200, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (200.0, 10.0), # | 1 | 10 | | + (200.0, 20.0), # | 3 | 10% | | + # --------------------------------------------------- + ], + res + ) + + def test_tax_group_percent(self): + res = self.group_tax_percent.with_context({'force_price_include':True}).compute_all(100.0) + self._check_compute_all_results( + 100, # 'total_included' + 83.33, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (83.33, 8.33), # | 1 | 10% | | + (83.33, 8.34), # | 2 | 10% | | + # --------------------------------------------------- + ], + res + ) + + def test_tax_percent_division(self): + self.division_tax.price_include = True + self.division_tax.include_base_amount = True + res_division = self.division_tax.compute_all(200.0) + self._check_compute_all_results( + 200, # 'total_included' + 180, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (180.0, 20.0), # | 4 | 10/ | t | t + # --------------------------------------------------- + ], + res_division + ) + self.percent_tax.price_include = False + self.percent_tax.include_base_amount = False + res_percent = self.percent_tax.compute_all(100.0) + self._check_compute_all_results( + 110, # 'total_included' + 100, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (100.0, 10.0), # | 3 | 10% | | + # --------------------------------------------------- + ], + res_percent + ) + self.division_tax.price_include = False + self.division_tax.include_base_amount = False + res_division = self.division_tax.compute_all(180.0) + self._check_compute_all_results( + 200, # 'total_included' + 180, # 'total_excluded' + [ + # base, amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (180.0, 20.0), # | 4 | 10/ | | + # --------------------------------------------------- + ], + res_division + ) + self.percent_tax.price_include = True + self.percent_tax.include_base_amount = True + res_percent = self.percent_tax.compute_all(110.0) + self._check_compute_all_results( + 110, # 'total_included' + 100, # 'total_excluded' + [ + # base, amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (100.0, 10.0), # | 3 | 10% | t | t + # --------------------------------------------------- + ], + res_percent + ) + self.percent_tax_bis.price_include = True + self.percent_tax_bis.include_base_amount = True + self.percent_tax_bis.amount = 21 + res_percent = self.percent_tax_bis.compute_all(7.0) + self._check_compute_all_results( + 7.0, # 'total_included' + 5.79, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (5.79, 1.21), # | 3 | 21% | t | t + # --------------------------------------------------- + ], + res_percent + ) + + def test_tax_sequence_normalized_set(self): + self.division_tax.sequence = 1 + self.fixed_tax.sequence = 2 + self.percent_tax.sequence = 3 + taxes_set = (self.group_tax | self.division_tax) + res = taxes_set.compute_all(200.0) + self._check_compute_all_results( + 252.22, # 'total_included' + 200, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (200.0, 22.22), # | 1 | 10/ | | + (200.0, 10.0), # | 2 | 10 | | + (200.0, 20.0), # | 3 | 10% | | + # --------------------------------------------------- + ], + res + ) + + def test_fixed_tax_include_base_amount(self): + self.fixed_tax.include_base_amount = True + res = self.group_tax.compute_all(200.0) + self._check_compute_all_results( + 231, # 'total_included' + 200, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (200.0, 10.0), # | 1 | 10 | | t + (210.0, 21.0), # | 3 | 10% | | + # --------------------------------------------------- + ], + res + ) + + self.fixed_tax.price_include = True + self.fixed_tax.include_base_amount = False + res = self.fixed_tax.compute_all(100.0, quantity=2.0) + self._check_compute_all_results( + 200, # 'total_included' + 180, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (180.0, 20.0), # | 1 | 20 | | t + # --------------------------------------------------- + ], + res + ) + + def test_percent_tax_include_base_amount(self): + self.percent_tax.price_include = True + self.percent_tax.amount = 21.0 + res = self.percent_tax.compute_all(7.0) + self._check_compute_all_results( + 7.0, # 'total_included' + 5.79, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (5.79, 1.21), # | 3 | 21% | t | + # --------------------------------------------------- + ], + res + ) + + self.percent_tax.price_include = True + self.percent_tax.amount = 20.0 + res = self.percent_tax.compute_all(399.99) + self._check_compute_all_results( + 399.99, # 'total_included' + 333.33, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (333.33, 66.66), # | 3 | 20% | t | + # --------------------------------------------------- + ], + res + ) + + def test_tax_decimals(self): + """Test the rounding of taxes up to 6 decimals (maximum decimals places allowed for currencies)""" + self.env.user.company_id.currency_id.rounding = 0.000001 + + self.percent_tax.price_include = True + self.percent_tax.amount = 21.0 + res = self.percent_tax.compute_all(7.0) + self._check_compute_all_results( + 7.0, # 'total_included' + 5.785124, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # -------------------------------------------------------- + (5.785124, 1.214876), # | 3 | 21% | t | + # -------------------------------------------------------- + ], + res + ) + + self.percent_tax.price_include = True + self.percent_tax.amount = 20.0 + res = self.percent_tax.compute_all(399.999999) + self._check_compute_all_results( + 399.999999, # 'total_included' + 333.333333, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # ----------------------------------------------------------- + (333.333333, 66.666666), # | 3 | 20% | t | + # ----------------------------------------------------------- + ], + res + ) + + def test_advanced_taxes_computation_0(self): + '''Test more advanced taxes computation (see issue 34471).''' + tax_1 = self.env['account.tax'].create({ + 'name': 'test_advanced_taxes_computation_0_1', + 'amount_type': 'percent', + 'amount': 10, + 'price_include': True, + 'include_base_amount': True, + 'sequence': 1, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + }) + tax_2 = self.env['account.tax'].create({ + 'name': 'test_advanced_taxes_computation_0_2', + 'amount_type': 'percent', + 'amount': 10, + 'sequence': 2, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + }) + tax_3 = self.env['account.tax'].create({ + 'name': 'test_advanced_taxes_computation_0_3', + 'amount_type': 'percent', + 'amount': 10, + 'price_include': True, + 'sequence': 3, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + }) + tax_4 = self.env['account.tax'].create({ + 'name': 'test_advanced_taxes_computation_0_4', + 'amount_type': 'percent', + 'amount': 10, + 'sequence': 4, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + }) + tax_5 = self.env['account.tax'].create({ + 'name': 'test_advanced_taxes_computation_0_5', + 'amount_type': 'percent', + 'amount': 10, + 'price_include': True, + 'sequence': 5, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + }) + taxes = tax_1 + tax_2 + tax_3 + tax_4 + tax_5 + + # Test with positive amount. + self._check_compute_all_results( + 154, # 'total_included' + 100, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (100.0, 5.0), # | 1 | 10% | t | t + (100.0, 5.0), # | 1 | 10% | t | t + (110.0, 5.5), # | 2 | 10% | | + (110.0, 5.5), # | 2 | 10% | | + (110.0, 5.5), # | 3 | 10% | t | + (110.0, 5.5), # | 3 | 10% | t | + (110.0, 5.5), # | 4 | 10% | | + (110.0, 5.5), # | 4 | 10% | | + (110.0, 5.5), # | 5 | 10% | t | + (110.0, 5.5), # | 5 | 10% | t | + # --------------------------------------------------- + ], + taxes.compute_all(132.0) + ) + + # Test with negative amount. + self._check_compute_all_results( + -154, # 'total_included' + -100, # 'total_excluded' + [ + # base , amount | seq | amount | incl | incl_base + # --------------------------------------------------- + (-100.0, -5.0), # | 1 | 10% | t | t + (-100.0, -5.0), # | 1 | 10% | t | t + (-110.0, -5.5), # | 2 | 10% | | + (-110.0, -5.5), # | 2 | 10% | | + (-110.0, -5.5), # | 3 | 10% | t | + (-110.0, -5.5), # | 3 | 10% | t | + (-110.0, -5.5), # | 4 | 10% | | + (-110.0, -5.5), # | 4 | 10% | | + (-110.0, -5.5), # | 5 | 10% | t | + (-110.0, -5.5), # | 5 | 10% | t | + # --------------------------------------------------- + ], + taxes.compute_all(-132.0) + ) + + def test_intracomm_taxes_computation_0(self): + ''' Test usage of intracomm taxes having e.g.+100%, -100% as repartition lines. ''' + intracomm_tax = self.env['account.tax'].create({ + 'name': 'test_intracomm_taxes_computation_0_1', + 'amount_type': 'percent', + 'amount': 21, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -100.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -100.0}), + ], + }) + + # Test with positive amount. + self._check_compute_all_results( + 100, # 'total_included' + 100, # 'total_excluded' + [ + # base , amount + # --------------- + (100.0, 21.0), + (100.0, -21.0), + # --------------- + ], + intracomm_tax.compute_all(100.0) + ) + + # Test with negative amount. + self._check_compute_all_results( + -100, # 'total_included' + -100, # 'total_excluded' + [ + # base , amount + # --------------- + (-100.0, -21.0), + (-100.0, 21.0), + # --------------- + ], + intracomm_tax.compute_all(-100.0) + ) + + def test_rounding_issues_0(self): + ''' Test taxes having a complex setup of repartition lines. ''' + tax = self.env['account.tax'].create({ + 'name': 'test_rounding_issues_0', + 'amount_type': 'percent', + 'amount': 3, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + ], + }) + + # Test with positive amount. + self._check_compute_all_results( + 1.09, # 'total_included' + 1, # 'total_excluded' + [ + # base , amount + # --------------- + (1.0, 0.01), + (1.0, 0.01), + (1.0, 0.01), + (1.0, 0.02), + (1.0, 0.02), + (1.0, 0.02), + # --------------- + ], + tax.compute_all(1.0) + ) + + # Test with negative amount. + self._check_compute_all_results( + -1.09, # 'total_included' + -1, # 'total_excluded' + [ + # base , amount + # --------------- + (-1.0, -0.01), + (-1.0, -0.01), + (-1.0, -0.01), + (-1.0, -0.02), + (-1.0, -0.02), + (-1.0, -0.02), + # --------------- + ], + tax.compute_all(-1.0) + ) + + def test_rounding_issues_1(self): + ''' Test taxes having a complex setup of repartition lines. ''' + tax = self.env['account.tax'].create({ + 'name': 'test_advanced_taxes_repartition_lines_computation_1', + 'amount_type': 'percent', + 'amount': 3, + 'invoice_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}), + ], + 'refund_repartition_line_ids': [ + (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -50.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}), + (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}), + ], + }) + + # Test with positive amount. + self._check_compute_all_results( + 1, # 'total_included' + 1, # 'total_excluded' + [ + # base , amount + # --------------- + (1.0, 0.02), + (1.0, -0.02), + (1.0, 0.01), + (1.0, 0.01), + (1.0, -0.01), + (1.0, -0.01), + # --------------- + ], + tax.compute_all(1.0) + ) + + # Test with negative amount. + self._check_compute_all_results( + -1, # 'total_included' + -1, # 'total_excluded' + [ + # base , amount + # --------------- + (-1.0, -0.02), + (-1.0, 0.02), + (-1.0, -0.01), + (-1.0, -0.01), + (-1.0, 0.01), + (-1.0, 0.01), + # --------------- + ], + tax.compute_all(-1.0) + ) + + def test_rounding_tax_excluded_round_per_line_01(self): + ''' Test the rounding of a 19% price excluded tax in an invoice having 22689 and 9176 as lines. + The decimal precision is set to zero. + The computation must be similar to round(22689 * 0.19) + round(9176 * 0.19). + ''' + self.tax_19_percent.company_id.currency_id.rounding = 1.0 + self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_per_line' + + res1 = self.tax_19_percent.compute_all(22689) + self._check_compute_all_results( + 27000, # 'total_included' + 22689, # 'total_excluded' + [ + # base, amount + # --------------- + (22689, 4311), + # --------------- + ], + res1 + ) + + res2 = self.tax_19_percent.compute_all(9176) + self._check_compute_all_results( + 10919, # 'total_included' + 9176, # 'total_excluded' + [ + # base , amount + # --------------- + (9176, 1743), + # --------------- + ], + res2 + ) + + def test_rounding_tax_excluded_round_globally(self): + ''' Test the rounding of a 19% price excluded tax in an invoice having 22689 and 9176 as lines. + The decimal precision is set to zero. + The computation must be similar to round((22689 + 9176) * 0.19). + ''' + self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_globally' + + res1 = self.tax_19_percent.compute_all(22689) + self._check_compute_all_results( + 27000, # 'total_included' + 22689, # 'total_excluded' + [ + # base, amount + # --------------- + (22689, 4310.91), + # --------------- + ], + res1 + ) + + res2 = self.tax_19_percent.compute_all(9176) + self._check_compute_all_results( + 10919, # 'total_included' + 9176, # 'total_excluded' + [ + # base , amount + # --------------- + (9176, 1743.44), + # --------------- + ], + res2 + ) + + def test_rounding_tax_included_round_per_line_01(self): + ''' Test the rounding of a 19% price included tax in an invoice having 27000 and 10920 as lines. + The decimal precision is set to zero. + The computation must be similar to round(27000 / 1.19) + round(10920 / 1.19). + ''' + self.tax_19_percent.price_include = True + self.tax_19_percent.company_id.currency_id.rounding = 1.0 + self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_per_line' + + res1 = self.tax_19_percent.compute_all(27000) + self._check_compute_all_results( + 27000, # 'total_included' + 22689, # 'total_excluded' + [ + # base , amount + # --------------- + (22689, 4311), + # --------------- + ], + res1 + ) + + res2 = self.tax_19_percent.compute_all(10920) + self._check_compute_all_results( + 10920, # 'total_included' + 9176, # 'total_excluded' + [ + # base , amount + # --------------- + (9176, 1744), + # --------------- + ], + res2 + ) + + def test_rounding_tax_included_round_per_line_02(self): + ''' Test the rounding of a 12% price included tax in an invoice having 52.50 as line. + The decimal precision is set to 2. + ''' + self.tax_12_percent.price_include = True + self.tax_12_percent.company_id.currency_id.rounding = 0.01 + + res1 = self.tax_12_percent.compute_all(52.50) + self._check_compute_all_results( + 52.50, # 'total_included' + 46.88, # 'total_excluded' + [ + # base , amount + # ------------- + (46.88, 5.62), + # ------------- + ], + res1 + ) + + def test_rounding_tax_included_round_per_line_03(self): + ''' Test the rounding of a 8% and 0% price included tax in an invoice having 8 * 15.55 as line. + The decimal precision is set to 2. + ''' + self.tax_0_percent.company_id.currency_id.rounding = 0.01 + self.tax_0_percent.price_include = True + self.tax_8_percent.price_include = True + + self.group_tax.children_tax_ids = [(6, 0, self.tax_0_percent.ids)] + self.group_tax_bis.children_tax_ids = [(6, 0, self.tax_8_percent.ids)] + + res1 = (self.tax_8_percent | self.tax_0_percent).compute_all(15.55, quantity=8.0) + self._check_compute_all_results( + 124.40, # 'total_included' + 115.19, # 'total_excluded' + [ + # base , amount + # ------------- + (115.19, 9.21), + (115.19, 0.00), + # ------------- + ], + res1 + ) + + res2 = (self.tax_0_percent | self.tax_8_percent).compute_all(15.55, quantity=8.0) + self._check_compute_all_results( + 124.40, # 'total_included' + 115.19, # 'total_excluded' + [ + # base , amount + # ------------- + (115.19, 0.00), + (115.19, 9.21), + # ------------- + ], + res2 + ) + + def test_rounding_tax_included_round_per_line_04(self): + ''' Test the rounding of a 5% price included tax. + The decimal precision is set to 0.05. + ''' + self.tax_5_percent.price_include = True + self.tax_5_percent.company_id.currency_id.rounding = 0.05 + self.tax_5_percent.company_id.tax_calculation_rounding_method = 'round_per_line' + + res1 = self.tax_5_percent.compute_all(5) + self._check_compute_all_results( + 5, # 'total_included' + 4.75, # 'total_excluded' + [ + # base , amount + # --------------- + (4.75, 0.25), + # --------------- + ], + res1 + ) + + res2 = self.tax_5_percent.compute_all(10) + self._check_compute_all_results( + 10, # 'total_included' + 9.5, # 'total_excluded' + [ + # base , amount + # --------------- + (9.5, 0.5), + # --------------- + ], + res2 + ) + + res3 = self.tax_5_percent.compute_all(50) + self._check_compute_all_results( + 50, # 'total_included' + 47.6, # 'total_excluded' + [ + # base , amount + # --------------- + (47.6, 2.4), + # --------------- + ], + res3 + ) + + def test_rounding_tax_included_round_globally_01(self): + ''' Test the rounding of a 19% price included tax in an invoice having 27000 and 10920 as lines. + The decimal precision is set to zero. + The computation must be similar to round((27000 + 10920) / 1.19). + ''' + self.tax_19_percent.price_include = True + self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_globally' + + res1 = self.tax_19_percent.compute_all(27000) + self._check_compute_all_results( + 27000, # 'total_included' + 22689, # 'total_excluded' + [ + # base , amount + # --------------- + (22689, 4311), + # --------------- + ], + res1 + ) + + res2 = self.tax_19_percent.compute_all(10920) + self._check_compute_all_results( + 10920, # 'total_included' + 9176, # 'total_excluded' + [ + # base , amount + # --------------- + (9176, 1744), + # --------------- + ], + res2 + ) + + def test_rounding_tax_included_round_globally_02(self): + ''' Test the rounding of a 21% price included tax in an invoice having 11.90 and 2.80 as lines. + The decimal precision is set to 2. + ''' + self.tax_21_percent.price_include = True + self.tax_21_percent.company_id.currency_id.rounding = 0.01 + self.tax_21_percent.company_id.tax_calculation_rounding_method = 'round_globally' + + res1 = self.tax_21_percent.compute_all(11.90) + self._check_compute_all_results( + 11.90, # 'total_included' + 9.83, # 'total_excluded' + [ + # base , amount + # --------------- + (9.83, 2.07), + # --------------- + ], + res1 + ) + + res2 = self.tax_21_percent.compute_all(2.80) + self._check_compute_all_results( + 2.80, # 'total_included' + 2.31, # 'total_excluded' + [ + # base , amount + # --------------- + (2.31, 0.49), + # --------------- + ], + res2 + ) + + def test_rounding_tax_included_round_globally_03(self): + ''' Test the rounding of a 5% price included tax. + The decimal precision is set to 0.05. + ''' + self.tax_5_percent.price_include = True + self.tax_5_percent.company_id.currency_id.rounding = 0.05 + self.tax_5_percent.company_id.tax_calculation_rounding_method = 'round_globally' + + res1 = self.tax_5_percent.compute_all(5) + self._check_compute_all_results( + 5, # 'total_included' + 4.75, # 'total_excluded' + [ + # base , amount + # --------------- + (4.75, 0.25), + # --------------- + ], + res1 + ) + + res2 = self.tax_5_percent.compute_all(10) + self._check_compute_all_results( + 10, # 'total_included' + 9.5, # 'total_excluded' + [ + # base , amount + # --------------- + (9.50, 0.50), + # --------------- + ], + res2 + ) + + res3 = self.tax_5_percent.compute_all(50) + self._check_compute_all_results( + 50, # 'total_included' + 47.6, # 'total_excluded' + [ + # base , amount + # --------------- + (47.60, 2.40), + # --------------- + ], + res3 + ) + + def test_mixing_price_included_excluded_with_affect_base(self): + tax_10_fix = self.env['account.tax'].create({ + 'name': "tax_10_fix", + 'amount_type': 'fixed', + 'amount': 10.0, + 'include_base_amount': True, + }) + tax_21 = self.env['account.tax'].create({ + 'name': "tax_21", + 'amount_type': 'percent', + 'amount': 21.0, + 'price_include': True, + 'include_base_amount': True, + }) + + self._check_compute_all_results( + 1222.1, # 'total_included' + 1000.0, # 'total_excluded' + [ + # base , amount + # --------------- + (1000.0, 10.0), + (1010.0, 212.1), + # --------------- + ], + (tax_10_fix + tax_21).compute_all(1210), + ) |
