# -*- coding: utf-8 -*- # pylint: disable=C0326 from odoo.addons.l10n_mx_edi.tests.common import TestMxEdiCommon from odoo.addons.account_reports.tests.common import TestAccountReportsCommon from odoo import fields, Command from odoo.tests import tagged from odoo.exceptions import RedirectWarning from datetime import datetime from freezegun import freeze_time from pytz import timezone @tagged('post_install_l10n', 'post_install', '-at_install') class TestL10nMXTrialBalanceReport(TestMxEdiCommon, TestAccountReportsCommon): @classmethod def setUpClass(cls): super().setUpClass() # Entries in 2020 to test initial balance cls.move_2020_01 = cls.env['account.move'].create({ 'move_type': 'entry', 'date': fields.Date.to_date('2020-01-01'), 'journal_id': cls.company_data['default_journal_misc'].id, 'line_ids': [ Command.create({'debit': 1000.0, 'credit': 0.0, 'account_id': cls.company_data['default_account_payable'].id}), Command.create({'debit': 0.0, 'credit': 1000.0, 'account_id': cls.company_data['default_account_revenue'].id}), ] }) cls.move_2020_02 = cls.env['account.move'].create({ 'move_type': 'entry', 'date': fields.Date.to_date('2020-02-01'), 'journal_id': cls.company_data['default_journal_misc'].id, 'line_ids': [ Command.create( {'debit': 500.0, 'credit': 0.0, 'account_id': cls.company_data['default_account_expense'].id}), Command.create( {'debit': 0.0, 'credit': 500.0, 'account_id': cls.company_data['default_account_revenue'].id}), ] }) (cls.move_2020_01 + cls.move_2020_02).action_post() # Entries in 2021 to test report for a specific financial year cls.move_2021_01 = cls.env['account.move'].create({ 'move_type': 'entry', 'date': fields.Date.to_date('2021-06-01'), 'journal_id': cls.company_data['default_journal_misc'].id, 'line_ids': [ Command.create( {'debit': 250.0, 'credit': 0.0, 'account_id': cls.company_data['default_account_expense'].id}), Command.create( {'debit': 0.0, 'credit': 250.0, 'account_id': cls.company_data['default_account_revenue'].id}), ] }) cls.move_2021_02 = cls.env['account.move'].create({ 'move_type': 'entry', 'date': fields.Date.to_date('2021-08-01'), 'journal_id': cls.company_data['default_journal_misc'].id, 'line_ids': [ Command.create( {'debit': 75.0, 'credit': 0.0, 'account_id': cls.company_data['default_account_payable'].id}), Command.create( {'debit': 0.0, 'credit': 75.0, 'account_id': cls.company_data['default_account_revenue'].id}), ] }) (cls.move_2021_01 + cls.move_2021_02).action_post() # Special cases: codes with extra levels from the default COA and dotted account names cls.extra_deep_code = cls.env["account.account"].create( { "name": "Extra deep code", "account_type": "liability_current", "code": "205.06.01.001", "reconcile": True, } ) cls.dotted_name = cls.env["account.account"].create( { "name": "Dotted name C.V.", "account_type": "liability_current", "code": "205.06.02", "reconcile": True, } ) cls.extra_deep_code_move = cls.env["account.move"].create( { "move_type": "entry", "date": fields.Date.to_date("2021-06-01"), "journal_id": cls.company_data["default_journal_misc"].id, "line_ids": [ Command.create( { "debit": 400.0, "credit": 0.0, "account_id": cls.dotted_name.id, } ), Command.create( { "debit": 0.0, "credit": 400.0, "account_id": cls.extra_deep_code.id, } ), ], } ) cls.dotted_name_move = cls.env["account.move"].create( { "move_type": "entry", "date": fields.Date.to_date("2021-06-01"), "journal_id": cls.company_data["default_journal_misc"].id, "line_ids": [ Command.create( { "debit": 50.0, "credit": 0.0, "account_id": cls.extra_deep_code.id, } ), Command.create( { "debit": 0.0, "credit": 50.0, "account_id": cls.dotted_name.id, } ), ], } ) (cls.extra_deep_code_move + cls.dotted_name_move).action_post() cls.report = cls.env.ref('account_reports.trial_balance_report') @classmethod def setup_company_data(cls, company_name, chart_template=None, **kwargs): # OVERRIDE account mx_country_id = cls.env.ref('base.mx').id return super().setup_company_data(company_name, chart_template=chart_template, country_id=mx_country_id, **kwargs) def test_generate_coa_xml(self): """ This test will generate a COA report and verify that every account with an entry in the selected period has been there. CodAgrup corresponds to Account Group code NumCta corresponds to Account Group code Desc corresponds to Account Group Name Nivel corresponds to Hierarchy Level Natur corresponds to type of account (Debit or Credit) Available values for "Natur": D = Debit Account A = Credit Account Unaffected Earnings account is not include in this report because it's custom Odoo account. """ expected_coa_xml = b""" """ frozen_today = datetime(year=2018, month=1, day=1, hour=0, minute=0, second=0, tzinfo=timezone('utc')) options = self._generate_options(self.report, '2021-01-01', '2021-12-31') with freeze_time(frozen_today): coa_report = self.env[self.report.custom_handler_model_name].with_context(skip_xsd=True).action_l10n_mx_generate_coa_sat_xml(options)['file_content'] self.assertXmlTreeEqual( self.get_xml_tree_from_string(coa_report), self.get_xml_tree_from_string(expected_coa_xml), ) def test_generate_sat_xml(self): """ This test will generate a SAT report and verify that every account present in the trial balance (except unaffected earnings account) is present in the xml. SaldoIni corresponds to Initial Balance SaldoFin corresponds to End Balance Debe corresponds to Debit in the current period Haber corresponds to Credit in the current period NumCta corresponds to Account Group code """ expected_sat_xml = b""" """ frozen_today = datetime(year=2018, month=1, day=1, hour=0, minute=0, second=0, tzinfo=timezone('utc')) options = self._generate_options(self.report, '2021-01-01', '2021-12-31') with freeze_time(frozen_today): sat_report = self.env[self.report.custom_handler_model_name].with_context(skip_xsd=True).action_l10n_mx_generate_sat_xml(options)['file_content'] self.assertXmlTreeEqual( self.get_xml_tree_from_string(sat_report), self.get_xml_tree_from_string(expected_sat_xml), ) def test_generate_coa_xml_without_tag(self): """This test verifies that all accounts present in the trial balance have a Debit or a Credit balance account tag""" self.company_data['default_account_payable'].tag_ids = [Command.clear()] options = self._generate_options(self.report, '2021-01-01', '2021-12-31') with self.assertRaises(RedirectWarning): self.env[self.report.custom_handler_model_name].action_l10n_mx_generate_coa_sat_xml(options) def test_generate_coa_xml_with_too_much_tag(self): """This test verifies that all accounts present in the trial balance have exactly one Debit or Credit balance account tag""" self.company_data['default_account_payable'].tag_ids = self.env.ref('l10n_mx.tag_debit_balance_account') + self.env.ref('l10n_mx.tag_credit_balance_account') options = self._generate_options(self.report, '2021-01-01', '2021-12-31') with self.assertRaises(RedirectWarning): self.env[self.report.custom_handler_model_name].action_l10n_mx_generate_coa_sat_xml(options) def test_generate_coa_xml_with_too_much_tag_in_group(self): """This test verifies that all accounts present in the same group have exactly one Debit or Credit balance account tag""" self.company_data['default_account_receivable'].tag_ids = self.env.ref('l10n_mx.tag_credit_balance_account') options = self._generate_options(self.report, '2021-01-01', '2021-12-31') with self.assertRaises(RedirectWarning): self.env[self.report.custom_handler_model_name].action_l10n_mx_generate_coa_sat_xml(options) def test_generate_coa_xml_with_too_much_tag_in_parent(self): """This test verifies that all account groups in the same parent have the same account tag""" self.company_data['default_account_tax_purchase'].tag_ids = self.env.ref('l10n_mx.tag_credit_balance_account') options = self._generate_options(self.report, '2021-01-01', '2021-12-31') with self.assertRaises(RedirectWarning): self.env[self.report.custom_handler_model_name].action_l10n_mx_generate_coa_sat_xml(options) def test_mx_trial_balance(self): """ This test will test the Mexican Trial Balance (with and without the hierarchy) """ # Testing the report without hierarchy options = self._generate_options(self.report, '2021-01-01', '2021-12-31', {'hierarchy': False, 'unfold_all': True}) self.assertLinesValues( self.report._get_lines(options), [ 0, 1, 2, 3, 4, 5, 6], [ ('201.01.01 National suppliers', 1000.0, 0.0, 75.0, 0.0, 1075.0, 0.0), ('205.06.01.001 Extra deep code', 0.0, 0.0, 50.0, 400.0, 0.0, 350.0), ('205.06.02 Dotted name C.V.', 0.0, 0.0, 400.0, 50.0, 350.0, 0.0), ('401.01.01 Sales and/or services taxed at the general rate', 0.0, 0.0, 0.0, 325.0, 0.0, 325.0), ('601.84.01 Other overheads', 0.0, 0.0, 250.0, 0.0, 250.0, 0.0), ('999999 Undistributed Profits/Losses', 0.0, 1000.0, 0.0, 0.0, 0.0, 1000.0), ('Total', 1000.0, 1000.0, 775.0, 775.0, 1675.0, 1675.0), ], options, ) # Testing the report with hierarchy options['hierarchy'] = True self.assertLinesValues( self.report._get_lines(options), [ 0, 1, 2, 3, 4, 5, 6], [ ('2 Passive', 1000.0, 0.0, 525.0, 450.0, 1425.0, 350.0), ('201 Suppliers', 1000.0, 0.0, 75.0, 0.0, 1075.0, 0.0), ('201.01 National suppliers', 1000.0, 0.0, 75.0, 0.0, 1075.0, 0.0), ('201.01.01 National suppliers', 1000.0, 0.0, 75.0, 0.0, 1075.0, 0.0), ('205 Short-term sundry creditors', 0.0, 0.0, 450.0, 450.0, 350.0, 350.0), ('205.06 Other short-term sundry creditors', 0.0, 0.0, 450.0, 450.0, 350.0, 350.0), ('205.06.01.001 Extra deep code', 0.0, 0.0, 50.0, 400.0, 0.0, 350.0), ('205.06.02 Dotted name C.V.', 0.0, 0.0, 400.0, 50.0, 350.0, 0.0), ('4 Income', 0.0, 0.0, 0.0, 325.0, 0.0, 325.0), ('401 Income', 0.0, 0.0, 0.0, 325.0, 0.0, 325.0), ('401.01 Sales and/or services taxed at the general rate', 0.0, 0.0, 0.0, 325.0, 0.0, 325.0), ('401.01.01 Sales and/or services taxed at the general rate', 0.0, 0.0, 0.0, 325.0, 0.0, 325.0), ('6 Expenditure', 0.0, 0.0, 250.0, 0.0, 250.0, 0.0), ('601 Overheads', 0.0, 0.0, 250.0, 0.0, 250.0, 0.0), ('601.84 Other overheads', 0.0, 0.0, 250.0, 0.0, 250.0, 0.0), ('601.84.01 Other overheads', 0.0, 0.0, 250.0, 0.0, 250.0, 0.0), ('(No Group)', 0.0, 1000.0, 0.0, 0.0, 0.0, 1000.0), ('999999 Undistributed Profits/Losses', 0.0, 1000.0, 0.0, 0.0, 0.0, 1000.0), ('Total', 1000.0, 1000.0, 775.0, 775.0, 1675.0, 1675.0), ], options, )