Files
enterprise-addons/account_reports/tests/test_all_reports_generation.py
T

178 lines
10 KiB
Python

# -*- coding: utf-8 -*-
import json
from collections import defaultdict
from unittest.mock import patch
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests.common import tagged
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestAllReportsGeneration(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
# do not disable buttons because of multiple companies selected
cls.env = cls.env(context={'allowed_company_ids': cls.env.company.ids})
cls.setup_other_currency('EUR')
cls.reports = cls.env['account.report'].with_context(active_test=False).search([])
# Make the reports always available, so that they don't clash with the company's country
cls.reports.availability_condition = 'always'
# We keep the country set on each of these reports, so that we can load the proper test data when testing exports
def test_open_all_reports(self):
# 'unfold_all' is forced on all reports (even if they don't support it), so that we really open it entirely
self.reports.filter_unfold_all = True
for report in self.reports:
with self.subTest(report=report.name, country=report.country_id.name):
# 'report_id' key is forced so that we don't open a variant when calling a root report
options = report.get_options({'selected_variant_id': report.id, 'unfold_all': True})
if report.use_sections:
self.assertNotEqual(options['report_id'], report.id, "Composite reports should always reroute.")
self.env['account.report'].browse(options['report_id']).get_report_information(options)
else:
report.get_report_information(options)
def test_generate_all_export_files(self):
# Test values for the fields that become mandatory when doing exports on the reports, depending on the country
l10n_pl_reports_tax_office = self.env.ref('l10n_pl.pl_tax_office_0215', raise_if_not_found=False)
l10n_bd_corporate_tax_liability = self.env['account.account'].search([('account_type', '=', 'liability_current')], limit=1)
l10n_ae_liability_account = self.env['account.account'].search([('account_type', '=', 'liability_current')], limit=1)
l10n_cz_reports_tax_office = self.env.ref('l10n_cz.tax_office_1', raise_if_not_found=False)
l10n_ar_activity_default = self.env.ref('l10n_ar_reports_simple.activity_620100', raise_if_not_found=False)
company_test_values = {
'LU': {'vat': 'LU12345613'},
'BR': {'vat': '01234567891251'},
'AR': {'vat': '30714295698', 'l10n_ar_arca_activity_id': l10n_ar_activity_default and l10n_ar_activity_default.id},
'AU': {'vat': '11225459588', 'street': 'Arrow Street', 'zip': '1348', 'city': 'Starling City', 'state_id': self.env.ref('base.state_au_1').id},
'DE': {'vat': 'DE123456788', 'l10n_de_stnr': '151/815/08156', 'state_id': self.env.ref('base.state_de_th').id},
'NO': {'vat': 'NO123456785', 'l10n_no_bronnoysund_number': '987654325'},
'PL': {
'vat': 'PL1234567883',
'l10n_pl_reports_tax_office_id': l10n_pl_reports_tax_office and l10n_pl_reports_tax_office.id,
},
'BD': {'l10n_bd_corporate_tax_liability': l10n_bd_corporate_tax_liability, 'l10n_bd_corporate_tax_expense': l10n_bd_corporate_tax_liability},
'AE': {'l10n_ae_tax_report_liabilities_account': l10n_ae_liability_account, 'l10n_ae_tax_report_expenses_account': l10n_ae_liability_account, 'l10n_ae_tax_report_asset_account': l10n_ae_liability_account},
'CZ': {'l10n_cz_tax_office_id': l10n_cz_reports_tax_office and l10n_cz_reports_tax_office.id},
'SK': {'zip': '010 01', 'city': 'Žilina', 'income_tax_id': '9999999999', 'company_registry': '47686065', 'l10n_sk_nace_code': '01110'},
}
# ecdf_prefix and matr_number only exist in enterprise
if self.env['ir.module.module']._get('l10n_lu_reports').state == 'installed':
company_test_values['LU'].update({
'ecdf_prefix': '1234AB',
'matr_number': '1111111111111',
})
partner_test_values = {
'AR': {'l10n_latam_identification_type_id': (self.env.ref('l10n_ar.it_cuit', raise_if_not_found=False) or {'id': None})['id']},
}
# Some root reports are made for just one country and require test fields to be set the right way to generate their exports properly.
# Since they are root reports and are always available, they normally have no country set; we assign one here (only for the ones requiring it)
reports_forced_countries = [
('AU', 'l10n_au_reports.tpar_report'),
]
for country_code, report_ref in reports_forced_countries:
country = self.env['res.country'].search([('code', '=', country_code)], limit=1)
report = self.env.ref(report_ref, raise_if_not_found=False)
if report:
report.country_id = country
# Check buttons of every report
for report in self.reports:
with self.subTest(report=report.name, country=report.country_id.name):
# Setup some generic data on the company that could be needed for some file export
self.env.company.write({
'vat': "VAT123456789",
'email': "dummy@email.com",
'phone': "01234567890",
'company_registry': '42',
**company_test_values.get(report.country_id.code, {}),
})
self.env.company.partner_id.write(partner_test_values.get(report.country_id.code, {}))
options = report.get_options({'selected_variant_id': report.id, '_running_export_test': True})
if report.use_sections:
self.assertNotEqual(options['report_id'], report.id, "Composite reports should always reroute.")
for option_button in options['buttons']:
if option_button['name'] in ('PDF', 'Download Excel'): # keep "Copy to Documents" and other actions
# TODO remove me
# This test seems to have some trouble on runbot. It is running for way longer than
# locally. Freeze is coming, explanation are missing... Sorry 😟
continue
if report.custom_handler_model_name == 'l10n_fr.report.handler' and option_button['name'] == 'EDI VAT':
# This button requires a tax closing entry to be called. It doesn't make sense to test this button
# without a tax closing entry, so we will exclude it from testing here.
continue
with self.subTest(button=option_button['name']):
with self.allow_pdf_render():
if not option_button.get('client_tag'):
action_dict = report.dispatch_report_action(
options,
option_button['action'],
action_param=option_button.get('action_param'),
on_sections_source=True,
)
if action_dict['type'] == 'ir_actions_account_report_download':
file_gen_res = report.dispatch_report_action(
json.loads(action_dict['data']['options']),
action_dict['data']['file_generator'],
on_sections_source=True,
)
self.assertEqual(
set(file_gen_res.keys()), {'file_name', 'file_content', 'file_type'},
"File generator's result should always contain the same 3 keys."
)
# Unset the test values, in case they are used in conditions to define custom behaviors
self.env.company.write({
field_name: None
for field_name in company_test_values.get(report.country_id.code, {}).keys()
})
self.env.company.partner_id.write({
field_name: None
for field_name in partner_test_values.get(report.country_id.code, {}).keys()
})
def test_custom_engines_related_groupby(self):
blacklist_xmlids = [
'account_reports.account_financial_report_executivesummary_avdebt0_ndays',
'account_reports.account_financial_report_executivesummary_avgcre0_ndays',
'account_reports.last_statement_balance_amount',
'account_reports.last_statement_balance_forced_currency_amount',
]
custom_engine_expressions = self.env['account.report.expression'].search([
('engine', '=', 'custom'),
('id', 'not in', tuple(self.env['ir.model.data']._xmlid_to_res_id(xmlid) for xmlid in blacklist_xmlids)),
])
expressions_per_engine = defaultdict(lambda: self.env['account.report.expression'])
for expression in custom_engine_expressions:
expressions_per_engine[(expression.report_line_id.report_id, expression.formula)] += expression
for (report, _formula), expressions in expressions_per_engine.items():
with self.subTest(report=report.name):
options = report.get_options({})
# Remove aggregations and external value expressions from those report lines, so that we always can set a groupby on the line
(expressions.report_line_id.expression_ids.filtered(lambda x: x.engine in ('aggregation', 'external'))).unlink()
expressions.report_line_id.user_groupby = 'account_code' # account_code is a non-stored related field on aml
self.env.flush_all()
report._compute_expression_totals_for_each_column_group(expressions, options, groupby_to_expand='account_code')
# This computation fill fail if the custom engine forgot to handle such groupby, typically via a call to _field_to_sql