150 lines
4.9 KiB
Python
150 lines
4.9 KiB
Python
from odoo.addons.account.tests.test_tax import TestTaxCommon
|
|
from odoo.tests import tagged
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestTaxesComputation(TestTaxCommon):
|
|
|
|
def python_tax(self, formula, **kwargs):
|
|
self.number += 1
|
|
vals = {
|
|
**kwargs,
|
|
'name': f"code_({self.number})",
|
|
'amount_type': 'code',
|
|
'amount': 0.0,
|
|
'formula': formula,
|
|
}
|
|
if 'price_include' in vals:
|
|
price_include = vals.pop('price_include')
|
|
if self.env.company.account_price_include != price_include:
|
|
vals['price_include_override'] = price_include
|
|
else:
|
|
vals['price_include_override'] = False
|
|
return self.env['account.tax'].create(vals)
|
|
|
|
def _jsonify_tax(self, tax):
|
|
values = super()._jsonify_tax(tax)
|
|
values['formula_decoded_info'] = tax.formula_decoded_info
|
|
return values
|
|
|
|
def assert_python_taxes_computation(
|
|
self,
|
|
formula,
|
|
price_unit,
|
|
expected_values,
|
|
product_values=None,
|
|
price_include='tax_excluded',
|
|
):
|
|
tax = self.python_tax(formula, price_include=price_include)
|
|
if product_values:
|
|
product = self.env['product.product'].create({
|
|
'name': "assert_python_taxes_computation",
|
|
**product_values,
|
|
})
|
|
else:
|
|
product = None
|
|
return self.assert_taxes_computation(tax, price_unit, expected_values, product=product)
|
|
|
|
def test_formula(self):
|
|
self.assert_python_taxes_computation(
|
|
"max(quantity * price_unit * 0.21, quantity * 4.17)",
|
|
130.0,
|
|
{
|
|
'total_included': 157.3,
|
|
'total_excluded': 130.0,
|
|
'taxes_data': (
|
|
(130.0, 27.3),
|
|
),
|
|
},
|
|
)
|
|
self.assert_python_taxes_computation(
|
|
"max(quantity * price_unit * 0.21, quantity * 4.17)",
|
|
130.0,
|
|
{
|
|
'total_included': 130.0,
|
|
'total_excluded': 102.7,
|
|
'taxes_data': (
|
|
(102.7, 27.3),
|
|
),
|
|
},
|
|
price_include='tax_included',
|
|
)
|
|
self.assert_python_taxes_computation(
|
|
"product.volume * quantity * 0.35",
|
|
100.0,
|
|
{
|
|
'total_included': 135.0,
|
|
'total_excluded': 100.0,
|
|
'taxes_data': (
|
|
(100.0, 35.0),
|
|
),
|
|
},
|
|
product_values={'volume': 100.0},
|
|
)
|
|
self.assert_python_taxes_computation(
|
|
"product.volume > 100 and 10 or 5",
|
|
100.0,
|
|
{
|
|
'total_included': 110.0,
|
|
'total_excluded': 100.0,
|
|
'taxes_data': (
|
|
(100.0, 10.0),
|
|
),
|
|
},
|
|
product_values={'volume': 105.0},
|
|
)
|
|
self.assert_python_taxes_computation(
|
|
"product.volume > 100 and 10 or 5",
|
|
100.0,
|
|
{
|
|
'total_included': 105.0,
|
|
'total_excluded': 100.0,
|
|
'taxes_data': (
|
|
(100.0, 5.0),
|
|
),
|
|
},
|
|
product_values={'volume': 50.0},
|
|
)
|
|
self.assert_python_taxes_computation(
|
|
"product.volume > 100 and 5 or None",
|
|
100.0,
|
|
{
|
|
'total_included': 100.0,
|
|
'total_excluded': 100.0,
|
|
'taxes_data': [],
|
|
},
|
|
product_values={'volume': 50.0},
|
|
)
|
|
self.assert_python_taxes_computation(
|
|
"(product.volume or 5.0) and 0.0 or 10.0",
|
|
100.0,
|
|
{
|
|
'total_included': 110.0,
|
|
'total_excluded': 100.0,
|
|
'taxes_data': (
|
|
(100.0, 10.0),
|
|
),
|
|
},
|
|
product_values={'volume': 0.0},
|
|
)
|
|
self._run_js_tests()
|
|
|
|
def test_invalid_formula(self):
|
|
# You have no access to relational field.
|
|
with self.assertRaises(ValidationError):
|
|
self.python_tax(formula='product.product_tmpl_id')
|
|
# You don't have access to any record.
|
|
with self.assertRaises(ValidationError):
|
|
self.python_tax(formula='product.sudo()')
|
|
# You are restricted to min max but that's it: no python collection.
|
|
with self.assertRaises(ValidationError):
|
|
self.python_tax(formula='tuple(1, 2, 3)')
|
|
with self.assertRaises(ValidationError):
|
|
self.python_tax(formula='set(1, 2, 3)')
|
|
with self.assertRaises(ValidationError):
|
|
self.python_tax(formula='[1, 2, 3]')
|
|
# No access to builtins that are not part of the whitelist.
|
|
with self.assertRaises(ValidationError):
|
|
self.python_tax(formula='range(1, 10)')
|