19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:30:07 +01:00
parent ba20ce7443
commit 768b70e05e
2357 changed files with 1057103 additions and 712486 deletions

View file

@ -9,10 +9,9 @@ from odoo.tests import tagged, Form
class TestInvoiceTaxes(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
cls.company_data['company'].country_id = cls.env.ref('base.us')
def setUpClass(cls):
super().setUpClass()
cls.other_currency = cls.setup_other_currency('HRK')
cls.percent_tax_1 = cls.env['account.tax'].create({
'name': '21%',
@ -24,7 +23,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'name': '21% incl',
'amount_type': 'percent',
'amount': 21,
'price_include': True,
'price_include_override': 'tax_included',
'include_base_amount': True,
'sequence': 20,
})
@ -38,7 +37,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'name': '5% incl',
'amount_type': 'percent',
'amount': 5,
'price_include': True,
'price_include_override': 'tax_included',
'include_base_amount': True,
'sequence': 40,
})
@ -76,8 +75,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
}),
],
})
tax_tags = tax_report_line.expression_ids._get_matching_tags()
cls.tax_tag_pos, cls.tax_tag_neg = tax_tags.sorted('tax_negate')
cls.tax_tag = tax_report_line.expression_ids._get_matching_tags()
base_report_line = cls.env['account.report.line'].create({
'name': 'base_test_tax_report_line',
@ -91,10 +89,9 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
}),
],
})
base_tags = base_report_line.expression_ids._get_matching_tags()
cls.base_tag_pos, cls.base_tag_neg = base_tags.sorted('tax_negate')
cls.base_tag = base_report_line.expression_ids._get_matching_tags()
def _create_invoice(self, taxes_per_line, inv_type='out_invoice', currency_id=False, invoice_payment_term_id=False):
def _create_invoice_taxes_per_line(self, taxes_per_line, inv_type='out_invoice', currency_id=False, invoice_payment_term_id=False):
''' Create an invoice on the fly.
:param taxes_per_line: A list of tuple (price_unit, account.tax recordset)
@ -125,10 +122,10 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
--------------------------------------------
21% | / | 100 | 21
'''
invoice = self._create_invoice([(100, self.env['account.tax'])])
invoice = self._create_invoice_taxes_per_line([(100, self.env['account.tax'])])
invoice.invoice_line_ids[0].tax_ids = self.percent_tax_1
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id'), [
{'name': self.percent_tax_1.name, 'tax_base_amount': 100, 'balance': -21, 'tax_ids': []},
{'name': self.percent_tax_1.name, 'tax_base_amount': -100, 'balance': -21, 'tax_ids': []},
])
def test_one_tax_per_line(self):
@ -146,16 +143,16 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
21% incl | / | 100 | 21
12% | / | 100 | 12
'''
invoice = self._create_invoice([
invoice = self._create_invoice_taxes_per_line([
(100, self.percent_tax_1),
(121, self.percent_tax_1_incl),
(100, self.percent_tax_2),
])
invoice.action_post()
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id').sorted(lambda x: x.name), [
{'name': self.percent_tax_2.name, 'tax_base_amount': 100, 'balance': -12, 'tax_ids': []},
{'name': self.percent_tax_1.name, 'tax_base_amount': 100, 'balance': -21, 'tax_ids': []},
{'name': self.percent_tax_1_incl.name, 'tax_base_amount': 100, 'balance': -21, 'tax_ids': []},
{'name': self.percent_tax_2.name, 'tax_base_amount': -100, 'balance': -12, 'tax_ids': []},
{'name': self.percent_tax_1.name, 'tax_base_amount': -100, 'balance': -21, 'tax_ids': []},
{'name': self.percent_tax_1_incl.name, 'tax_base_amount': -100, 'balance': -21, 'tax_ids': []},
])
def test_affecting_base_amount(self):
@ -172,14 +169,14 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
12% | / | 121 | 14.52
12% | / | 100 | 12
'''
invoice = self._create_invoice([
invoice = self._create_invoice_taxes_per_line([
(121, self.percent_tax_1_incl + self.percent_tax_2),
(100, self.percent_tax_2),
])
invoice.action_post()
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id').sorted(lambda x: -x.balance), [
{'name': self.percent_tax_1_incl.name, 'tax_base_amount': 100, 'balance': -21, 'tax_ids': [self.percent_tax_2.id]},
{'name': self.percent_tax_2.name, 'tax_base_amount': 221, 'balance': -26.52, 'tax_ids': []},
{'name': self.percent_tax_1_incl.name, 'tax_base_amount': -100, 'balance': -21, 'tax_ids': [self.percent_tax_2.id]},
{'name': self.percent_tax_2.name, 'tax_base_amount': -221, 'balance': -26.52, 'tax_ids': []},
])
def test_group_of_taxes(self):
@ -196,15 +193,15 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
12% | 21% incl | 121 | 14.52
12% | / | 100 | 12
'''
invoice = self._create_invoice([
invoice = self._create_invoice_taxes_per_line([
(121, self.group_tax),
(100, self.percent_tax_2),
])
invoice.action_post()
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id').sorted('balance'), [
{'name': self.percent_tax_1_incl.name, 'tax_base_amount': 100.0, 'balance': -21.0, 'tax_ids': [self.percent_tax_2.id]},
{'name': self.percent_tax_2.name, 'tax_base_amount': 121.0, 'balance': -14.52, 'tax_ids': []},
{'name': self.percent_tax_2.name, 'tax_base_amount': 100.0, 'balance': -12.0, 'tax_ids': []},
{'name': self.percent_tax_1_incl.name, 'tax_base_amount': -100.0, 'balance': -21.0, 'tax_ids': [self.percent_tax_2.id]},
{'name': self.percent_tax_2.name, 'tax_base_amount': -121.0, 'balance': -14.52, 'tax_ids': []},
{'name': self.percent_tax_2.name, 'tax_base_amount': -100.0, 'balance': -12.0, 'tax_ids': []},
])
def _create_tax_tag(self, tag_name):
@ -271,7 +268,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
})
# Test invoice repartition
invoice = self._create_invoice([(100, tax)], inv_type='out_invoice')
invoice = self._create_invoice_taxes_per_line([(100, tax)], inv_type='out_invoice')
invoice.action_post()
self.assertEqual(len(invoice.line_ids), 4, "There should be 4 account move lines created for the invoice: payable, base and 2 tax lines")
@ -287,7 +284,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
self.assertEqual(inv_tax_lines.filtered(lambda x: x.account_id == account_2).tax_tag_ids, inv_tax_tag_90, "Tax line on account 2 should have 90% tag")
# Test refund repartition
refund = self._create_invoice([(100, tax)], inv_type='out_refund')
refund = self._create_invoice_taxes_per_line([(100, tax)], inv_type='out_refund')
refund.action_post()
self.assertEqual(len(refund.line_ids), 4, "There should be 4 account move lines created for the refund: payable, base and 2 tax lines")
@ -319,10 +316,10 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'type_tax_use': 'sale',
'amount_type': 'division',
'amount': 100,
'price_include': True,
'price_include_override': 'tax_included',
'include_base_amount': True,
})
invoice = self._create_invoice([(100, sale_tax)])
invoice = self._create_invoice_taxes_per_line([(100, sale_tax)])
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id'), [{
'name': sale_tax.name,
'tax_base_amount': 0.0,
@ -348,21 +345,21 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'invoice_repartition_line_ids': [
(0, 0, {
'repartition_type': 'base',
'tag_ids': [(6, 0, self.base_tag_pos.ids)],
'tag_ids': [(6, 0, self.base_tag.ids)],
}),
(0, 0, {
'repartition_type': 'tax',
'tag_ids': [(6, 0, self.tax_tag_pos.ids)],
'tag_ids': [(6, 0, self.tax_tag.ids)],
}),
],
'refund_repartition_line_ids': [
(0, 0, {
'repartition_type': 'base',
'tag_ids': [(6, 0, self.base_tag_neg.ids)],
'tag_ids': [(6, 0, self.base_tag.ids)],
}),
(0, 0, {
'repartition_type': 'tax',
'tag_ids': [(6, 0, self.tax_tag_neg.ids)],
'tag_ids': [(6, 0, self.tax_tag.ids)],
}),
],
})
@ -393,9 +390,9 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
move = move_form.save()
self.assertRecordValues(move.line_ids.sorted('balance'), [
{'balance': -1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': False},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_neg.ids, 'tax_base_amount': 1000, 'tax_repartition_line_id': ref_tax_rep_ln.id, 'tax_tag_invert': False},
{'balance': 1000.0, 'tax_ids': sale_tax.ids, 'tax_tag_ids': self.base_tag_neg.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': False},
{'balance': -1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': 1000, 'tax_repartition_line_id': ref_tax_rep_ln.id},
{'balance': 1000.0, 'tax_ids': sale_tax.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False},
])
# === Tax in credit ===
@ -420,9 +417,9 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
move = move_form.save()
self.assertRecordValues(move.line_ids.sorted('balance'), [
{'balance': -1000.0, 'tax_ids': sale_tax.ids, 'tax_tag_ids': self.base_tag_pos.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': True},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_pos.ids, 'tax_base_amount': 1000, 'tax_repartition_line_id': inv_tax_rep_ln.id, 'tax_tag_invert': True},
{'balance': 1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': False},
{'balance': -1000.0, 'tax_ids': sale_tax.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': -1000, 'tax_repartition_line_id': inv_tax_rep_ln.id},
{'balance': 1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False},
])
def test_misc_journal_entry_tax_tags_purchase(self):
@ -434,21 +431,21 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'invoice_repartition_line_ids': [
(0, 0, {
'repartition_type': 'base',
'tag_ids': [(6, 0, self.base_tag_pos.ids)],
'tag_ids': [(6, 0, self.base_tag.ids)],
}),
(0, 0, {
'repartition_type': 'tax',
'tag_ids': [(6, 0, self.tax_tag_pos.ids)],
'tag_ids': [(6, 0, self.tax_tag.ids)],
}),
],
'refund_repartition_line_ids': [
(0, 0, {
'repartition_type': 'base',
'tag_ids': [(6, 0, self.base_tag_neg.ids)],
'tag_ids': [(6, 0, self.base_tag.ids)],
}),
(0, 0, {
'repartition_type': 'tax',
'tag_ids': [(6, 0, self.tax_tag_neg.ids)],
'tag_ids': [(6, 0, self.tax_tag.ids)],
}),
],
})
@ -478,9 +475,9 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
move = move_form.save()
self.assertRecordValues(move.line_ids.sorted('balance'), [
{'balance': -1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': False},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_pos.ids, 'tax_base_amount': 1000, 'tax_repartition_line_id': inv_tax_rep_ln.id, 'tax_tag_invert': False},
{'balance': 1000.0, 'tax_ids': purch_tax.ids, 'tax_tag_ids': self.base_tag_pos.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': False},
{'balance': -1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': 1000, 'tax_repartition_line_id': inv_tax_rep_ln.id},
{'balance': 1000.0, 'tax_ids': purch_tax.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False},
])
# === Tax in credit ===
@ -505,9 +502,9 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
move = move_form.save()
self.assertRecordValues(move.line_ids.sorted('balance'), [
{'balance': -1000.0, 'tax_ids': purch_tax.ids, 'tax_tag_ids': self.base_tag_neg.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': True},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_neg.ids, 'tax_base_amount': 1000, 'tax_repartition_line_id': ref_tax_rep_ln.id, 'tax_tag_invert': True},
{'balance': 1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False, 'tax_tag_invert': False},
{'balance': -1000.0, 'tax_ids': purch_tax.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0, 'tax_repartition_line_id': False},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': -1000, 'tax_repartition_line_id': ref_tax_rep_ln.id},
{'balance': 1100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0, 'tax_repartition_line_id': False},
])
def test_misc_entry_tax_group_signs(self):
@ -525,11 +522,11 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'invoice_repartition_line_ids': [
(0, 0, {
'repartition_type': 'base',
'tag_ids': [(6, 0, self.base_tag_pos.ids)],
'tag_ids': [(6, 0, self.base_tag.ids)],
}),
(0, 0, {
'repartition_type': 'tax',
'tag_ids': [(6, 0, self.tax_tag_pos.ids)],
'tag_ids': [(6, 0, self.tax_tag.ids)],
}),
],
'refund_repartition_line_ids': [
@ -550,11 +547,11 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'refund_repartition_line_ids': [
(0, 0, {
'repartition_type': 'base',
'tag_ids': [(6, 0, self.base_tag_neg.ids)],
'tag_ids': [(6, 0, self.base_tag.ids)],
}),
(0, 0, {
'repartition_type': 'tax',
'tag_ids': [(6, 0, self.tax_tag_neg.ids)],
'tag_ids': [(6, 0, self.tax_tag.ids)],
}),
],
})
@ -588,37 +585,37 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
# Sale tax on debit: use refund repartition
debit_sale_move = _create_misc_operation(sale_group, 'debit')
self.assertRecordValues(debit_sale_move.line_ids.sorted('balance'), [
{'balance': -1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
{'balance': 50.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 1000},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_neg.ids, 'tax_base_amount': 1000},
{'balance': 1000.0, 'tax_ids': sale_group.ids, 'tax_tag_ids': self.base_tag_neg.ids, 'tax_base_amount': 0},
{'balance': -1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
{'balance': 50.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 1000},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': 1000},
{'balance': 1000.0, 'tax_ids': sale_group.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0},
])
# Sale tax on credit: use invoice repartition
credit_sale_move = _create_misc_operation(sale_group, 'credit')
self.assertRecordValues(credit_sale_move.line_ids.sorted('balance'), [
{'balance': -1000.0, 'tax_ids': sale_group.ids, 'tax_tag_ids': self.base_tag_pos.ids, 'tax_base_amount': 0},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 1000},
{'balance': -50.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_pos.ids, 'tax_base_amount': 1000},
{'balance': 1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
{'balance': -1000.0, 'tax_ids': sale_group.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': -1000},
{'balance': -50.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': -1000},
{'balance': 1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
])
# Purchase tax on debit: use invoice repartition
debit_purchase_move = _create_misc_operation(purchase_group, 'debit')
self.assertRecordValues(debit_purchase_move.line_ids.sorted('balance'), [
{'balance': -1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
{'balance': 50.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_pos.ids, 'tax_base_amount': 1000},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 1000},
{'balance': 1000.0, 'tax_ids': purchase_group.ids, 'tax_tag_ids': self.base_tag_pos.ids, 'tax_base_amount': 0},
{'balance': -1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
{'balance': 50.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': 1000},
{'balance': 100.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 1000},
{'balance': 1000.0, 'tax_ids': purchase_group.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0},
])
# Purchase tax on credit: use refund repartition
credit_purchase_move = _create_misc_operation(purchase_group, 'credit')
self.assertRecordValues(credit_purchase_move.line_ids.sorted('balance'), [
{'balance': -1000.0, 'tax_ids': purchase_group.ids, 'tax_tag_ids': self.base_tag_neg.ids, 'tax_base_amount': 0},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_neg.ids, 'tax_base_amount': 1000},
{'balance': -50.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 1000},
{'balance': 1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
{'balance': -1000.0, 'tax_ids': purchase_group.ids, 'tax_tag_ids': self.base_tag.ids, 'tax_base_amount': 0},
{'balance': -100.0, 'tax_ids': [], 'tax_tag_ids': self.tax_tag.ids, 'tax_base_amount': -1000},
{'balance': -50.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': -1000},
{'balance': 1150.0, 'tax_ids': [], 'tax_tag_ids': [], 'tax_base_amount': 0},
])
def test_tax_calculation_foreign_currency_large_quantity(self):
@ -631,15 +628,15 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
self.env['res.currency.rate'].create({
'name': '2018-01-01',
'rate': 1.1726,
'currency_id': self.currency_data['currency'].id,
'currency_id': self.other_currency.id,
'company_id': self.env.company.id,
})
self.currency_data['currency'].rounding = 0.05
self.other_currency.rounding = 0.05
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'currency_id': self.currency_data['currency'].id,
'currency_id': self.other_currency.id,
'invoice_date': '2018-01-01',
'date': '2018-01-01',
'invoice_line_ids': [(0, 0, {
@ -651,7 +648,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
})
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id'), [{
'tax_base_amount': 48098.24, # 20000 * 2.82 / 1.1726
'tax_base_amount': -48098.24, # 20000 * 2.82 / 1.1726
'credit': 10100.63, # tax_base_amount * 0.21
}])
@ -660,31 +657,31 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
self.env['res.currency.rate'].create({
'name': '2018-01-01',
'rate': 0.654065014,
'currency_id': self.currency_data['currency'].id,
'currency_id': self.other_currency.id,
'company_id': self.env.company.id,
})
self.currency_data['currency'].rounding = 0.05
self.other_currency.rounding = 0.05
invoice = self._create_invoice([
invoice = self._create_invoice_taxes_per_line([
(5, self.percent_tax_3_incl),
(10, self.percent_tax_3_incl),
(50, self.percent_tax_3_incl),
], currency_id=self.currency_data['currency'], invoice_payment_term_id=self.pay_terms_a)
], currency_id=self.other_currency, invoice_payment_term_id=self.pay_terms_a)
invoice.action_post()
def test_tax_calculation_multi_currency(self):
self.env['res.currency.rate'].create({
'name': '2018-01-01',
'rate': 0.273748,
'currency_id': self.currency_data['currency'].id,
'currency_id': self.other_currency.id,
'company_id': self.env.company.id,
})
self.currency_data['currency'].rounding = 0.01
self.other_currency.rounding = 0.01
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'currency_id': self.currency_data['currency'].id,
'currency_id': self.other_currency.id,
'invoice_date': '2018-01-01',
'date': '2018-01-01',
'invoice_line_ids': [(0, 0, {
@ -696,59 +693,24 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
})
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id'), [{
'tax_base_amount': 567.38, # 155.32 * 1 / (1 / 0.273748)
'balance': -119.16, # tax_base_amount * 0.21
'tax_base_amount': -567.38, # 155.32 * 1 / (1 / 0.273748)
'balance': -119.15, # tax_base_amount * 0.21
}])
self.assertRecordValues(invoice.line_ids.filtered(lambda l: not l.name), [{
'balance': 686.54,
'balance': 686.53,
}])
with Form(invoice) as invoice_form:
invoice_form.currency_id = self.currency_data['currency']
invoice_form.currency_id = self.other_currency
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id'), [{
'tax_base_amount': 567.38,
'balance': -119.16,
'tax_base_amount': -567.38,
'balance': -119.15,
}])
self.assertRecordValues(invoice.line_ids.filtered(lambda l: l.account_id.account_type == 'asset_receivable'), [{
'balance': 686.54,
}])
def test_tax_calculation_multi_currency_100_included_tax(self):
self.env['res.currency.rate'].create({
'name': '2018-01-01',
'rate': 0.273748,
'currency_id': self.currency_data['currency'].id,
'company_id': self.env.company.id,
})
self.currency_data['currency'].rounding = 0.01
tax = self.env['account.tax'].create({
'name': 'tax_100',
'amount_type': 'division',
'amount': 100,
'price_include': True,
})
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'currency_id': self.currency_data['currency'].id,
'invoice_date': '2018-01-01',
'date': '2018-01-01',
'invoice_line_ids': [(0, 0, {
'name': 'xxxx',
'quantity': 1,
'price_unit': 100.00,
'tax_ids': [(6, 0, tax.ids)],
})]
})
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id'), [{
'tax_base_amount': 0.0,
'balance': -365.3, # 100 * (1 / 0.273748)
'balance': 686.53,
}])
def test_fixed_tax_with_zero_price(self):
@ -757,7 +719,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'amount_type': 'fixed',
'amount': 5,
})
invoice = self._create_invoice([
invoice = self._create_invoice_taxes_per_line([
(0, fixed_tax),
])
self.assertRecordValues(invoice.line_ids.filtered('tax_line_id'), [{
@ -770,6 +732,64 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'debit': 0,
}])
def test_tax_repartition_lines_dispatch_amount_1(self):
""" Ensure the tax amount is well dispatched to the repartition lines and the rounding errors are well managed.
The 5% tax is applied on 1 so the total tax amount should be 0.05.
However, there are 10 tax repartition lines of 0.05 * 0.1 = 0.005 that will be rounded to 0.01.
The test checks the tax amount doesn't become 10 * 0.01 = 0.1 instead of 0.05.
"""
base_tax_rep = Command.create({'repartition_type': 'base', 'factor_percent': 100.0})
tax_reps = [Command.create({'repartition_type': 'tax', 'factor_percent': 10.0})] * 10
tax = self.env['account.tax'].create({
'name': "test_tax_repartition_lines_dispatch_amount_1",
'amount_type': 'percent',
'amount': 5.0,
'invoice_repartition_line_ids': [base_tax_rep] + tax_reps,
'refund_repartition_line_ids': [base_tax_rep] + tax_reps,
})
invoice = self._create_invoice_taxes_per_line([(1, tax)])
self.assertRecordValues(invoice, [{
'amount_untaxed': 1.0,
'amount_tax': 0.05,
'amount_total': 1.05,
}])
self.assertRecordValues(
invoice.line_ids.filtered('tax_line_id').sorted('balance'),
[{'balance': -0.01}] * 5,
)
def test_tax_repartition_lines_dispatch_amount_2(self):
""" Ensure the tax amount is well dispatched to the repartition lines and the rounding errors are well managed.
The 5% tax is applied on 1 so the total tax amount should be 0.05 but the distribution is 100 - 100 = 0%.
So at the end, the tax amount is 0.
However, there are 10 positive tax repartition lines of 0.05 * 0.1 = 0.005 that will be rounded to 0.01
and one negative repartition line of 50% and 2 of 25% that will give respectively 0.025 ~= 0.03 and 0.0125 ~= 0.01.
The test checks the tax amount is still zero at the end.
"""
base_tax_rep = Command.create({'repartition_type': 'base', 'factor_percent': 100.0})
plus_tax_reps = [Command.create({'repartition_type': 'tax', 'factor_percent': 10.0})] * 10
neg_tax_reps = [
Command.create({'repartition_type': 'tax', 'factor_percent': percent})
for percent in (-50, -25, -25)
]
tax = self.env['account.tax'].create({
'name': "test_tax_repartition_lines_dispatch_amount_2",
'amount_type': 'percent',
'amount': 5.0,
'invoice_repartition_line_ids': [base_tax_rep] + plus_tax_reps + neg_tax_reps,
'refund_repartition_line_ids': [base_tax_rep] + plus_tax_reps + neg_tax_reps,
})
invoice = self._create_invoice_taxes_per_line([(1, tax)], inv_type='out_refund')
self.assertRecordValues(invoice, [{
'amount_untaxed': 1.0,
'amount_tax': 0.0,
'amount_total': 1.0,
}])
self.assertRecordValues(
invoice.line_ids.filtered('tax_line_id').sorted('balance'),
[{'balance': -0.03}] + [{'balance': -0.01}] * 2 + [{'balance': 0.01}] * 5,
)
def test_tax_line_amount_currency_modification_auto_balancing(self):
date = '2017-01-01'
move = self.env['account.move'].create({
@ -777,10 +797,10 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'date': date,
'partner_id': self.partner_a.id,
'invoice_date': date,
'currency_id': self.currency_data['currency'].id,
'currency_id': self.other_currency.id,
'invoice_payment_term_id': self.pay_terms_a.id,
'invoice_line_ids': [
(0, None, {
Command.create({
'name': self.product_a.name,
'product_id': self.product_a.id,
'product_uom_id': self.product_a.uom_id.id,
@ -788,7 +808,7 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
'price_unit': 1000,
'tax_ids': self.product_a.taxes_id.ids,
}),
(0, None, {
Command.create({
'name': self.product_b.name,
'product_id': self.product_b.id,
'product_uom_id': self.product_b.uom_id.id,
@ -816,3 +836,117 @@ class TestInvoiceTaxes(AccountTestInvoicingCommon):
self.assertRecordValues(receivable_line, [
{'amount_currency': 1410.02, 'balance': 705.02},
])
def test_product_account_tags(self):
product_tag = self.env['account.account.tag'].create({
'name': "Pikachu",
'applicability': 'products',
})
self.product_a.account_tag_ids = [Command.set(product_tag.ids)]
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2025-01-01',
'partner_id': self.partner_a.id,
'invoice_line_ids': [
Command.create({
'name': 'test with product tag',
'product_id': self.product_a.id,
'price_unit': 1000,
'tax_ids': self.percent_tax_1.ids,
}),
Command.create({
'name': 'test with product tag',
'product_id': self.product_b.id,
'price_unit': 100,
'tax_ids': self.percent_tax_1.ids,
}),
Command.create({
'name': 'test without product tag',
'product_id': self.product_b.id,
'price_unit': 200,
'tax_ids': self.percent_tax_2.ids,
}),
]
})
invoice.action_post()
self.assertRecordValues(
invoice.line_ids,
[
{'tax_ids': self.percent_tax_1.ids, 'tax_line_id': False, 'tax_tag_ids': product_tag.ids, 'credit': 1000, 'debit': 0},
{'tax_ids': self.percent_tax_1.ids, 'tax_line_id': False, 'tax_tag_ids': [], 'credit': 100, 'debit': 0},
{'tax_ids': self.percent_tax_2.ids, 'tax_line_id': False, 'tax_tag_ids': [], 'credit': 200, 'debit': 0},
{'tax_ids': [], 'tax_line_id': self.percent_tax_1.id, 'tax_tag_ids': product_tag.ids, 'credit': 210, 'debit': 0},
{'tax_ids': [], 'tax_line_id': self.percent_tax_1.id, 'tax_tag_ids': [], 'credit': 21, 'debit': 0},
{'tax_ids': [], 'tax_line_id': self.percent_tax_2.id, 'tax_tag_ids': [], 'credit': 24, 'debit': 0},
{'tax_ids': [], 'tax_line_id': False, 'tax_tag_ids': [], 'credit': 0, 'debit': 1555},
],
)
def test_fiscal_position_tax_mapping_with_inactive_tax(self):
""" Test that inactive taxes are not mapped by fiscal positions """
fp = self.env['account.fiscal.position'].create({'name': 'FP'})
src_tax = self.company_data['default_tax_sale']
active_tax = self.percent_tax_1.copy({
'fiscal_position_ids': [Command.set(fp.ids)],
'original_tax_ids': [Command.set(src_tax.ids)],
})
self.percent_tax_2.copy({
'active': False,
'fiscal_position_ids': [Command.set(fp.ids)],
'original_tax_ids': [Command.set(src_tax.ids)],
})
self.partner_a.property_account_position_id = fp
move = self.init_invoice('out_invoice', self.partner_a, post=True, products=[self.product])
line = move.invoice_line_ids
self.assertEqual(line.tax_ids, active_tax, f"The tax should be {active_tax.name}, but is is currently {line.tax_ids.name}")
def test_multiple_onchange_product_and_price(self):
"""
This test checks that the totals are computed correctly when an onchange is executed
with "price_unit" before "product_id" in the values.
This test covers a UI issue where the totals were not updated when the price was changed,
then the product and finally the price again.
The issue was only occuring between the change of value and the next save.
That's why the test is using the onchange method directly instead of using a Form.
"""
invoice = self.init_invoice('out_invoice', products=self.product_a)
self.assertEqual(invoice.tax_totals['base_amount'], 1000.0)
self.assertEqual(invoice.tax_totals['total_amount'], 1150.0)
# The onchange is executed directly to simulate the following flow:
# 1) unit price is changed to any value
# 2) product is changed to "Product B"
# 3) unit price is changed to 2000.0
results = invoice.onchange(
{'invoice_line_ids': [Command.update(invoice.invoice_line_ids[0].id, {'price_unit': 2000.0, 'product_id': self.product_b.id})]},
['invoice_line_ids'],
{"invoice_line_ids": {}, 'tax_totals': {}}
)
self.assertEqual(results['value']['tax_totals']['base_amount'], 2000.0)
self.assertEqual(results['value']['tax_totals']['total_amount'], 2600.0)
def test_tax_mapping_with_tax_fiscal_position_set_to_all(self):
"""
A tax without any fiscal positions assigned should be applicable to
any fiscal position.
This test ensures that when a single fiscal position exists and a tax
has no fiscal position restriction, the tax is correctly applied to
invoice lines.
"""
self.env['account.fiscal.position'].search([]).action_archive()
default_tax = self.company_data['default_tax_sale']
self.env['account.fiscal.position'].create({
'name': 'FP',
'auto_apply': True,
'country_id': self.env.company.country_id.id,
'tax_ids': default_tax.ids,
})
self.assertEqual(self.product.taxes_id, default_tax)
default_tax.fiscal_position_ids = False
self.partner_a.country_id = self.env.company.country_id.id
move = self._create_invoice_one_line(product_id=self.product, partner_id=self.partner_a, post=True)
line = move.invoice_line_ids
self.assertEqual(line.tax_ids, default_tax)