1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/account_reports/tests/test_report_engines.py
2024-12-10 09:04:09 +07:00

1833 lines
80 KiB
Python

from .common import TestAccountReportsCommon
from odoo import fields, Command
from odoo.tests import tagged
from odoo.tools import frozendict
from unittest.mock import patch
@tagged('post_install', '-at_install')
class TestReportEngines(TestAccountReportsCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
cls.company_data['company'].totals_below_sections = False
cls.garbage_account = cls.env['account.account'].create({
'code': "turlututu",
'name': "turlututu",
'account_type': "asset_current",
})
cls.fake_country = cls.env['res.country'].create({
'name': "L'Île de la Mouche",
'code': 'YY',
})
# -------------------------------------------------------------------------
# HELPERS
# -------------------------------------------------------------------------
def _prepare_test_account_move_line(self, balance, account_code=None, tax_tags=None, date='2020-01-01', **kwargs):
if tax_tags:
tags = self.env['account.account.tag'].search([
('applicability', '=', 'taxes'),
('country_id', '=', self.fake_country.id),
('name', 'in', tax_tags),
])
else:
tags = self.env['account.account.tag']
return {
'account_move_line_values': {
'name': "turlututu",
'account_id': self.garbage_account.id,
**kwargs,
'debit': balance if balance > 0.0 else 0.0,
'credit': -balance if balance < 0.0 else 0.0,
'tax_tag_ids': [Command.set(tags.ids)],
},
'account_move_values': {'date': date},
'account_code': account_code,
}
def _create_test_account_moves(self, test_account_move_line_values_list):
# Create the missing account on-the-fly.
accounts_to_create_by_code = set()
for test_account_move_line_values in test_account_move_line_values_list:
if test_account_move_line_values.get('account_code'):
accounts_to_create_by_code.add(test_account_move_line_values['account_code'])
if accounts_to_create_by_code:
accounts = self.env['account.account'].create([
{
'code': account_code,
'name': account_code,
'account_type': "asset_current",
}
for account_code in accounts_to_create_by_code
])
account_by_code = {x.code: x for x in accounts}
for test_account_move_line_values in test_account_move_line_values_list:
account = account_by_code.get(test_account_move_line_values.get('account_code'))
if account:
test_account_move_line_values['account_move_line_values']['account_id'] = account.id
# Create the journal entries.
to_create = {}
for test_account_move_line_values in test_account_move_line_values_list:
account_move_key = frozendict(test_account_move_line_values['account_move_values'])
account_move_line_values = test_account_move_line_values['account_move_line_values']
account_move_to_create = to_create.setdefault(account_move_key, {
'account_move_values': {'line_ids': []},
'balance': 0.0,
})
account_move_to_create['account_move_values']['line_ids'].append(Command.create(account_move_line_values))
account_move_to_create['balance'] += account_move_line_values['debit'] - account_move_line_values['credit']
account_move_create_list = []
for account_move_dict, account_move_to_create in to_create.items():
open_balance = account_move_to_create['balance']
account_move_values = account_move_to_create['account_move_values']
if not self.env.company.currency_id.is_zero(open_balance):
account_move_values['line_ids'].append(Command.create({
'name': 'open balance',
'account_id': self.garbage_account.id,
'debit': -open_balance if open_balance < 0.0 else 0.0,
'credit': open_balance if open_balance > 0.0 else 0.0,
}))
account_move_create_list.append({
**account_move_dict,
**account_move_values,
})
moves = self.env['account.move'].create(account_move_create_list)
moves.action_post()
return moves
def _prepare_test_external_values(self, value, date, figure_type=False):
field_name = 'text_value' if figure_type == 'string' else 'value'
return {
'name': date,
field_name: value,
'date': date,
}
def _prepare_test_expression(self, formula, label='balance', **kwargs):
return {
'expression_values': {
'label': label,
'formula': formula,
**kwargs,
},
}
def _prepare_test_expression_tax_tags(self, formula, **kwargs):
return self._prepare_test_expression(engine='tax_tags', formula=formula, **kwargs)
def _prepare_test_expression_domain(self, formula, subformula, **kwargs):
return self._prepare_test_expression(engine='domain', formula=formula, subformula=subformula, **kwargs)
def _prepare_test_expression_account_codes(self, formula, **kwargs):
return self._prepare_test_expression(engine='account_codes', formula=formula, **kwargs)
def _prepare_test_expression_external(self, formula, external_value_generators, **kwargs):
return {
**self._prepare_test_expression(engine='external', formula=formula, **kwargs),
'external_value_generators': external_value_generators,
}
def _prepare_test_expression_custom(self, formula, **kwargs):
return self._prepare_test_expression(engine='custom', formula=formula, **kwargs)
def _prepare_test_expression_aggregation(self, formula, subformula=None, column='balance', date_scope=None):
expression_values = {
'label': column,
'engine': 'aggregation',
'formula': formula,
'subformula': subformula,
}
if date_scope:
expression_values['date_scope'] = date_scope
return {
'expression_values': expression_values,
}
def _prepare_test_report_line(self, *expression_generators, **kwargs):
return {
'report_line_values': {
**kwargs,
'expression_ids': [
Command.create({
'date_scope': 'strict_range',
**expression_values['expression_values'],
})
for expression_values in expression_generators
],
},
'expression_generators': expression_generators,
}
def _create_report(self, test_report_line_values_list, columns=None, **kwargs):
if not columns:
columns = ['balance']
# Create a new report
report = self.env['account.report'].create({
'name': "_run_report",
'filter_date_range': True,
'filter_unfold_all': True,
**kwargs,
'column_ids': [
Command.create({
'name': column,
'expression_label': column,
'sequence': i,
})
for i, column in enumerate(columns)
],
'line_ids': [
Command.create({
'name': f"test_line_{i}",
**test_report_line_values['report_line_values'],
'sequence': i,
})
for i, test_report_line_values in enumerate(test_report_line_values_list, start=1)
],
})
# Create the external values
external_values_create_list = []
for report_line, test_report_line_values in zip(report.line_ids, test_report_line_values_list):
for expression, expression_values in zip(report_line.expression_ids, test_report_line_values['expression_generators']):
for external_values in expression_values.get('external_value_generators', []):
external_values_create_list.append({
**external_values,
'target_report_expression_id': expression.id,
})
self.env['account.report.external.value'].create(external_values_create_list)
return report
# -------------------------------------------------------------------------
# TESTS
# -------------------------------------------------------------------------
def test_engine_tax_tags(self):
self.env.company.account_fiscal_country_id = self.fake_country
# Create the report.
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('11'),
groupby='account_id',
)
test_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('222T'),
groupby='account_id',
)
test_line_3 = self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('3333'),
groupby='account_id',
)
report = self._create_report(
[test_line_1, test_line_2, test_line_3],
country_id=self.fake_country.id,
)
# Create the journal entries.
move = self._create_test_account_moves([
self._prepare_test_account_move_line(2000.0, account_code='101001', tax_tags=['+11', '-222T']),
self._prepare_test_account_move_line(1000.0, account_code='101001', tax_tags=['+11', '-222T']),
self._prepare_test_account_move_line(3600.0, account_code='101001', tax_tags=['+222T']),
self._prepare_test_account_move_line(-600.0, account_code='101001', tax_tags=['+222T', '-3333']),
self._prepare_test_account_move_line(-900.0, account_code='101002', tax_tags=['-11']),
self._prepare_test_account_move_line(1500.0, account_code='101002', tax_tags=['+11']),
])
options = self._generate_options(report, '2020-01-01', '2020-01-01', default_options={'unfold_all': True})
report_lines = report._get_lines(options)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report_lines,
[ 0, 1],
[
('test_line_1', 5400.0),
('101001 101001', 3000.0),
('101002 101002', 2400.0),
('test_line_2', 0.0),
('101001 101001', 0.0),
('test_line_3', 600.0),
('101001 101001', 600.0),
],
options,
)
# Check redirection.
expected_redirection_values_list = [
move.line_ids[:2] + move.line_ids[4:6],
move.line_ids[:4],
move.line_ids[3],
]
for report_line, expected_amls in zip(report.line_ids, expected_redirection_values_list):
report_line_dict = [x for x in report_lines if x['name'] == report_line.name][0]
with self.subTest(report_line=report_line.name):
action_dict = report.action_audit_cell(options, self._get_audit_params_from_report_line(options, report_line, report_line_dict))
self.assertEqual(move.line_ids.filtered_domain(action_dict['domain']), expected_amls)
def test_engine_domain(self):
domain = [('account_id.code', '=like', '1%'), ('balance', '<', 0.0)]
# Create the report.
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_domain(domain, 'sum'),
groupby='account_id',
)
test_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_domain(domain, '-sum'),
groupby='account_id',
)
test_line_3 = self._prepare_test_report_line(
self._prepare_test_expression_domain(domain, 'sum_if_neg'),
groupby='account_id',
)
test_line_4 = self._prepare_test_report_line(
self._prepare_test_expression_domain(domain, '-sum_if_neg'),
groupby='account_id',
)
test_line_5 = self._prepare_test_report_line(
self._prepare_test_expression_domain(domain, 'sum_if_pos'),
groupby='account_id',
)
test_line_6 = self._prepare_test_report_line(
self._prepare_test_expression_domain(domain, '-sum_if_pos'),
groupby='account_id',
)
test_line_7 = self._prepare_test_report_line(
self._prepare_test_expression_domain(domain, 'count_rows'),
groupby='account_id',
)
report = self._create_report([test_line_1, test_line_2, test_line_3, test_line_4, test_line_5, test_line_6, test_line_7])
# Create the journal entries.
move = self._create_test_account_moves([
self._prepare_test_account_move_line(2000.0, account_code='101001'),
self._prepare_test_account_move_line(-300.0, account_code='101002'),
self._prepare_test_account_move_line(-600.0, account_code='101003'),
self._prepare_test_account_move_line(-900.0, account_code='101004'),
])
# Check the values.
options = self._generate_options(report, '2020-01-01', '2020-01-01', default_options={'unfold_all': True})
report_lines = report._get_lines(options)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report_lines,
[ 0, 1],
[
('test_line_1', -1800.0),
('101002 101002', -300.0),
('101003 101003', -600.0),
('101004 101004', -900.0),
('test_line_2', 1800.0),
('101002 101002', 300.0),
('101003 101003', 600.0),
('101004 101004', 900.0),
('test_line_3', -1800.0),
('101002 101002', -300.0),
('101003 101003', -600.0),
('101004 101004', -900.0),
('test_line_4', 1800.0),
('101002 101002', 300.0),
('101003 101003', 600.0),
('101004 101004', 900.0),
('test_line_5', 0.0),
('test_line_6', 0.0),
('test_line_7', 3),
('101002 101002', 1),
('101003 101003', 1),
('101004 101004', 1),
],
options,
)
# Check redirection.
expected_amls = move.line_ids.search(domain)
for report_line in report.line_ids:
report_line_dict = [x for x in report_lines if x['name'] == report_line.name][0]
with self.subTest(report_line=report_line.name):
action_dict = report.action_audit_cell(options, self._get_audit_params_from_report_line(options, report_line, report_line_dict))
self.assertEqual(move.line_ids.filtered_domain(action_dict['domain']), expected_amls)
def test_engine_account_codes(self):
# Create test account tags
account_tags = self.env['account.account.tag']._load_records([
{
'xml_id': 'account_reports.account_codes_engine_test_tag1',
'noupdate': True,
'values': {
'name': "account_codes test tag 1",
'applicability': 'accounts',
},
},
{
'xml_id': 'account_reports.account_codes_engine_test_tag2',
'noupdate': True,
'values': {
'name': "account_codes test tag 2",
'applicability': 'accounts',
},
},
])
# Create the report.
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('1'),
groupby='account_id',
)
test_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('1C'),
groupby='account_id',
)
test_line_3 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('1D'),
groupby='account_id',
)
test_line_4 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'-101\(101003)'),
groupby='account_id',
)
test_line_5 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'-101\(101003)C'),
groupby='account_id',
)
test_line_6 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'-101\(101002,101003)'),
groupby='account_id',
)
test_line_7 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('10.'),
groupby='account_id',
)
test_line_8 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('10.20'),
groupby='account_id',
)
test_line_9 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('10.20 - 101 + 101002'),
groupby='account_id',
)
test_line_10 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'10.20 - 101\(101002)'),
groupby='account_id',
)
test_line_11 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'345D\()D'),
groupby='account_id',
)
test_line_12 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'345D\()C'),
groupby='account_id',
)
test_line_13 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(rf'tag(account_reports.account_codes_engine_test_tag1) + tag({account_tags[1].id})'),
groupby='account_id',
)
test_line_14 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'tag(account_reports.account_codes_engine_test_tag1)D'),
groupby='account_id',
)
test_line_15 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(r'tag(account_reports.account_codes_engine_test_tag1)C'),
groupby='account_id',
)
test_line_16 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes(rf'tag(account_reports.account_codes_engine_test_tag1)\(101)D + 101003 + tag({account_tags[1].id})\(101)C'),
groupby='account_id',
)
report = self._create_report([
test_line_1, test_line_2, test_line_3, test_line_4, test_line_5, test_line_6, test_line_7, test_line_8,
test_line_9, test_line_10, test_line_11, test_line_12, test_line_13, test_line_14, test_line_15, test_line_16
])
# Create the journal entries.
move = self._create_test_account_moves([
self._prepare_test_account_move_line(1000.0, account_code='100001'),
self._prepare_test_account_move_line(2000.0, account_code='101001'),
self._prepare_test_account_move_line(-300.0, account_code='101002'),
self._prepare_test_account_move_line(-600.0, account_code='101003'),
self._prepare_test_account_move_line(10000.0, account_code='10.20.0'),
self._prepare_test_account_move_line(10.0, account_code='345D'),
])
# Setup tags on accounts
self.env['account.account'].search([('code', 'in', ('100001', '101001'))]).tag_ids = account_tags[0]
self.env['account.account'].search([('code', 'in', ('10.20.0', '101002'))]).tag_ids = account_tags[1]
# Check the values.
options = self._generate_options(report, '2020-01-01', '2020-01-01', default_options={'unfold_all': True})
report_lines = report._get_lines(options)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report_lines,
[ 0, 1],
[
('test_line_1', 12100.0),
('10.20.0 10.20.0', 10000.0),
('100001 100001', 1000.0),
('101001 101001', 2000.0),
('101002 101002', -300.0),
('101003 101003', -600.0),
('test_line_2', -900.0),
('101002 101002', -300.0),
('101003 101003', -600.0),
('test_line_3', 13000.0),
('10.20.0 10.20.0', 10000.0),
('100001 100001', 1000.0),
('101001 101001', 2000.0),
('test_line_4', -1700.0),
('101001 101001', -2000.0),
('101002 101002', 300.0),
('test_line_5', 300.0),
('101002 101002', 300.0),
('test_line_6', -2000.0),
('101001 101001', -2000.0),
('test_line_7', 10000.0),
('10.20.0 10.20.0', 10000.0),
('test_line_8', 10000.0),
('10.20.0 10.20.0', 10000.0),
('test_line_9', 8600.0),
('10.20.0 10.20.0', 10000.0),
('101001 101001', -2000.0),
('101002 101002', 0.0),
('101003 101003', 600.0),
('test_line_10', 8600.0),
('10.20.0 10.20.0', 10000.0),
('101001 101001', -2000.0),
('101003 101003', 600.0),
('test_line_11', 10.0),
('345D 345D', 10.0),
('test_line_12', 0.0),
('test_line_13', 12700.0),
('10.20.0 10.20.0', 10000.0),
('100001 100001', 1000.0),
('101001 101001', 2000.0),
('101002 101002', -300.0),
('test_line_14', 3000.0),
('100001 100001', 1000.0),
('101001 101001', 2000.0),
('test_line_15', 0.0),
('test_line_16', 400.0),
('100001 100001', 1000.0),
('101003 101003', -600.0),
],
options,
)
# Check redirection.
expected_redirection_values_list = [
move.line_ids[:5],
move.line_ids[:5],
move.line_ids[:5],
move.line_ids[1:3],
move.line_ids[1:3],
move.line_ids[1],
move.line_ids[4],
move.line_ids[4],
move.line_ids[1:5],
move.line_ids[1] + move.line_ids[3:5],
move.line_ids[5],
move.line_ids[5],
]
for report_line, expected_amls in zip(report.line_ids, expected_redirection_values_list):
report_line_dict = [x for x in report_lines if x['name'] == report_line.name][0]
with self.subTest(report_line=report_line.name):
action_dict = report.action_audit_cell(options, self._get_audit_params_from_report_line(options, report_line, report_line_dict))
self.assertEqual(move.line_ids.filtered_domain(action_dict['domain']), expected_amls)
def test_engine_external(self):
# Create the report.
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_external('sum', [
self._prepare_test_external_values(100.0, '2020-01-02'),
self._prepare_test_external_values(200.0, '2020-01-03'),
self._prepare_test_external_values(300.0, '2020-01-03'),
self._prepare_test_external_values(299.999999999, '2020-01-05'),
])
)
test_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_external('most_recent', [
self._prepare_test_external_values(100.0, '2020-01-02'),
self._prepare_test_external_values(200.0, '2020-01-03'),
self._prepare_test_external_values(300.0, '2020-01-03'),
self._prepare_test_external_values(299.999999999, '2020-01-05'),
])
)
report = self._create_report([test_line_1, test_line_2])
# Check the values at multiple dates.
options = self._generate_options(report, '2020-01-01', '2020-01-01')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 0.0),
('test_line_2', 0.0),
],
options,
)
options = self._generate_options(report, '2020-01-02', '2020-01-02')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 100.0),
('test_line_2', 100.0),
],
options,
)
options = self._generate_options(report, '2020-01-03', '2020-01-03')
report_lines = report._get_lines(options)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report_lines,
[ 0, 1],
[
('test_line_1', 500.0),
('test_line_2', 500.0),
],
options,
)
# Check redirection.
for report_line, report_line_dict in zip(report.line_ids, report_lines):
with self.subTest(report_line=report_line.name):
action_dict = report.action_audit_cell(options, self._get_audit_params_from_report_line(options, report_line, report_line_dict))
self.assertRecordValues(
self.env['account.report.external.value'].search(action_dict['domain']),
[
{'date': fields.Date.from_string('2020-01-03')},
{'date': fields.Date.from_string('2020-01-03')},
],
)
options = self._generate_options(report, '2020-01-04', '2020-01-04')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 0.0),
('test_line_2', 0.0),
],
options,
)
options = self._generate_options(report, '2020-01-02', '2020-01-04')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 600.0),
('test_line_2', 500.0),
],
options,
)
# Check redirection.
expected_redirection_values_list = [
[
{'date': fields.Date.from_string('2020-01-02')},
{'date': fields.Date.from_string('2020-01-03')},
{'date': fields.Date.from_string('2020-01-03')},
],
[
{'date': fields.Date.from_string('2020-01-03')},
{'date': fields.Date.from_string('2020-01-03')},
],
]
for report_line, report_line_dict, expected_values in zip(report.line_ids, report_lines, expected_redirection_values_list):
with self.subTest(report_line=report_line.name):
action_dict = report.action_audit_cell(options, self._get_audit_params_from_report_line(options, report_line, report_line_dict))
self.assertRecordValues(
self.env['account.report.external.value'].search(action_dict['domain']),
expected_values,
)
options = self._generate_options(report, '2020-01-03', '2020-01-05')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 800.0),
('test_line_2', 300.0),
],
options,
)
def test_engine_external_editable_percentage(self):
# Create the report.
test_rounding_4 = self._prepare_test_report_line(
self._prepare_test_expression_external(
'most_recent', [
self._prepare_test_external_values(10.1254, '2020-01-01'),
self._prepare_test_external_values(5, '2020-01-02'),
], figure_type='percentage', subformula='editable;rounding=4',
),
code='TEST_PERCENTAGE'
)
test_rounding_2 = self._prepare_test_report_line(
self._prepare_test_expression_external(
'most_recent', [
self._prepare_test_external_values(10.12, '2020-01-01'),
self._prepare_test_external_values(5, '2020-01-02'),
], figure_type='percentage', subformula='editable;rounding=2',
)
)
test_percentage_aggregate = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('10000 * TEST_PERCENTAGE.balance'),
)
test_float = self._prepare_test_report_line(
self._prepare_test_expression_external(
'most_recent', [
self._prepare_test_external_values(10.12, '2020-01-01'),
self._prepare_test_external_values(5, '2020-01-02'),
], figure_type='float', subformula='editable;rounding=2',
)
)
report = self._create_report([test_rounding_4, test_rounding_2, test_percentage_aggregate, test_float])
# Check the values at multiple dates.
options = self._generate_options(report, '2020-01-01', '2020-01-01')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[0, 1],
[
('test_line_1', '10.1254%'),
('test_line_2', '10.12%'),
('test_line_3', 101254),
('test_line_4', '10.12'),
],
options,
)
options = self._generate_options(report, '2020-01-02', '2020-01-02')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[0, 1],
[
('test_line_1', '5.0000%'),
('test_line_2', '5.00%'),
('test_line_3', 50000),
('test_line_4', '5.00'),
],
options,
)
def test_engine_custom(self):
# Create the report.
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_custom('_custom_engine_test', subformula='sum'),
groupby='account_id',
)
report = self._create_report([test_line_1])
# Create the journal entries.
self._create_test_account_moves([
self._prepare_test_account_move_line(2000.0, account_code='101001'),
self._prepare_test_account_move_line(-300.0, account_code='101002'),
])
# Check the values.
def _custom_engine_test(expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
domain = [('account_id.code', '=', '101002')]
domain_key = str(domain)
formulas_dict = {domain_key: expressions}
domain_result = report._compute_formula_batch_with_engine_domain(
options, date_scope, formulas_dict, current_groupby, next_groupby,
offset=offset, limit=limit,
)
return list(domain_result.values())[0]
orig_get_custom_report_function = report._get_custom_report_function
def get_custom_report_function(_report, function_name, prefix):
if function_name == '_custom_engine_test':
return _custom_engine_test
return orig_get_custom_report_function(function_name, prefix)
with patch.object(type(report), '_get_custom_report_function', get_custom_report_function):
options = self._generate_options(report, '2020-01-01', '2020-01-01')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', -300.0),
('101002 101002', -300.0),
],
options,
)
def test_engine_aggregation(self):
self.env.company.account_fiscal_country_id = self.fake_country
self.currency_data['currency'].name = 'GOL'
# Test division by zero.
test1 = self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('11', label='tax_tags'),
self._prepare_test_expression_domain([('account_id.code', '=', '101002')], 'sum', label='domain'),
self._prepare_test_expression_external('sum', [self._prepare_test_external_values(100.0, '2020-01-01')], label='external'),
self._prepare_test_expression_aggregation('test1.tax_tags + test1.domain', column='aggregation'),
self._prepare_test_expression_aggregation('test1.tax_tags / 0'),
self._prepare_test_expression_external('sum', [self._prepare_test_external_values(100.47, '2020-01-01')], label='external_decimal'),
name='test1', code='test1',
)
# Test if_(above|below|between) operators.
test2_1 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.tax_tags', subformula='if_above(USD(0))'),
name='test2_1', code='test2_1',
)
test2_2 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.tax_tags', subformula='if_above(USD(1999.9999999))'),
name='test2_2', code='test2_2',
)
test2_3 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.tax_tags', subformula='if_above(USD(2500.0))'),
name='test2_3', code='test2_3',
)
test2_4 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.tax_tags', subformula='if_above(GOL(3600.0))'),
name='test2_4', code='test2_4',
)
test3_1 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.domain', subformula='if_below(USD(0))'),
name='test3_1', code='test3_1',
)
test3_2 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.domain', subformula='if_below(USD(-300.00001))'),
name='test3_2', code='test3_2',
)
test3_3 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.domain', subformula='if_below(USD(- 350))'),
name='test3_3', code='test3_3',
)
test4_1 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.tax_tags + test1.domain', subformula='if_between(USD(0), USD(2000))'),
name='test4_1', code='test4_1',
)
test4_2 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.tax_tags + test1.domain', subformula='if_between(GOL(0), GOL(3000))'),
name='test4_2', code='test4_2',
)
# Test line code recognition.
test5 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('101003', label='account_codes'),
self._prepare_test_expression_aggregation('test1.tax_tags + 9999.account_codes'),
name='9999', code='9999',
)
# Test mathematical operators.
test6 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation(
'(test1.tax_tags + (2 * test1.domain) + 100.0) / (9999.account_codes)'
),
name='test6', code='test6',
)
# Test other date scope
test7 = self._prepare_test_report_line(
self._prepare_test_expression_domain(
[('account_id.code', '=', '101002')],
'sum',
label='domain',
date_scope='to_beginning_of_period',
),
self._prepare_test_expression_aggregation('test7.domain'),
name='test7', code='test7',
)
# Test exponential notation
test9 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation(
'(test1.tax_tags + (2 * test1.domain) + 100.0 + 1.752e-17) / (9999.account_codes)'
),
name='test9', code='test9',
)
# Test 'round' subformula
test10_1 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external_decimal', subformula='round(0)'),
name='test10_1', code='test10_1',
)
test10_2 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external_decimal', subformula='round(1)'),
name='test10_2', code='test10_2',
)
test10_3 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external_decimal', subformula='round(3)'),
name='test10_3', code='test10_3',
)
# Test if_other_expr_above / if_other_expr_below
test11_1 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external', subformula='if_other_expr_above(test1.tax_tags, USD(3000.0))'),
name='test11_1', code='test11_1',
)
test11_2 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external', subformula='if_other_expr_below(test1.tax_tags, USD(3000.0))'),
name='test11_2', code='test11_2',
)
test11_3 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external', subformula='if_other_expr_above(test1.tax_tags, USD(1000.0))'),
name='test11_3', code='test11_3',
)
test11_4 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external', subformula='if_other_expr_below(test1.tax_tags, USD(1000.0))'),
name='test11_4', code='test11_4',
)
# Test with an aggregation in the condition
test11_5 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external', subformula='if_other_expr_above(test1.aggregation, USD(1000.0))'),
name='test11_5', code='test11_5',
)
test11_6 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.external', subformula='if_other_expr_below(test1.aggregation, USD(1000.0))'),
name='test11_6', code='test11_6',
)
# Test sum_children formula (parent_id relationship is populated below)
test_12_1 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('sum_children'),
name='test12_1', code='test12_1',
)
test_12_2 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.tax_tags'),
name='test12_2', code='test12_2',
)
test_12_3 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test1.domain'),
name='test12_3', code='test12_3',
)
test_12_4 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('sum_children'),
name='test12_4', code='test12_4',
)
test_12_5 = self._prepare_test_report_line(
self._prepare_test_expression_domain([('account_id.code', '=', '101003')], 'sum'),
name='test12_5', # No code on purpose to check a different case of sum_children
)
report = self._create_report(
[
test1, test2_1, test2_2, test2_3, test2_4, test3_1, test3_2, test3_3, test4_1, test4_2,
test5, test6, test7, test9, test10_1, test10_2, test10_3, test11_1, test11_2, test11_3, test11_4,
test11_5, test11_6, test_12_1, test_12_2, test_12_3, test_12_4, test_12_5,
],
country_id=self.fake_country.id,
)
# Set parent link properly for sum_children test, now that all lines are created:
line_12_1 = self.env['account.report.line'].search([('code', '=', 'test12_1')])
self.env['account.report.line'].search([('code', 'in', ('test12_2', 'test12_3', 'test12_4'))]).parent_id = line_12_1
line_12_4 = self.env['account.report.line'].search([('code', '=', 'test12_4')])
self.env['account.report.line'].search([('name', '=', 'test12_5')]).parent_id = line_12_4
# Create the journal entries.
moves = self._create_test_account_moves([
self._prepare_test_account_move_line(100000.0, account_code='101002', date='2019-01-01'),
self._prepare_test_account_move_line(2000.0, account_code='101001', tax_tags=['+11']),
self._prepare_test_account_move_line(-300.0, account_code='101002'),
self._prepare_test_account_move_line(1500.0, account_code='101003'),
])
# Check the values.
options = self._generate_options(report, '2020-01-01', '2020-01-01')
report_lines = report._get_lines(options)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report_lines,
[ 0, 1],
[
('test1', 0.0),
('test2_1', 2000.0),
('test2_2', 0.0),
('test2_3', 0.0),
('test2_4', 2000.0),
('test3_1', -300.0),
('test3_2', 0.0),
('test3_3', 0.0),
('test4_1', 1700.0),
('test4_2', 0.0),
('9999', 3500.0),
('test6', 1.0),
('test7', 100000.0),
('test9', 1.0),
('test10_1', 100.0),
('test10_2', 100.5),
('test10_3', 100.47),
('test11_1', 0.0),
('test11_2', 100.0),
('test11_3', 100.0),
('test11_4', 0.0),
('test11_5', 100.0),
('test11_6', 0.0),
('test12_1', 3200.0),
('test12_2', 2000.0),
('test12_3', -300.0),
('test12_4', 1500.0),
('test12_5', 1500.0),
],
options,
)
# Check redirection.
expected_amls_to_test = [
('9999', moves[1].line_ids[0] + moves[1].line_ids[2]),
('test7', moves[0].line_ids[0]),
('test12_1', moves[1].line_ids[:3]),
]
for report_line_name, expected_amls in expected_amls_to_test:
report_line = report.line_ids.filtered(lambda x: x.name == report_line_name)
report_line_dict = [x for x in report_lines if x['name'] == report_line.name][0]
with self.subTest(report_line=report_line.name):
action_dict = report.action_audit_cell(options, self._get_audit_params_from_report_line(options, report_line, report_line_dict))
self.assertEqual(moves.line_ids.filtered_domain(action_dict['domain']), expected_amls)
def test_engine_aggregation_cross_report(self):
moves = self._create_test_account_moves([
self._prepare_test_account_move_line(1.0, account_code='100000', date='2020-01-01'),
self._prepare_test_account_move_line(2.0, account_code='100000', date='2021-01-01'),
self._prepare_test_account_move_line(3.0, account_code='200000', date='2020-01-01'),
self._prepare_test_account_move_line(4.0, account_code='200000', date='2021-01-01'),
self._prepare_test_account_move_line(5.0, account_code='300000', date='2021-01-01'),
])
# Other report
other_report_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('1'),
name='other_report_line_1', code='other_report_line_1',
)
other_report_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('2'),
name='other_report_line_2', code='other_report_line_2',
)
other_report_line_3 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('other_report_line_1.balance + other_report_line_2.balance'),
name='other_report_line_3', code='other_report_line_3',
)
other_report_line_4 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('3'),
name='other_report_line_4', code='other_report_line_4',
)
other_report = self._create_report([other_report_line_1, other_report_line_2, other_report_line_3, other_report_line_4])
other_report_options = self._generate_options(other_report, '2021-01-01', '2021-01-01')
# Main report
main_report_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('other_report_line_2.balance', subformula='cross_report', date_scope='strict_range'),
name='main_report_line_1', code='main_report_line_1',
)
main_report_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('other_report_line_2.balance', subformula='cross_report', date_scope='from_beginning'),
name='main_report_line_2', code='main_report_line_2',
)
main_report_line_3 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('other_report_line_3.balance', subformula='cross_report', date_scope='strict_range'),
name='main_report_line_3', code='main_report_line_3',
)
main_report_line_4 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('other_report_line_3.balance', subformula='cross_report', date_scope='from_beginning'),
name='main_report_line_4', code='main_report_line_4',
)
main_report_line_5 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation(
'main_report_line_1.balance + main_report_line_2.balance + main_report_line_3.balance + main_report_line_4.balance',
),
name='main_report_line_5', code='main_report_line_5',
)
main_report_line_6 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation(
'main_report_line_1.balance + main_report_line_2.balance + main_report_line_3.balance + main_report_line_4.balance',
),
name='main_report_line_6', code='main_report_line_6',
)
main_report = self._create_report([main_report_line_1, main_report_line_2, main_report_line_3, main_report_line_4, main_report_line_5, main_report_line_6])
main_report_options = self._generate_options(main_report, '2021-01-01', '2021-01-01')
# First check other_report
self.assertLinesValues(
# pylint: disable=bad-whitespace
other_report._get_lines(other_report_options),
[ 0, 1],
[
('other_report_line_1', 2.0),
('other_report_line_2', 4.0),
('other_report_line_3', 6.0),
('other_report_line_4', 5.0),
],
other_report_options,
)
# Check main_report
main_report_options = self._generate_options(main_report, '2021-01-01', '2021-01-01')
main_report_lines = main_report._get_lines(main_report_options)
self.assertLinesValues(
# pylint: disable=bad-whitespace
main_report_lines,
[ 0, 1],
[
('main_report_line_1', 4.0),
('main_report_line_2', 7.0),
('main_report_line_3', 6.0),
('main_report_line_4', 10.0),
('main_report_line_5', 27.0),
('main_report_line_6', 27.0),
],
main_report_options,
)
# Check redirection.
expected_amls_to_test = [
('main_report_line_1', moves[1].line_ids[1]),
('main_report_line_2', moves[1].line_ids[1] + moves[0].line_ids[1]),
]
for report_line_name, expected_amls in expected_amls_to_test:
report_line = main_report.line_ids.filtered(lambda x: x.name == report_line_name)
report_line_dict = [x for x in main_report_lines if x['name'] == report_line.name][0]
with self.subTest(report_line=report_line.name):
action_dict = main_report.action_audit_cell(main_report_options, self._get_audit_params_from_report_line(main_report_options, report_line, report_line_dict))
self.assertEqual(moves.line_ids.filtered_domain(action_dict['domain']), expected_amls)
def test_engine_aggregation_expansion(self):
report = self._create_report([
self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('42'),
code='TAG_1',
),
self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('221292'),
code='TAG_2',
),
self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('777'),
code='TAG_3',
),
self._prepare_test_report_line(
self._prepare_test_expression_aggregation('TAG_1.balance + TAG_2.balance'),
code='SIMPLE_AGG',
),
self._prepare_test_report_line(
self._prepare_test_expression_aggregation('SIMPLE_AGG.balance + TAG_3.balance'),
code='COMPLEX_AGG',
),
self._prepare_test_report_line(
self._prepare_test_expression_aggregation('TAG_1.balance + TAG_2.balance', subformula='if_other_expr_above(TAG_3.balance, EUR(13))'),
code='BOUNDED_AGG',
),
self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('3333'),
),
])
other_report = self._create_report([
self._prepare_test_report_line(
self._prepare_test_expression_aggregation('SIMPLE_AGG.balance + BOUNDED_AGG.balance', subformula='cross_report'),
code='CROSS_REPORT_AGG',
),
])
expr_map = {expression.report_line_id.code: expression for expression in (report + other_report).line_ids.expression_ids}
self.assertEqual(
expr_map['SIMPLE_AGG']._expand_aggregations(),
expr_map['SIMPLE_AGG'] + expr_map['TAG_1'] + expr_map['TAG_2'],
)
self.assertEqual(
expr_map['COMPLEX_AGG']._expand_aggregations(),
expr_map['COMPLEX_AGG'] + expr_map['SIMPLE_AGG'] + expr_map['TAG_1'] + expr_map['TAG_2'] + expr_map['TAG_3'],
)
self.assertEqual(
expr_map['BOUNDED_AGG']._expand_aggregations(),
expr_map['BOUNDED_AGG'] + expr_map['TAG_1'] + expr_map['TAG_2'] + expr_map['TAG_3'],
)
self.assertEqual(
expr_map['CROSS_REPORT_AGG']._expand_aggregations(),
expr_map['CROSS_REPORT_AGG'] + expr_map['SIMPLE_AGG'] + expr_map['BOUNDED_AGG'] + expr_map['TAG_1'] + expr_map['TAG_2'] + expr_map['TAG_3'],
)
def test_load_more(self):
partner_a, partner_b, partner_c = self.env['res.partner'].create([
{'name': 'Partner A'},
{'name': 'Partner B'},
{'name': 'Partner C'},
])
self._create_test_account_moves([
self._prepare_test_account_move_line(1000.0, partner_id=partner_a.id, date='2020-01-01'),
self._prepare_test_account_move_line(2000.0, partner_id=partner_b.id, date='2020-01-01'),
self._prepare_test_account_move_line(3000.0, partner_id=partner_c.id, date='2020-01-01'),
])
report = self._create_report(
test_report_line_values_list=[self._prepare_test_report_line(
self._prepare_test_expression_domain([('partner_id', '!=', False)], 'sum'),
groupby='partner_id',
)],
load_more_limit=2,
)
options = self._generate_options(report, '2020-01-01', '2020-01-31')
lines = report._get_lines(options)
self.assertLinesValues(
# pylint: disable=bad-whitespace
lines,
[ 0, 1],
[
('test_line_1', '6,000.00'),
('Partner A', '1,000.00'),
('Partner B', '2,000.00'),
('Load more...', ''),
],
options,
)
load_more_line = lines[-1]
load_more_res = report._get_custom_report_function(load_more_line['expand_function'], 'expand_unfoldable_line')(
load_more_line['id'],
load_more_line['groupby'],
options,
load_more_line['progress'],
load_more_line['offset']
)['lines']
self.assertLinesValues(
# pylint: disable=bad-whitespace
load_more_res,
[ 0, 1],
[
('Partner C', '3,000.00'),
],
options,
)
def test_engine_external_boolean(self):
# Create the report.
test_line = self._prepare_test_report_line(
self._prepare_test_expression_external('most_recent', [
self._prepare_test_external_values('1', '2020-01-02'),
self._prepare_test_external_values('0', '2020-01-03'),
self._prepare_test_external_values('1', '2020-01-03'),
self._prepare_test_external_values('0', '2020-01-05'),
], figure_type='boolean')
)
report = self._create_report([test_line])
# Check the values at multiple dates.
options = self._generate_options(report, '2020-01-01', '2020-01-01')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 'No'),
],
options,
)
options = self._generate_options(report, '2020-01-02', '2020-01-02')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 'Yes'),
],
options,
)
options = self._generate_options(report, '2020-01-03', '2020-01-03')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 'Yes'),
],
options,
)
options = self._generate_options(report, '2020-01-05', '2020-01-05')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 'No'),
],
options,
)
options = self._generate_options(report, '2020-01-02', '2020-01-05')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 'No'),
],
options,
)
def test_engine_external_string(self):
# Create the report.
test_line = self._prepare_test_report_line(
self._prepare_test_expression_external('most_recent', [
self._prepare_test_external_values('TARDIS', '2020-01-02', figure_type='string'),
self._prepare_test_external_values('Kris Kelvin', '2020-01-03', figure_type='string'),
self._prepare_test_external_values('Trisolaris', '2020-01-03', figure_type='string'),
self._prepare_test_external_values("5-ounce bird carrying a 1-pound coconut", '2020-01-05', figure_type='string'),
], figure_type='string')
)
report = self._create_report([test_line])
# Check the values at multiple dates.
options = self._generate_options(report, '2020-01-01', '2020-01-01')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', ''),
],
options,
)
options = self._generate_options(report, '2020-01-02', '2020-01-02')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 'TARDIS'),
],
options,
)
options = self._generate_options(report, '2020-01-03', '2020-01-03')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 'Trisolaris'),
],
options,
)
options = self._generate_options(report, '2020-01-05', '2020-01-05')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', "5-ounce bird carrying a 1-pound coconut"),
],
options,
)
options = self._generate_options(report, '2020-01-02', '2020-01-05')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', "5-ounce bird carrying a 1-pound coconut"),
],
options,
)
def test_engine_external_default_value_tax_closing_fiscalyear_lock_date(self):
def lock_via_fiscalyear_lock_date(non_tax_report, tax_report, report_options_map):
lock_date_wizard = self.env['account.change.lock.date'].create({
'fiscalyear_lock_date': fields.Date.from_string('2020-01-02'),
})
lock_date_wizard.change_lock_date()
self._run_external_engine_default_test_case(False, True, lock_via_fiscalyear_lock_date)
def test_engine_external_default_value_tax_closing_tax_lock_date(self):
def lock_via_tax_lock_date(non_tax_report, tax_report, report_options_map):
lock_date_wizard = self.env['account.change.lock.date'].create({
'tax_lock_date': fields.Date.from_string('2020-01-02'),
})
lock_date_wizard.change_lock_date()
self._run_external_engine_default_test_case(True, False, lock_via_tax_lock_date)
def test_engine_external_default_value_tax_closing(self):
def lock_via_tax_closing(non_tax_report, tax_report, report_options_map):
tax_closing_action = self.env['account.tax.report.handler'].action_periodic_vat_entries(report_options_map[tax_report])
closing_move_id = tax_closing_action['res_id']
self.env['account.move'].browse(closing_move_id).action_post()
self._run_external_engine_default_test_case(True, False, lock_via_tax_closing)
def _run_external_engine_default_test_case(self, impact_tax_report, impact_non_tax_report, lock_operation_function):
""" Common helper to run the tests of _default expressions
"""
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('10'),
groupby='account_id',
)
test_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_external('sum', {}),
self._prepare_test_expression_account_codes('10', label='_default_balance'),
)
non_tax_report = self._create_report([test_line_1, test_line_2], name="non_tax_report")
tax_report = self._create_report([test_line_1, test_line_2], root_report_id=self.env.ref('account.generic_tax_report').id, name="tax_report")
# Create the journal entries.
self._create_test_account_moves([
self._prepare_test_account_move_line(1000.0, account_code='100001'),
self._prepare_test_account_move_line(-300.0, account_code='101002'),
self._prepare_test_account_move_line(-600.0, account_code='314159'),
])
report_options_map = {
report: self._generate_options(
report,
'2020-01-01', '2020-01-31',
default_options={
'unfold_all': True,
}
)
for report in [non_tax_report, tax_report]
}
# Check the values before locking
for report in [non_tax_report, tax_report]:
with self.subTest(report=report.name):
options = report_options_map[report]
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[0, 1],
[
('test_line_1', 700.0),
('100001 100001', 1000.0),
('101002 101002', -300.0),
('test_line_2', 0.0),
],
options,
)
# Run the lock operation
lock_operation_function(non_tax_report, tax_report, report_options_map)
# Check the values after locking
for report, impacted in [(non_tax_report, impact_non_tax_report), (tax_report, impact_tax_report)]:
with self.subTest(report=report.name):
options = report_options_map[report]
if impacted:
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[0, 1],
[
('test_line_1', 700.0),
('100001 100001', 1000.0),
('101002 101002', -300.0),
('test_line_2', 700.0),
],
options,
)
else:
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[0, 1],
[
('test_line_1', 700.0),
('100001 100001', 1000.0),
('101002 101002', -300.0),
('test_line_2', 0.0),
],
options,
)
def test_engine_aggregation_cross_bound(self):
report_1 = self._create_report([
self._prepare_test_report_line(
self._prepare_test_expression_aggregation('line_2_1.balance', subformula='cross_report'),
name='Line 1-1',
code='line_1_1',
),
])
self._create_report([
self._prepare_test_report_line(
self._prepare_test_expression_aggregation('14.0', subformula='if_other_expr_above(line_2_1.dudu, EUR(0))'),
self._prepare_test_expression_account_codes('101', label='dudu'),
name='Line 2-1',
code='line_2_1',
),
])
options = self._generate_options(report_1, '2020-01-01', '2020-01-01')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report_1._get_lines(options),
[ 0, 1],
[
('Line 1-1', 0.0),
],
options
)
self._create_test_account_moves([
self._prepare_test_account_move_line(10, account_code='101001'),
self._prepare_test_account_move_line(-10, account_code='100001'),
])
self.assertLinesValues(
# pylint: disable=bad-whitespace
report_1._get_lines(options),
[ 0, 1],
[
('Line 1-1', 14.0),
],
options
)
def test_change_expression_engine_to_tax_tags(self):
"""
Ensure that tax tags are created when switching the expression engine to tax tags if formula is unchanged.
"""
formula = 'dudu'
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_external(formula, [self._prepare_test_external_values(100.0, '2020-01-01')], label='external'),
)
report = self._create_report([test_line_1], country_id=self.fake_country.id)
tags = self.env['account.account.tag']._get_tax_tags(formula, self.fake_country.id)
self.assertEqual(len(tags), 0)
report.line_ids[0].expression_ids[0].engine = 'tax_tags'
tags = self.env['account.account.tag']._get_tax_tags(formula, self.fake_country.id)
self.assertEqual(tags.mapped('name'), ['-' + formula, '+' + formula])
def test_integer_rounding(self):
line_1 = self._prepare_test_report_line(
self._prepare_test_expression_domain([('account_id.code', '=', '101001')], 'sum'),
code='test_1',
)
line_2 = self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('42'),
code='test_2',
)
line_3 = self._prepare_test_report_line(
self._prepare_test_expression_account_codes('1'),
code='test_3',
)
line_4 = self._prepare_test_report_line(
self._prepare_test_expression_external('sum', [
self._prepare_test_external_values(3.5, '2023-01-01'),
]),
code='test_4',
)
line_5 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test_1.balance + test_2.balance + test_3.balance + test_4.balance'),
code='test_5',
)
line_6 = self._prepare_test_report_line(
self._prepare_test_expression_aggregation('test_5.balance / 10'),
)
report = self._create_report([line_1, line_2, line_3, line_4, line_5, line_6], country_id=self.fake_country.id,)
self._create_test_account_moves([
self._prepare_test_account_move_line(5.4, account_code='101001', tax_tags=['+42'], date='2023-01-01'),
])
main_options = self._generate_options(report, '2023-01-01', '2023-01-01')
# Test with a first rounding
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(report._custom_options_add_integer_rounding({**main_options}, 'HALF-UP')),
[ 0, 1],
[
('test_line_1', 5.0),
('test_line_2', 5.0),
('test_line_3', 5.0),
('test_line_4', 4.0),
('test_line_5', 19.0),
('test_line_6', 2.0),
],
main_options,
)
# Test with another rounding method
up_options = report._custom_options_add_integer_rounding({**main_options}, 'UP', previous_options={'integer_rounding_enabled': True})
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(up_options),
[ 0, 1],
[
('test_line_1', 6.0),
('test_line_2', 6.0),
('test_line_3', 6.0),
('test_line_4', 4.0),
('test_line_5', 22.0),
('test_line_6', 3.0),
],
up_options
)
# In file export mode, the rounding should always be applied, even if it was previously disabled
print_mode_options = report._custom_options_add_integer_rounding(
{**main_options, 'export_mode': 'file'},
'HALF-UP',
previous_options={'integer_rounding_enabled': False},
)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(print_mode_options),
[ 0, 1],
[
('test_line_1', 5.0),
('test_line_2', 5.0),
('test_line_3', 5.0),
('test_line_4', 4.0),
('test_line_5', 19.0),
('test_line_6', 2.0),
],
print_mode_options,
)
# Rounding available, but disabled
no_rounding_options = report._custom_options_add_integer_rounding({**main_options}, 'UP', previous_options={'integer_rounding_enabled': False})
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(no_rounding_options),
[ 0, 1],
[
('test_line_1', 5.40),
('test_line_2', 5.40),
('test_line_3', 5.40),
('test_line_4', 3.50),
('test_line_5', 19.70),
('test_line_6', 1.97),
],
no_rounding_options,
)
def test_print_hide_0_lines(self):
# Create the report.
test_line_1 = self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('11'),
groupby='account_id',
)
test_line_2 = self._prepare_test_report_line(
self._prepare_test_expression_tax_tags('222T'),
groupby='account_id',
)
report = self._create_report([test_line_1, test_line_2], country_id=self.fake_country.id)
# Create the journal entries.
self._create_test_account_moves([
self._prepare_test_account_move_line(3000.0, account_code='101001', tax_tags=['+11', '-222T']),
self._prepare_test_account_move_line(3600.0, account_code='101001', tax_tags=['+222T']),
self._prepare_test_account_move_line(-600.0, account_code='101001', tax_tags=['+222T', '-11']),
])
# To ensure that the lines are shown when hide_0_lines isn't toggled and vice versa, we test both scenarios.
options_not_hide = self._generate_options(
report,
'2020-01-01', '2020-01-01',
default_options={'unfold_all': True, 'export_mode': 'print'}
)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options_not_hide),
[ 0, 1],
[
('test_line_1', 3600.0),
('101001 101001', 3600.0),
('test_line_2', 0.0),
('101001 101001', 0.0),
],
options_not_hide,
)
options_hide = self._generate_options(
report,
'2020-01-01', '2020-01-01',
default_options={'unfold_all': True, 'export_mode': 'print', 'hide_0_lines': True}
)
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options_hide),
[ 0, 1],
[
('test_line_1', 3600.0),
('101001 101001', 3600.0),
],
options_hide,
)
def test_column_blank_if_zero(self):
"""account.report.column's `blank_if_zero` option should only impacts number figure types"""
test_line = self._prepare_test_report_line(
self._prepare_test_expression_external('most_recent', [], label='monetary', figure_type='monetary'),
self._prepare_test_expression_external('most_recent', [], label='percentage', figure_type='percentage'),
self._prepare_test_expression_external('most_recent', [], label='integer', figure_type='integer'),
self._prepare_test_expression_external('most_recent', [], label='float', figure_type='float'),
self._prepare_test_expression_external('most_recent', [
self._prepare_test_external_values(False, '2024-01-01', figure_type='boolean'),
], label='boolean', figure_type='boolean'),
self._prepare_test_expression_external('most_recent', [
self._prepare_test_external_values('dudu', '2024-01-01', figure_type='string'),
], label='string', figure_type='string'),
)
report = self._create_report([test_line], columns=['monetary', 'percentage', 'integer', 'float', 'boolean', 'string'])
report.column_ids.blank_if_zero = True
options = self._generate_options(report, '2024-01-01', '2024-01-01')
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1, 2, 3, 4, 5, 6],
[
('test_line_1', '', '', '', '', 'No', 'dudu'),
],
options,
)
def test_column_groups_audit(self):
account = self.company_data['default_account_assets']
move = self.env['account.move'].create({
'move_type': 'entry',
'date': '2024-01-01',
'line_ids': [
(0, 0, {'debit': 10.0, 'credit': 0.0, 'account_id': account.id, 'partner_id': self.partner_a.id}),
(0, 0, {'debit': 20.0, 'credit': 0.0, 'account_id': account.id, 'partner_id': self.partner_b.id}),
(0, 0, {'debit': 0.0, 'credit': 30.0, 'account_id': account.id}),
],
})
move.action_post()
report = self._create_report([
self._prepare_test_report_line(
self._prepare_test_expression_domain([('account_id', '=', account.id)], 'sum'),
code='report_line',
),
], country_id=self.fake_country.id)
horizontal_group = self.env['account.report.horizontal.group'].create({
'name': 'Horizontal Group',
'report_ids': report.ids,
'rule_ids': [
Command.create({
'field_name': 'partner_id',
'domain': f"[('id', 'in', {(self.partner_a + self.partner_b).ids})]",
}),
],
})
main_options = self._generate_options(report, '2024-01-01', '2024-01-01', default_options={'selected_horizontal_group_id': horizontal_group.id})
lines = report._get_lines(main_options)
for (col_group_key, col_group_options), expected_partner in zip(report._split_options_per_column_group(main_options).items(), [self.partner_a, self.partner_b]):
audit_params = self._get_audit_params_from_report_line(col_group_options, report.line_ids, lines[0], column_group_key=col_group_key)
action_dict = report.action_audit_cell(col_group_options, audit_params)
expected_amls = move.line_ids.filtered(lambda x: x.partner_id == expected_partner)
audit_result_amls = move.line_ids.filtered_domain(action_dict['domain'])
self.assertEqual(audit_result_amls, expected_amls, f"Wrong audit result for partner {expected_partner.name}: {audit_result_amls}")
def test_account_codes_load_more_limit_groupby(self):
""" The account_codes engine performs an additional groupby in its SQL query. This tests makes sure this does not break the behavior
of the load_more_limit when grouping.
"""
partner_a, partner_b, partner_c = self.env['res.partner'].create([
{'name': 'Partner A'},
{'name': 'Partner B'},
{'name': 'Partner C'},
])
report = self._create_report(
[
self._prepare_test_report_line(
self._prepare_test_expression_account_codes('1'),
groupby='partner_id',
),
],
load_more_limit=2,
)
move = self._create_test_account_moves([
self._prepare_test_account_move_line(10, account_code='11', partner_id=partner_a.id),
self._prepare_test_account_move_line(20, account_code='11', partner_id=partner_a.id),
self._prepare_test_account_move_line(25, account_code='12', partner_id=partner_a.id),
self._prepare_test_account_move_line(30, account_code='11'),
self._prepare_test_account_move_line(40, account_code='11'),
self._prepare_test_account_move_line(50, account_code='12', partner_id=partner_b.id),
self._prepare_test_account_move_line(60, account_code='13', partner_id=partner_c.id),
self._prepare_test_account_move_line(-210, account_code='2'),
])
options = self._generate_options(report, '2020-01-01', '2020-01-01', default_options={'unfold_all': True})
self.assertLinesValues(
# pylint: disable=bad-whitespace
report._get_lines(options),
[ 0, 1],
[
('test_line_1', 235.0),
('Partner A', 55.0),
('Partner B', 50.0),
('Load more...', ''),
],
options,
)