178 lines
10 KiB
Python
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
|