Odoo18-Base/addons/account/tests/test_account_tax.py
2025-01-06 10:57:38 +07:00

245 lines
9.9 KiB
Python

# -*- coding: utf-8 -*-
from odoo import Command
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests import tagged
from odoo.exceptions import UserError
@tagged('post_install', '-at_install')
class TestAccountTax(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.company_data_2 = cls.setup_other_company()
@classmethod
def default_env_context(cls):
# OVERRIDE
return {}
def set_up_and_use_tax(self):
self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2023-01-01',
'invoice_line_ids': [
Command.create({
'name': 'invoice_line',
'quantity': 1.0,
'price_unit': 100.0,
'tax_ids': [Command.set(self.company_data['default_tax_sale'].ids)],
}),
],
})
# Create two lines after creating the move so that those lines are not used in the move
self.company_data['default_tax_sale'].write({
'invoice_repartition_line_ids': [
Command.create({'repartition_type': 'tax', 'factor_percent': 0.0}),
],
'refund_repartition_line_ids': [
Command.create({'repartition_type': 'tax', 'factor_percent': 0.0}),
],
})
self.flush_tracking()
self.assertTrue(self.company_data['default_tax_sale'].is_used)
def flush_tracking(self):
""" Force the creation of tracking values. """
self.env.flush_all()
self.cr.flush()
def test_changing_tax_company(self):
''' Ensure you can't change the company of an account.tax if there are some journal entries '''
# Avoid duplicate key value violates unique constraint "account_tax_name_company_uniq".
self.company_data['default_tax_sale'].name = 'test_changing_account_company'
self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2019-01-01',
'invoice_line_ids': [
(0, 0, {
'name': 'invoice_line',
'quantity': 1.0,
'price_unit': 100.0,
'tax_ids': [(6, 0, self.company_data['default_tax_sale'].ids)],
}),
],
})
with self.assertRaises(UserError), self.cr.savepoint():
self.company_data['default_tax_sale'].company_id = self.company_data_2['company']
def test_logging_of_tax_update_when_tax_is_used(self):
""" Modifications of a used tax should be logged. """
self.set_up_and_use_tax()
self.company_data['default_tax_sale'].write({
'name': self.company_data['default_tax_sale'].name + ' MODIFIED',
'amount': 21,
'amount_type': 'fixed',
'type_tax_use': 'purchase',
'price_include_override': 'tax_included',
'include_base_amount': True,
'is_base_affected': False,
})
self.flush_tracking()
self.assertEqual(len(self.company_data['default_tax_sale'].message_ids), 1,
"Only 1 message should have been created when updating all the values.")
# There are 7 tracked values in account.tax and we update each of them, each on should be included in the message
self.assertEqual(len(self.company_data['default_tax_sale'].message_ids.tracking_value_ids), 7,
"The number of updated value should be 7.")
def test_logging_of_repartition_lines_addition_when_tax_is_used(self):
""" Adding repartition lines in a used tax should be logged. """
self.set_up_and_use_tax()
self.company_data['default_tax_sale'].write({
'invoice_repartition_line_ids': [
Command.create({'repartition_type': 'tax', 'factor_percent': -100.0}),
],
'refund_repartition_line_ids': [
Command.create({'repartition_type': 'tax', 'factor_percent': -100.0}),
],
})
self.flush_tracking()
previews = self.company_data['default_tax_sale'].message_ids.mapped('preview')
self.assertIn(
"New Invoice repartition line 4: -100.0 (Factor Percent) None (Account) None (Tax Grids) False (Use in tax closing)",
previews
)
self.assertIn(
"New Refund repartition line 4: -100.0 (Factor Percent) None (Account) None (Tax Grids) False (Use in tax closing)",
previews
)
def test_logging_of_repartition_lines_update_when_tax_is_used(self):
""" Updating repartition lines in a used tax should be logged. """
self.set_up_and_use_tax()
last_invoice_rep_line = self.company_data['default_tax_sale'].invoice_repartition_line_ids\
.filtered(lambda tax_rep: not tax_rep.factor_percent)
last_refund_rep_line = self.company_data['default_tax_sale'].refund_repartition_line_ids\
.filtered(lambda tax_rep: not tax_rep.factor_percent)
self.company_data['default_tax_sale'].write({
"invoice_repartition_line_ids": [
Command.update(last_invoice_rep_line.id, {
'factor_percent': -100,
'tag_ids': [Command.create({'name': 'TaxTag12345'})]
}),
],
"refund_repartition_line_ids": [
Command.update(last_refund_rep_line.id, {
'factor_percent': -100,
'account_id': self.company_data['default_account_tax_purchase'].id,
}),
],
})
self.flush_tracking()
previews = self.company_data['default_tax_sale'].message_ids.mapped('preview')
self.assertIn("Invoice repartition line 3: 0.0 -100.0 (Factor Percent) None ['TaxTag12345'] (Tax Grids)", previews)
self.assertIn("Refund repartition line 3: 0.0 -100.0 (Factor Percent) None 131000 Tax Paid (Account) False True (Use in tax closing)", previews)
def test_logging_of_repartition_lines_reordering_when_tax_is_used(self):
""" Reordering repartition lines in a used tax should be logged. """
self.set_up_and_use_tax()
last_invoice_rep_line = self.company_data['default_tax_sale'].invoice_repartition_line_ids\
.filtered(lambda tax_rep: not tax_rep.factor_percent)
last_refund_rep_line = self.company_data['default_tax_sale'].refund_repartition_line_ids\
.filtered(lambda tax_rep: not tax_rep.factor_percent)
self.company_data['default_tax_sale'].write({
"invoice_repartition_line_ids": [
Command.update(last_invoice_rep_line.id, {'sequence': 0}),
],
"refund_repartition_line_ids": [
Command.update(last_refund_rep_line.id, {'sequence': 0}),
],
})
self.flush_tracking()
previews = self.company_data['default_tax_sale'].message_ids.mapped('preview')
self.assertIn("Invoice repartition line 1: 100.0 0.0 (Factor Percent)", previews)
self.assertIn("Invoice repartition line 3: 0.0 100.0 (Factor Percent) None 251000 Tax Received (Account) False True (Use in tax closing)", previews)
def test_logging_of_repartition_lines_removal_when_tax_is_used(self):
""" Deleting repartition lines in a used tax should be logged. """
self.set_up_and_use_tax()
last_invoice_rep_line = self.company_data['default_tax_sale'].invoice_repartition_line_ids.sorted(key=lambda r: r.sequence)[-1]
last_refund_rep_line = self.company_data['default_tax_sale'].refund_repartition_line_ids.sorted(key=lambda r: r.sequence)[-1]
self.company_data['default_tax_sale'].write({
"invoice_repartition_line_ids": [
Command.delete(last_invoice_rep_line.id),
],
"refund_repartition_line_ids": [
Command.delete(last_refund_rep_line.id),
],
})
self.flush_tracking()
previews = self.company_data['default_tax_sale'].message_ids.mapped('preview')
self.assertIn(
"Removed Invoice repartition line 3: 0.0 (Factor Percent) None (Account) None (Tax Grids) False (Use in tax closing)",
previews
)
self.assertIn(
"Removed Refund repartition line 3: 0.0 (Factor Percent) None (Account) None (Tax Grids) False (Use in tax closing)",
previews
)
def test_tax_is_used_when_in_transactions(self):
''' Ensures that a tax is set to used when it is part of some transactions '''
# Account.move is one type of transaction
tax_invoice = self.env['account.tax'].create({
'name': 'test_is_used_invoice',
'amount': '100',
})
self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2023-01-01',
'invoice_line_ids': [
Command.create({
'name': 'invoice_line',
'quantity': 1.0,
'price_unit': 100.0,
'tax_ids': [Command.set(tax_invoice.ids)],
}),
],
})
tax_invoice.invalidate_model(fnames=['is_used'])
self.assertTrue(tax_invoice.is_used)
# Account.reconcile is another of transaction
tax_reconciliation = self.env['account.tax'].create({
'name': 'test_is_used_reconcilition',
'amount': '100',
})
self.env['account.reconcile.model'].create({
'name': "test_tax_is_used",
'rule_type': 'writeoff_suggestion',
'auto_reconcile': False,
'line_ids': [Command.create({
'account_id': self.company_data['default_account_revenue'].id,
'tax_ids': [Command.set(tax_reconciliation.ids)],
})],
})
tax_reconciliation.invalidate_model(fnames=['is_used'])
self.assertTrue(tax_reconciliation.is_used)