1# -*- coding: utf-8 -*-
2from odoo.addons.account.tests.common import AccountTestInvoicingCommon
3from odoo.tests import tagged
4
5
6@tagged('post_install', '-at_install')
7class TestTaxCommon(AccountTestInvoicingCommon):
8
9    @classmethod
10    def setUpClass(cls, chart_template_ref=None):
11        super().setUpClass(chart_template_ref=chart_template_ref)
12
13        # Setup another company having a rounding of 1.0.
14        cls.currency_data['currency'].rounding = 1.0
15        cls.currency_no_decimal = cls.currency_data['currency']
16        cls.company_data_2 = cls.setup_company_data('company_2', currency_id=cls.currency_no_decimal.id)
17        cls.env.user.company_id = cls.company_data['company']
18
19        cls.fixed_tax = cls.env['account.tax'].create({
20            'name': "Fixed tax",
21            'amount_type': 'fixed',
22            'amount': 10,
23            'sequence': 1,
24        })
25        cls.fixed_tax_bis = cls.env['account.tax'].create({
26            'name': "Fixed tax bis",
27            'amount_type': 'fixed',
28            'amount': 15,
29            'sequence': 2,
30        })
31        cls.percent_tax = cls.env['account.tax'].create({
32            'name': "Percent tax",
33            'amount_type': 'percent',
34            'amount': 10,
35            'sequence': 3,
36        })
37        cls.percent_tax_bis = cls.env['account.tax'].create({
38            'name': "Percent tax bis",
39            'amount_type': 'percent',
40            'amount': 10,
41            'sequence': 4,
42        })
43        cls.division_tax = cls.env['account.tax'].create({
44            'name': "Division tax",
45            'amount_type': 'division',
46            'amount': 10,
47            'sequence': 4,
48        })
49        cls.group_tax = cls.env['account.tax'].create({
50            'name': "Group tax",
51            'amount_type': 'group',
52            'amount': 0,
53            'sequence': 5,
54            'children_tax_ids': [
55                (4, cls.fixed_tax.id, 0),
56                (4, cls.percent_tax.id, 0)
57            ]
58        })
59        cls.group_tax_bis = cls.env['account.tax'].create({
60            'name': "Group tax bis",
61            'amount_type': 'group',
62            'amount': 0,
63            'sequence': 6,
64            'children_tax_ids': [
65                (4, cls.fixed_tax.id, 0),
66                (4, cls.percent_tax.id, 0)
67            ]
68        })
69        cls.group_tax_percent = cls.env['account.tax'].create({
70            'name': "Group tax percent",
71            'amount_type': 'group',
72            'amount': 0,
73            'sequence': 6,
74            'children_tax_ids': [
75                (4, cls.percent_tax.id, 0),
76                (4, cls.percent_tax_bis.id, 0)
77            ]
78        })
79        cls.group_of_group_tax = cls.env['account.tax'].create({
80            'name': "Group of group tax",
81            'amount_type': 'group',
82            'amount': 0,
83            'sequence': 7,
84            'children_tax_ids': [
85                (4, cls.group_tax.id, 0),
86                (4, cls.group_tax_bis.id, 0)
87            ]
88        })
89        cls.tax_with_no_account = cls.env['account.tax'].create({
90            'name': "Tax with no account",
91            'amount_type': 'fixed',
92            'amount': 0,
93            'sequence': 8,
94        })
95        some_account = cls.env['account.account'].search([], limit=1)
96        cls.tax_with_account = cls.env['account.tax'].create({
97            'name': "Tax with account",
98            'amount_type': 'fixed',
99            'amount': 0,
100            'sequence': 8,
101            'invoice_repartition_line_ids': [
102                (0,0, {
103                    'factor_percent': 100,
104                    'repartition_type': 'base',
105                }),
106
107                (0,0, {
108                    'factor_percent': 100,
109                    'repartition_type': 'tax',
110                    'account_id': some_account.id,
111                }),
112            ],
113            'refund_repartition_line_ids': [
114                (0,0, {
115                    'factor_percent': 100,
116                    'repartition_type': 'base',
117                }),
118
119                (0,0, {
120                    'factor_percent': 100,
121                    'repartition_type': 'tax',
122                    'account_id': some_account.id,
123                }),
124            ],
125        })
126
127        cls.tax_0_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
128            'name': "test_0_percent",
129            'amount_type': 'percent',
130            'amount': 0,
131        })
132
133        cls.tax_5_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
134            'name': "test_5_percent",
135            'amount_type': 'percent',
136            'amount': 5,
137        })
138
139        cls.tax_8_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
140            'name': "test_8_percent",
141            'amount_type': 'percent',
142            'amount': 8,
143        })
144        cls.tax_12_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
145            'name': "test_12_percent",
146            'amount_type': 'percent',
147            'amount': 12,
148        })
149
150        cls.tax_19_percent = cls.env['account.tax'].with_company(cls.company_data_2['company']).create({
151            'name': "test_19_percent",
152            'amount_type': 'percent',
153            'amount': 19,
154        })
155
156        cls.tax_21_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
157            'name': "test_21_percent",
158            'amount_type': 'percent',
159            'amount': 19,
160        })
161
162        cls.tax_21_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
163            'name': "test_rounding_methods_2",
164            'amount_type': 'percent',
165            'amount': 21,
166        })
167
168        cls.bank_journal = cls.company_data['default_journal_bank']
169        cls.bank_account = cls.bank_journal.default_account_id
170        cls.expense_account = cls.company_data['default_account_expense']
171
172    def _check_compute_all_results(self, total_included, total_excluded, taxes, res):
173        self.assertAlmostEqual(res['total_included'], total_included)
174        self.assertAlmostEqual(res['total_excluded'], total_excluded)
175        for i in range(0, len(taxes)):
176            self.assertAlmostEqual(res['taxes'][i]['base'], taxes[i][0])
177            self.assertAlmostEqual(res['taxes'][i]['amount'], taxes[i][1])
178
179
180@tagged('post_install', '-at_install')
181class TestTax(TestTaxCommon):
182
183    @classmethod
184    def setUpClass(cls):
185        super(TestTax, cls).setUpClass()
186
187    def test_tax_group_of_group_tax(self):
188        self.fixed_tax.include_base_amount = True
189        res = self.group_of_group_tax.compute_all(200.0)
190        self._check_compute_all_results(
191            263,    # 'total_included'
192            200,    # 'total_excluded'
193            [
194                # base , amount     | seq | amount | incl | incl_base
195                # ---------------------------------------------------
196                (200.0, 10.0),    # |  1  |    10  |      |     t
197                (210.0, 21.0),    # |  3  |    10% |      |
198                (210.0, 10.0),    # |  1  |    10  |      |     t
199                (220.0, 22.0),    # |  3  |    10% |      |
200                # ---------------------------------------------------
201            ],
202            res
203        )
204
205    def test_tax_group(self):
206        res = self.group_tax.compute_all(200.0)
207        self._check_compute_all_results(
208            230,    # 'total_included'
209            200,    # 'total_excluded'
210            [
211                # base , amount     | seq | amount | incl | incl_base
212                # ---------------------------------------------------
213                (200.0, 10.0),    # |  1  |    10  |      |
214                (200.0, 20.0),    # |  3  |    10% |      |
215                # ---------------------------------------------------
216            ],
217            res
218        )
219
220    def test_tax_group_percent(self):
221        res = self.group_tax_percent.with_context({'force_price_include':True}).compute_all(100.0)
222        self._check_compute_all_results(
223            100,    # 'total_included'
224            83.33,    # 'total_excluded'
225            [
226                # base , amount     | seq | amount | incl | incl_base
227                # ---------------------------------------------------
228                (83.33, 8.33),    # |  1  |    10% |      |
229                (83.33, 8.34),    # |  2  |    10% |      |
230                # ---------------------------------------------------
231            ],
232            res
233        )
234
235    def test_tax_percent_division(self):
236        self.division_tax.price_include = True
237        self.division_tax.include_base_amount = True
238        res_division = self.division_tax.compute_all(200.0)
239        self._check_compute_all_results(
240            200,    # 'total_included'
241            180,    # 'total_excluded'
242            [
243                # base , amount     | seq | amount | incl | incl_base
244                # ---------------------------------------------------
245                (180.0, 20.0),    # |  4  |    10/ |   t  |     t
246                # ---------------------------------------------------
247            ],
248            res_division
249        )
250        self.percent_tax.price_include = False
251        self.percent_tax.include_base_amount = False
252        res_percent = self.percent_tax.compute_all(100.0)
253        self._check_compute_all_results(
254            110,    # 'total_included'
255            100,    # 'total_excluded'
256            [
257                # base , amount     | seq | amount | incl | incl_base
258                # ---------------------------------------------------
259                (100.0, 10.0),    # |  3  |    10% |      |
260                # ---------------------------------------------------
261            ],
262            res_percent
263        )
264        self.division_tax.price_include = False
265        self.division_tax.include_base_amount = False
266        res_division = self.division_tax.compute_all(180.0)
267        self._check_compute_all_results(
268            200,    # 'total_included'
269            180,    # 'total_excluded'
270            [
271                # base, amount     | seq | amount | incl | incl_base
272                # ---------------------------------------------------
273                (180.0, 20.0),   # |  4  |    10/ |      |
274                # ---------------------------------------------------
275            ],
276            res_division
277        )
278        self.percent_tax.price_include = True
279        self.percent_tax.include_base_amount = True
280        res_percent = self.percent_tax.compute_all(110.0)
281        self._check_compute_all_results(
282            110,    # 'total_included'
283            100,    # 'total_excluded'
284            [
285                # base, amount     | seq | amount | incl | incl_base
286                # ---------------------------------------------------
287                (100.0, 10.0),   # |  3  |    10% |   t  |     t
288                # ---------------------------------------------------
289            ],
290            res_percent
291        )
292        self.percent_tax_bis.price_include = True
293        self.percent_tax_bis.include_base_amount = True
294        self.percent_tax_bis.amount = 21
295        res_percent = self.percent_tax_bis.compute_all(7.0)
296        self._check_compute_all_results(
297            7.0,   # 'total_included'
298            5.79,  # 'total_excluded'
299            [
300                # base , amount     | seq | amount | incl | incl_base
301                # ---------------------------------------------------
302                (5.79, 1.21),     # |  3  |    21% |   t  |     t
303                # ---------------------------------------------------
304            ],
305            res_percent
306        )
307
308    def test_tax_sequence_normalized_set(self):
309        self.division_tax.sequence = 1
310        self.fixed_tax.sequence = 2
311        self.percent_tax.sequence = 3
312        taxes_set = (self.group_tax | self.division_tax)
313        res = taxes_set.compute_all(200.0)
314        self._check_compute_all_results(
315            252.22,  # 'total_included'
316            200,     # 'total_excluded'
317            [
318                # base , amount     | seq | amount | incl | incl_base
319                # ---------------------------------------------------
320                (200.0, 22.22),   # |  1  |    10/ |      |
321                (200.0, 10.0),    # |  2  |    10  |      |
322                (200.0, 20.0),    # |  3  |    10% |      |
323                # ---------------------------------------------------
324            ],
325            res
326        )
327
328    def test_fixed_tax_include_base_amount(self):
329        self.fixed_tax.include_base_amount = True
330        res = self.group_tax.compute_all(200.0)
331        self._check_compute_all_results(
332            231,     # 'total_included'
333            200,     # 'total_excluded'
334            [
335                # base , amount     | seq | amount | incl | incl_base
336                # ---------------------------------------------------
337                (200.0, 10.0),    # |  1  |    10  |      |     t
338                (210.0, 21.0),    # |  3  |    10% |      |
339                # ---------------------------------------------------
340            ],
341            res
342        )
343
344        self.fixed_tax.price_include = True
345        self.fixed_tax.include_base_amount = False
346        res = self.fixed_tax.compute_all(100.0, quantity=2.0)
347        self._check_compute_all_results(
348            200,     # 'total_included'
349            180,     # 'total_excluded'
350            [
351                # base , amount     | seq | amount | incl | incl_base
352                # ---------------------------------------------------
353                (180.0, 20.0),    # |  1  |    20  |      |     t
354                # ---------------------------------------------------
355            ],
356            res
357        )
358
359    def test_percent_tax_include_base_amount(self):
360        self.percent_tax.price_include = True
361        self.percent_tax.amount = 21.0
362        res = self.percent_tax.compute_all(7.0)
363        self._check_compute_all_results(
364            7.0,      # 'total_included'
365            5.79,     # 'total_excluded'
366            [
367                # base , amount     | seq | amount | incl | incl_base
368                # ---------------------------------------------------
369                (5.79, 1.21),     # |  3  |    21% |   t  |
370                # ---------------------------------------------------
371            ],
372            res
373        )
374
375        self.percent_tax.price_include = True
376        self.percent_tax.amount = 20.0
377        res = self.percent_tax.compute_all(399.99)
378        self._check_compute_all_results(
379            399.99,     # 'total_included'
380            333.33,     # 'total_excluded'
381            [
382                # base , amount     | seq | amount | incl | incl_base
383                # ---------------------------------------------------
384                (333.33, 66.66),  # |  3  |    20% |   t  |
385                # ---------------------------------------------------
386            ],
387            res
388        )
389
390    def test_tax_decimals(self):
391        """Test the rounding of taxes up to 6 decimals (maximum decimals places allowed for currencies)"""
392        self.env.user.company_id.currency_id.rounding = 0.000001
393
394        self.percent_tax.price_include = True
395        self.percent_tax.amount = 21.0
396        res = self.percent_tax.compute_all(7.0)
397        self._check_compute_all_results(
398            7.0,          # 'total_included'
399            5.785124,     # 'total_excluded'
400            [
401                # base , amount          | seq | amount | incl | incl_base
402                # --------------------------------------------------------
403                (5.785124, 1.214876),  # |  3  |    21% |   t  |
404                # --------------------------------------------------------
405            ],
406            res
407        )
408
409        self.percent_tax.price_include = True
410        self.percent_tax.amount = 20.0
411        res = self.percent_tax.compute_all(399.999999)
412        self._check_compute_all_results(
413            399.999999,     # 'total_included'
414            333.333333,     # 'total_excluded'
415            [
416                # base , amount             | seq | amount | incl | incl_base
417                # -----------------------------------------------------------
418                (333.333333, 66.666666),  # |  3  |    20% |   t  |
419                # -----------------------------------------------------------
420            ],
421            res
422        )
423
424    def test_advanced_taxes_computation_0(self):
425        '''Test more advanced taxes computation (see issue 34471).'''
426        tax_1 = self.env['account.tax'].create({
427            'name': 'test_advanced_taxes_computation_0_1',
428            'amount_type': 'percent',
429            'amount': 10,
430            'price_include': True,
431            'include_base_amount': True,
432            'sequence': 1,
433            'invoice_repartition_line_ids': [
434                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
435                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
436                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
437            ],
438            'refund_repartition_line_ids': [
439                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
440                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
441                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
442            ],
443        })
444        tax_2 = self.env['account.tax'].create({
445            'name': 'test_advanced_taxes_computation_0_2',
446            'amount_type': 'percent',
447            'amount': 10,
448            'sequence': 2,
449            'invoice_repartition_line_ids': [
450                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
451                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
452                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
453            ],
454            'refund_repartition_line_ids': [
455                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
456                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
457                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
458            ],
459        })
460        tax_3 = self.env['account.tax'].create({
461            'name': 'test_advanced_taxes_computation_0_3',
462            'amount_type': 'percent',
463            'amount': 10,
464            'price_include': True,
465            'sequence': 3,
466            'invoice_repartition_line_ids': [
467                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
468                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
469                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
470            ],
471            'refund_repartition_line_ids': [
472                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
473                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
474                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
475            ],
476        })
477        tax_4 = self.env['account.tax'].create({
478            'name': 'test_advanced_taxes_computation_0_4',
479            'amount_type': 'percent',
480            'amount': 10,
481            'sequence': 4,
482            'invoice_repartition_line_ids': [
483                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
484                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
485                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
486            ],
487            'refund_repartition_line_ids': [
488                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
489                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
490                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
491            ],
492        })
493        tax_5 = self.env['account.tax'].create({
494            'name': 'test_advanced_taxes_computation_0_5',
495            'amount_type': 'percent',
496            'amount': 10,
497            'price_include': True,
498            'sequence': 5,
499            'invoice_repartition_line_ids': [
500                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
501                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
502                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
503            ],
504            'refund_repartition_line_ids': [
505                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
506                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
507                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
508            ],
509        })
510        taxes = tax_1 + tax_2 + tax_3 + tax_4 + tax_5
511
512        # Test with positive amount.
513        self._check_compute_all_results(
514            154,     # 'total_included'
515            100,     # 'total_excluded'
516            [
517                # base , amount     | seq | amount | incl | incl_base
518                # ---------------------------------------------------
519                (100.0, 5.0),     # |  1  |    10% |   t  |     t
520                (100.0, 5.0),     # |  1  |    10% |   t  |     t
521                (110.0, 5.5),     # |  2  |    10% |      |
522                (110.0, 5.5),     # |  2  |    10% |      |
523                (110.0, 5.5),     # |  3  |    10% |   t  |
524                (110.0, 5.5),     # |  3  |    10% |   t  |
525                (110.0, 5.5),     # |  4  |    10% |      |
526                (110.0, 5.5),     # |  4  |    10% |      |
527                (110.0, 5.5),     # |  5  |    10% |   t  |
528                (110.0, 5.5),     # |  5  |    10% |   t  |
529                # ---------------------------------------------------
530            ],
531            taxes.compute_all(132.0)
532        )
533
534        # Test with negative amount.
535        self._check_compute_all_results(
536            -154,    # 'total_included'
537            -100,    # 'total_excluded'
538            [
539                # base , amount     | seq | amount | incl | incl_base
540                # ---------------------------------------------------
541                (-100.0, -5.0),   # |  1  |    10% |   t  |     t
542                (-100.0, -5.0),   # |  1  |    10% |   t  |     t
543                (-110.0, -5.5),   # |  2  |    10% |      |
544                (-110.0, -5.5),   # |  2  |    10% |      |
545                (-110.0, -5.5),   # |  3  |    10% |   t  |
546                (-110.0, -5.5),   # |  3  |    10% |   t  |
547                (-110.0, -5.5),   # |  4  |    10% |      |
548                (-110.0, -5.5),   # |  4  |    10% |      |
549                (-110.0, -5.5),   # |  5  |    10% |   t  |
550                (-110.0, -5.5),   # |  5  |    10% |   t  |
551                # ---------------------------------------------------
552            ],
553            taxes.compute_all(-132.0)
554        )
555
556    def test_intracomm_taxes_computation_0(self):
557        ''' Test usage of intracomm taxes having e.g.+100%, -100% as repartition lines. '''
558        intracomm_tax = self.env['account.tax'].create({
559            'name': 'test_intracomm_taxes_computation_0_1',
560            'amount_type': 'percent',
561            'amount': 21,
562            'invoice_repartition_line_ids': [
563                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
564                (0, 0, {'repartition_type': 'tax', 'factor_percent': 100.0}),
565                (0, 0, {'repartition_type': 'tax', 'factor_percent': -100.0}),
566            ],
567            'refund_repartition_line_ids': [
568                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
569                (0, 0, {'repartition_type': 'tax', 'factor_percent': 100.0}),
570                (0, 0, {'repartition_type': 'tax', 'factor_percent': -100.0}),
571            ],
572        })
573
574        # Test with positive amount.
575        self._check_compute_all_results(
576            100,     # 'total_included'
577            100,     # 'total_excluded'
578            [
579                # base , amount
580                # ---------------
581                (100.0, 21.0),
582                (100.0, -21.0),
583                # ---------------
584            ],
585            intracomm_tax.compute_all(100.0)
586        )
587
588        # Test with negative amount.
589        self._check_compute_all_results(
590            -100,    # 'total_included'
591            -100,    # 'total_excluded'
592            [
593                # base , amount
594                # ---------------
595                (-100.0, -21.0),
596                (-100.0, 21.0),
597                # ---------------
598            ],
599            intracomm_tax.compute_all(-100.0)
600        )
601
602    def test_rounding_issues_0(self):
603        ''' Test taxes having a complex setup of repartition lines. '''
604        tax = self.env['account.tax'].create({
605            'name': 'test_rounding_issues_0',
606            'amount_type': 'percent',
607            'amount': 3,
608            'invoice_repartition_line_ids': [
609                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
610                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
611                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
612                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
613                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
614                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
615                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
616            ],
617            'refund_repartition_line_ids': [
618                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
619                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
620                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
621                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
622                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
623                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
624                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
625            ],
626        })
627
628        # Test with positive amount.
629        self._check_compute_all_results(
630            1.09,   # 'total_included'
631            1,      # 'total_excluded'
632            [
633                # base , amount
634                # ---------------
635                (1.0, 0.01),
636                (1.0, 0.01),
637                (1.0, 0.01),
638                (1.0, 0.02),
639                (1.0, 0.02),
640                (1.0, 0.02),
641                # ---------------
642            ],
643            tax.compute_all(1.0)
644        )
645
646        # Test with negative amount.
647        self._check_compute_all_results(
648            -1.09,  # 'total_included'
649            -1,     # 'total_excluded'
650            [
651                # base , amount
652                # ---------------
653                (-1.0, -0.01),
654                (-1.0, -0.01),
655                (-1.0, -0.01),
656                (-1.0, -0.02),
657                (-1.0, -0.02),
658                (-1.0, -0.02),
659                # ---------------
660            ],
661            tax.compute_all(-1.0)
662        )
663
664    def test_rounding_issues_1(self):
665        ''' Test taxes having a complex setup of repartition lines. '''
666        tax = self.env['account.tax'].create({
667            'name': 'test_advanced_taxes_repartition_lines_computation_1',
668            'amount_type': 'percent',
669            'amount': 3,
670            'invoice_repartition_line_ids': [
671                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
672                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
673                (0, 0, {'repartition_type': 'tax', 'factor_percent': -50.0}),
674                (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
675                (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
676                (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
677                (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
678            ],
679            'refund_repartition_line_ids': [
680                (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
681                (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
682                (0, 0, {'repartition_type': 'tax', 'factor_percent': -50.0}),
683                (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
684                (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
685                (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
686                (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
687            ],
688        })
689
690        # Test with positive amount.
691        self._check_compute_all_results(
692            1,      # 'total_included'
693            1,      # 'total_excluded'
694            [
695                # base , amount
696                # ---------------
697                (1.0, 0.02),
698                (1.0, -0.02),
699                (1.0, 0.01),
700                (1.0, 0.01),
701                (1.0, -0.01),
702                (1.0, -0.01),
703                # ---------------
704            ],
705            tax.compute_all(1.0)
706        )
707
708        # Test with negative amount.
709        self._check_compute_all_results(
710            -1,     # 'total_included'
711            -1,     # 'total_excluded'
712            [
713                # base , amount
714                # ---------------
715                (-1.0, -0.02),
716                (-1.0, 0.02),
717                (-1.0, -0.01),
718                (-1.0, -0.01),
719                (-1.0, 0.01),
720                (-1.0, 0.01),
721                # ---------------
722            ],
723            tax.compute_all(-1.0)
724        )
725
726    def test_rounding_tax_excluded_round_per_line_01(self):
727        ''' Test the rounding of a 19% price excluded tax in an invoice having 22689 and 9176 as lines.
728        The decimal precision is set to zero.
729        The computation must be similar to round(22689 * 0.19) + round(9176 * 0.19).
730        '''
731        self.tax_19_percent.company_id.currency_id.rounding = 1.0
732        self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_per_line'
733
734        res1 = self.tax_19_percent.compute_all(22689)
735        self._check_compute_all_results(
736            27000,      # 'total_included'
737            22689,      # 'total_excluded'
738            [
739                # base, amount
740                # ---------------
741                (22689, 4311),
742                # ---------------
743            ],
744            res1
745        )
746
747        res2 = self.tax_19_percent.compute_all(9176)
748        self._check_compute_all_results(
749            10919,      # 'total_included'
750            9176,       # 'total_excluded'
751            [
752                # base , amount
753                # ---------------
754                (9176,  1743),
755                # ---------------
756            ],
757            res2
758        )
759
760    def test_rounding_tax_excluded_round_globally(self):
761        ''' Test the rounding of a 19% price excluded tax in an invoice having 22689 and 9176 as lines.
762        The decimal precision is set to zero.
763        The computation must be similar to round((22689 + 9176) * 0.19).
764        '''
765        self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_globally'
766
767        res1 = self.tax_19_percent.compute_all(22689)
768        self._check_compute_all_results(
769            27000,      # 'total_included'
770            22689,      # 'total_excluded'
771            [
772                # base, amount
773                # ---------------
774                (22689, 4310.91),
775                # ---------------
776            ],
777            res1
778        )
779
780        res2 = self.tax_19_percent.compute_all(9176)
781        self._check_compute_all_results(
782            10919,      # 'total_included'
783            9176,       # 'total_excluded'
784            [
785                # base , amount
786                # ---------------
787                (9176,  1743.44),
788                # ---------------
789            ],
790            res2
791        )
792
793    def test_rounding_tax_included_round_per_line_01(self):
794        ''' Test the rounding of a 19% price included tax in an invoice having 27000 and 10920 as lines.
795        The decimal precision is set to zero.
796        The computation must be similar to round(27000 / 1.19) + round(10920 / 1.19).
797        '''
798        self.tax_19_percent.price_include = True
799        self.tax_19_percent.company_id.currency_id.rounding = 1.0
800        self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_per_line'
801
802        res1 = self.tax_19_percent.compute_all(27000)
803        self._check_compute_all_results(
804            27000,      # 'total_included'
805            22689,      # 'total_excluded'
806            [
807                # base , amount
808                # ---------------
809                (22689, 4311),
810                # ---------------
811            ],
812            res1
813        )
814
815        res2 = self.tax_19_percent.compute_all(10920)
816        self._check_compute_all_results(
817            10920,      # 'total_included'
818            9176,       # 'total_excluded'
819            [
820                # base , amount
821                # ---------------
822                (9176,  1744),
823                # ---------------
824            ],
825            res2
826        )
827
828    def test_rounding_tax_included_round_per_line_02(self):
829        ''' Test the rounding of a 12% price included tax in an invoice having 52.50 as line.
830        The decimal precision is set to 2.
831        '''
832        self.tax_12_percent.price_include = True
833        self.tax_12_percent.company_id.currency_id.rounding = 0.01
834
835        res1 = self.tax_12_percent.compute_all(52.50)
836        self._check_compute_all_results(
837            52.50,      # 'total_included'
838            46.88,      # 'total_excluded'
839            [
840                # base , amount
841                # -------------
842                (46.88, 5.62),
843                # -------------
844            ],
845            res1
846        )
847
848    def test_rounding_tax_included_round_per_line_03(self):
849        ''' Test the rounding of a 8% and 0% price included tax in an invoice having 8 * 15.55 as line.
850        The decimal precision is set to 2.
851        '''
852        self.tax_0_percent.company_id.currency_id.rounding = 0.01
853        self.tax_0_percent.price_include = True
854        self.tax_8_percent.price_include = True
855
856        self.group_tax.children_tax_ids = [(6, 0, self.tax_0_percent.ids)]
857        self.group_tax_bis.children_tax_ids = [(6, 0, self.tax_8_percent.ids)]
858
859        res1 = (self.tax_8_percent | self.tax_0_percent).compute_all(15.55, quantity=8.0)
860        self._check_compute_all_results(
861            124.40,      # 'total_included'
862            115.19,      # 'total_excluded'
863            [
864                # base , amount
865                # -------------
866                (115.19, 9.21),
867                (115.19, 0.00),
868                # -------------
869            ],
870            res1
871        )
872
873        res2 = (self.tax_0_percent | self.tax_8_percent).compute_all(15.55, quantity=8.0)
874        self._check_compute_all_results(
875            124.40,      # 'total_included'
876            115.19,      # 'total_excluded'
877            [
878                # base , amount
879                # -------------
880                (115.19, 0.00),
881                (115.19, 9.21),
882                # -------------
883            ],
884            res2
885        )
886
887    def test_rounding_tax_included_round_per_line_04(self):
888        ''' Test the rounding of a 5% price included tax.
889        The decimal precision is set to 0.05.
890        '''
891        self.tax_5_percent.price_include = True
892        self.tax_5_percent.company_id.currency_id.rounding = 0.05
893        self.tax_5_percent.company_id.tax_calculation_rounding_method = 'round_per_line'
894
895        res1 = self.tax_5_percent.compute_all(5)
896        self._check_compute_all_results(
897            5,      # 'total_included'
898            4.75,      # 'total_excluded'
899            [
900                # base , amount
901                # ---------------
902                (4.75, 0.25),
903                # ---------------
904            ],
905            res1
906        )
907
908        res2 = self.tax_5_percent.compute_all(10)
909        self._check_compute_all_results(
910            10,      # 'total_included'
911            9.5,      # 'total_excluded'
912            [
913                # base , amount
914                # ---------------
915                (9.5, 0.5),
916                # ---------------
917            ],
918            res2
919        )
920
921        res3 = self.tax_5_percent.compute_all(50)
922        self._check_compute_all_results(
923            50,      # 'total_included'
924            47.6,      # 'total_excluded'
925            [
926                # base , amount
927                # ---------------
928                (47.6, 2.4),
929                # ---------------
930            ],
931            res3
932        )
933
934    def test_rounding_tax_included_round_globally_01(self):
935        ''' Test the rounding of a 19% price included tax in an invoice having 27000 and 10920 as lines.
936        The decimal precision is set to zero.
937        The computation must be similar to round((27000 + 10920) / 1.19).
938        '''
939        self.tax_19_percent.price_include = True
940        self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_globally'
941
942        res1 = self.tax_19_percent.compute_all(27000)
943        self._check_compute_all_results(
944            27000,      # 'total_included'
945            22689,      # 'total_excluded'
946            [
947                # base , amount
948                # ---------------
949                (22689, 4311),
950                # ---------------
951            ],
952            res1
953        )
954
955        res2 = self.tax_19_percent.compute_all(10920)
956        self._check_compute_all_results(
957            10920,      # 'total_included'
958            9176,       # 'total_excluded'
959            [
960                # base , amount
961                # ---------------
962                (9176,  1744),
963                # ---------------
964            ],
965            res2
966        )
967
968    def test_rounding_tax_included_round_globally_02(self):
969        ''' Test the rounding of a 21% price included tax in an invoice having 11.90 and 2.80 as lines.
970        The decimal precision is set to 2.
971        '''
972        self.tax_21_percent.price_include = True
973        self.tax_21_percent.company_id.currency_id.rounding = 0.01
974        self.tax_21_percent.company_id.tax_calculation_rounding_method = 'round_globally'
975
976        res1 = self.tax_21_percent.compute_all(11.90)
977        self._check_compute_all_results(
978            11.90,      # 'total_included'
979            9.83,       # 'total_excluded'
980            [
981                # base , amount
982                # ---------------
983                (9.83, 2.07),
984                # ---------------
985            ],
986            res1
987        )
988
989        res2 = self.tax_21_percent.compute_all(2.80)
990        self._check_compute_all_results(
991            2.80,      # 'total_included'
992            2.31,      # 'total_excluded'
993            [
994                # base , amount
995                # ---------------
996                (2.31,  0.49),
997                # ---------------
998            ],
999            res2
1000        )
1001
1002    def test_rounding_tax_included_round_globally_03(self):
1003        ''' Test the rounding of a 5% price included tax.
1004        The decimal precision is set to 0.05.
1005        '''
1006        self.tax_5_percent.price_include = True
1007        self.tax_5_percent.company_id.currency_id.rounding = 0.05
1008        self.tax_5_percent.company_id.tax_calculation_rounding_method = 'round_globally'
1009
1010        res1 = self.tax_5_percent.compute_all(5)
1011        self._check_compute_all_results(
1012            5,      # 'total_included'
1013            4.75,      # 'total_excluded'
1014            [
1015                # base , amount
1016                # ---------------
1017                (4.75, 0.25),
1018                # ---------------
1019            ],
1020            res1
1021        )
1022
1023        res2 = self.tax_5_percent.compute_all(10)
1024        self._check_compute_all_results(
1025            10,      # 'total_included'
1026            9.5,      # 'total_excluded'
1027            [
1028                # base , amount
1029                # ---------------
1030                (9.50, 0.50),
1031                # ---------------
1032            ],
1033            res2
1034        )
1035
1036        res3 = self.tax_5_percent.compute_all(50)
1037        self._check_compute_all_results(
1038            50,      # 'total_included'
1039            47.6,      # 'total_excluded'
1040            [
1041                # base , amount
1042                # ---------------
1043                (47.60, 2.40),
1044                # ---------------
1045            ],
1046            res3
1047        )
1048
1049    def test_mixing_price_included_excluded_with_affect_base(self):
1050        tax_10_fix = self.env['account.tax'].create({
1051            'name': "tax_10_fix",
1052            'amount_type': 'fixed',
1053            'amount': 10.0,
1054            'include_base_amount': True,
1055        })
1056        tax_21 = self.env['account.tax'].create({
1057            'name': "tax_21",
1058            'amount_type': 'percent',
1059            'amount': 21.0,
1060            'price_include': True,
1061            'include_base_amount': True,
1062        })
1063
1064        self._check_compute_all_results(
1065            1222.1,     # 'total_included'
1066            1000.0,     # 'total_excluded'
1067            [
1068                # base , amount
1069                # ---------------
1070                (1000.0, 10.0),
1071                (1010.0, 212.1),
1072                # ---------------
1073            ],
1074            (tax_10_fix + tax_21).compute_all(1210),
1075        )
1076