forked from Mapan/odoo17e
905 lines
47 KiB
Python
905 lines
47 KiB
Python
# -*- coding: utf-8 -*-
|
|
# pylint: disable=C0326
|
|
|
|
from .common import TestAccountReportsCommon
|
|
|
|
from odoo import fields, Command
|
|
from odoo.tests import tagged
|
|
|
|
from freezegun import freeze_time
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestFinancialReport(TestAccountReportsCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls, chart_template_ref=None):
|
|
super().setUpClass(chart_template_ref=chart_template_ref)
|
|
|
|
# ==== Partners ====
|
|
|
|
cls.partner_a = cls.env['res.partner'].create({'name': 'partner_a', 'company_id': False})
|
|
cls.partner_b = cls.env['res.partner'].create({'name': 'partner_b', 'company_id': False})
|
|
cls.partner_c = cls.env['res.partner'].create({'name': 'partner_c', 'company_id': False})
|
|
|
|
# ==== Accounts ====
|
|
|
|
# Cleanup existing "Current year earnings" accounts since we can only have one by company.
|
|
cls.env['account.account'].search([
|
|
('company_id', 'in', (cls.company_data['company'] + cls.company_data_2['company']).ids),
|
|
('account_type', '=', 'equity_unaffected'),
|
|
]).unlink()
|
|
|
|
account_type_data = [
|
|
('asset_receivable', {'reconcile': True}),
|
|
('liability_payable', {'reconcile': True}),
|
|
('asset_cash', {}),
|
|
('asset_current', {}),
|
|
('asset_prepayments', {}),
|
|
('asset_fixed', {}),
|
|
('asset_non_current', {}),
|
|
('equity', {}),
|
|
('equity_unaffected', {}),
|
|
('income', {}),
|
|
]
|
|
|
|
accounts = cls.env['account.account'].create([{
|
|
**data[1],
|
|
'name': 'account%s' % i,
|
|
'code': 'code%s' % i,
|
|
'account_type': data[0],
|
|
'company_id': cls.company_data['company'].id,
|
|
} for i, data in enumerate(account_type_data)])
|
|
|
|
accounts_2 = cls.env['account.account'].create([{
|
|
**data[1],
|
|
'name': 'account%s' % (i + 100),
|
|
'code': 'code%s' % (i + 100),
|
|
'account_type': data[0],
|
|
'company_id': cls.company_data_2['company'].id,
|
|
} for i, data in enumerate(account_type_data)])
|
|
|
|
# ==== Custom filters ====
|
|
|
|
cls.horizontal_group = cls.env['account.report.horizontal.group'].create({
|
|
'name': 'Horizontal Group',
|
|
'rule_ids': [
|
|
Command.create({
|
|
'field_name': 'partner_id',
|
|
'domain': f"[('id', 'in', {(cls.partner_a + cls.partner_b).ids})]",
|
|
}),
|
|
Command.create({
|
|
'field_name': 'account_id',
|
|
'domain': f"[('id', 'in', {accounts[:2].ids})]",
|
|
}),
|
|
],
|
|
})
|
|
|
|
# ==== Journal entries ====
|
|
|
|
cls.move_2019 = cls.env['account.move'].create({
|
|
'move_type': 'entry',
|
|
'date': fields.Date.from_string('2019-01-01'),
|
|
'line_ids': [
|
|
(0, 0, {'debit': 25.0, 'credit': 0.0, 'account_id': accounts[0].id, 'partner_id': cls.partner_a.id}),
|
|
(0, 0, {'debit': 25.0, 'credit': 0.0, 'account_id': accounts[0].id, 'partner_id': cls.partner_b.id}),
|
|
(0, 0, {'debit': 25.0, 'credit': 0.0, 'account_id': accounts[0].id, 'partner_id': cls.partner_c.id}),
|
|
(0, 0, {'debit': 25.0, 'credit': 0.0, 'account_id': accounts[0].id, 'partner_id': cls.partner_a.id}),
|
|
(0, 0, {'debit': 200.0, 'credit': 0.0, 'account_id': accounts[1].id, 'partner_id': cls.partner_b.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 300.0, 'account_id': accounts[2].id, 'partner_id': cls.partner_c.id}),
|
|
(0, 0, {'debit': 400.0, 'credit': 0.0, 'account_id': accounts[3].id, 'partner_id': cls.partner_a.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 1100.0, 'account_id': accounts[4].id, 'partner_id': cls.partner_b.id}),
|
|
(0, 0, {'debit': 700.0, 'credit': 0.0, 'account_id': accounts[6].id, 'partner_id': cls.partner_a.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 800.0, 'account_id': accounts[7].id, 'partner_id': cls.partner_b.id}),
|
|
(0, 0, {'debit': 800.0, 'credit': 0.0, 'account_id': accounts[8].id, 'partner_id': cls.partner_c.id}),
|
|
],
|
|
})
|
|
cls.move_2019.action_post()
|
|
|
|
cls.move_2018 = cls.env['account.move'].create({
|
|
'move_type': 'entry',
|
|
'date': fields.Date.from_string('2018-01-01'),
|
|
'line_ids': [
|
|
(0, 0, {'debit': 1000.0, 'credit': 0.0, 'account_id': accounts[0].id, 'partner_id': cls.partner_a.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 1000.0, 'account_id': accounts[2].id, 'partner_id': cls.partner_b.id}),
|
|
(0, 0, {'debit': 250.0, 'credit': 0.0, 'account_id': accounts[0].id, 'partner_id': cls.partner_a.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 250.0, 'account_id': accounts[9].id, 'partner_id': cls.partner_a.id}),
|
|
],
|
|
})
|
|
cls.move_2018.action_post()
|
|
|
|
cls.move_2017 = cls.env['account.move'].with_company(cls.company_data_2['company']).create({
|
|
'move_type': 'entry',
|
|
'date': fields.Date.from_string('2017-01-01'),
|
|
'line_ids': [
|
|
(0, 0, {'debit': 2000.0, 'credit': 0.0, 'account_id': accounts_2[0].id, 'partner_id': cls.partner_a.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 4000.0, 'account_id': accounts_2[2].id, 'partner_id': cls.partner_b.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 5000.0, 'account_id': accounts_2[4].id, 'partner_id': cls.partner_c.id}),
|
|
(0, 0, {'debit': 7000.0, 'credit': 0.0, 'account_id': accounts_2[6].id, 'partner_id': cls.partner_a.id}),
|
|
],
|
|
})
|
|
cls.move_2017.action_post()
|
|
|
|
cls.report = cls.env.ref('account_reports.balance_sheet')
|
|
|
|
cls.report_no_parent_id = cls.env["account.report"].create({
|
|
'name': "Test report",
|
|
|
|
'column_ids': [
|
|
Command.create({
|
|
'name': 'Balance',
|
|
'expression_label': 'balance',
|
|
'sequence': 1
|
|
})
|
|
],
|
|
|
|
'line_ids': [
|
|
Command.create({
|
|
'name': "Invisible Partner A line",
|
|
'code': "INVA",
|
|
'sequence': 1,
|
|
'hierarchy_level': 0,
|
|
'groupby': "account_id",
|
|
'foldable': True,
|
|
'expression_ids': [Command.clear(), Command.create({
|
|
'label': 'balance',
|
|
'engine': 'domain',
|
|
'formula': [("partner_id", "=", cls.partner_a.id)],
|
|
'subformula': 'sum',
|
|
'date_scope': 'strict_range'
|
|
})],
|
|
}),
|
|
Command.create({
|
|
'name': "Invisible Partner B line",
|
|
'code': "INVB",
|
|
'sequence': 2,
|
|
'hierarchy_level': 0,
|
|
'groupby': "account_id",
|
|
'foldable': True,
|
|
'expression_ids': [Command.clear(), Command.create({
|
|
'label': 'balance',
|
|
'engine': 'domain',
|
|
'formula': [("partner_id", "=", cls.partner_b.id)],
|
|
'subformula': 'sum',
|
|
'date_scope': 'strict_range'
|
|
})],
|
|
}),
|
|
Command.create({
|
|
'name': "Total of Invisible lines",
|
|
'code': "INVT",
|
|
'sequence': 3,
|
|
'hierarchy_level': 0,
|
|
'expression_ids': [Command.clear(), Command.create({
|
|
'label': 'balance',
|
|
'engine': 'aggregation',
|
|
'formula': 'INVA.balance + INVB.balance',
|
|
'date_scope': 'normal'
|
|
})],
|
|
}),
|
|
],
|
|
})
|
|
|
|
def _build_generic_id_from_financial_line(self, financial_rep_ln_xmlid):
|
|
report_line = self.env.ref(financial_rep_ln_xmlid)
|
|
return '-account.financial.html.report.line-%s' % report_line.id
|
|
|
|
def _get_line_id_from_generic_id(self, generic_id):
|
|
return int(generic_id.split('-')[-1])
|
|
|
|
def test_financial_report_strict_range_on_report_lines_with_no_parent_id(self):
|
|
""" Tests that lines with no parent can be correctly filtered by date range """
|
|
self.report_no_parent_id.filter_multi_company = 'disabled'
|
|
options = self._generate_options(self.report_no_parent_id, fields.Date.from_string('2019-01-01'), fields.Date.from_string('2019-12-31'))
|
|
|
|
lines = self.report_no_parent_id._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
[
|
|
('Invisible Partner A line', 1150.0),
|
|
('Invisible Partner B line', -1675.0),
|
|
('Total of Invisible lines', -525.0),
|
|
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_financial_report_strict_empty_range_on_report_lines_with_no_parent_id(self):
|
|
""" Tests that lines with no parent can be correctly filtered by date range with no invoices"""
|
|
self.report_no_parent_id.filter_multi_company = 'disabled'
|
|
options = self._generate_options(self.report_no_parent_id, fields.Date.from_string('2019-03-01'), fields.Date.from_string('2019-03-31'))
|
|
|
|
lines = self.report_no_parent_id._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
[
|
|
('Invisible Partner A line', 0.0),
|
|
('Invisible Partner B line', 0.0),
|
|
('Total of Invisible lines', 0.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
@freeze_time("2016-06-06")
|
|
def test_balance_sheet_today_current_year_earnings(self):
|
|
invoice = self.env['account.move'].create({
|
|
'move_type': 'out_invoice',
|
|
'partner_id': self.partner_a.id,
|
|
'date': '2016-02-02',
|
|
'invoice_line_ids': [Command.create({
|
|
'product_id': self.product_a.id,
|
|
'price_unit': 110,
|
|
'tax_ids': [],
|
|
})]
|
|
})
|
|
invoice.action_post()
|
|
|
|
self.report.filter_multi_company = 'disabled'
|
|
options = self._generate_options(self.report, fields.Date.from_string('2016-06-01'), fields.Date.from_string('2016-06-06'))
|
|
options['date']['filter'] = 'today'
|
|
|
|
lines = self.report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
[
|
|
('ASSETS', 110.0),
|
|
('Current Assets', 110.0),
|
|
('Bank and Cash Accounts', 0.0),
|
|
('Receivables', 110.0),
|
|
('Current Assets', 0.0),
|
|
('Prepayments', 0.0),
|
|
('Total Current Assets', 110.0),
|
|
('Plus Fixed Assets', 0.0),
|
|
('Plus Non-current Assets', 0.0),
|
|
('Total ASSETS', 110.0),
|
|
|
|
('LIABILITIES', 0.0),
|
|
('Current Liabilities', 0.0),
|
|
('Current Liabilities', 0.0),
|
|
('Payables', 0.0),
|
|
('Total Current Liabilities', 0.0),
|
|
('Plus Non-current Liabilities', 0.0),
|
|
('Total LIABILITIES', 0.0),
|
|
|
|
('EQUITY', 110.0),
|
|
('Unallocated Earnings', 110.0),
|
|
('Current Year Unallocated Earnings', 110.0),
|
|
('Current Year Earnings', 110.0),
|
|
('Current Year Allocated Earnings', 0.0),
|
|
('Total Current Year Unallocated Earnings', 110.0),
|
|
('Previous Years Unallocated Earnings', 0.0),
|
|
('Total Unallocated Earnings', 110.0),
|
|
('Retained Earnings', 0.0),
|
|
('Total EQUITY', 110.0),
|
|
|
|
('LIABILITIES + EQUITY', 110.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
@freeze_time("2016-05-05")
|
|
def test_balance_sheet_last_month_vs_custom_current_year_earnings(self):
|
|
"""
|
|
Checks the balance sheet calls the right period of the P&L when using last_month date filter, or an equivalent custom filter
|
|
(this used to fail due to options regeneration made by the P&L's get_options())"
|
|
"""
|
|
to_invoice = [('15', '11'), ('15', '12'), ('16', '01'), ('16', '02'), ('16', '03'), ('16', '04')]
|
|
for year, month in to_invoice:
|
|
invoice = self.env['account.move'].create({
|
|
'move_type': 'out_invoice',
|
|
'partner_id': self.partner_a.id,
|
|
'invoice_date': f'20{year}-{month}-01',
|
|
'invoice_line_ids': [Command.create({
|
|
'product_id': self.product_a.id,
|
|
'price_unit': 1000,
|
|
'tax_ids': [],
|
|
})]
|
|
})
|
|
invoice.action_post()
|
|
expected_result =[
|
|
('ASSETS', 6000.0),
|
|
('Current Assets', 6000.0),
|
|
('Bank and Cash Accounts', 0.0),
|
|
('Receivables', 6000.0),
|
|
('Current Assets', 0.0),
|
|
('Prepayments', 0.0),
|
|
('Total Current Assets', 6000.0),
|
|
('Plus Fixed Assets', 0.0),
|
|
('Plus Non-current Assets', 0.0),
|
|
('Total ASSETS', 6000.0),
|
|
|
|
('LIABILITIES', 0.0),
|
|
('Current Liabilities', 0.0),
|
|
('Current Liabilities', 0.0),
|
|
('Payables', 0.0),
|
|
('Total Current Liabilities', 0.0),
|
|
('Plus Non-current Liabilities', 0.0),
|
|
('Total LIABILITIES', 0.0),
|
|
|
|
('EQUITY', 6000.0),
|
|
('Unallocated Earnings', 6000.0),
|
|
('Current Year Unallocated Earnings', 4000.0),
|
|
('Current Year Earnings', 4000.0),
|
|
('Current Year Allocated Earnings', 0.0),
|
|
('Total Current Year Unallocated Earnings', 4000.0),
|
|
('Previous Years Unallocated Earnings', 2000.0),
|
|
('Total Unallocated Earnings', 6000.0),
|
|
('Retained Earnings', 0.0),
|
|
('Total EQUITY', 6000.0),
|
|
('LIABILITIES + EQUITY', 6000.0),
|
|
|
|
]
|
|
self.report.filter_multi_company = 'disabled'
|
|
options = self._generate_options(self.report, fields.Date.from_string('2016-05-05'), fields.Date.from_string('2016-05-05'))
|
|
|
|
# End of Last Month
|
|
options['date']['filter'] = 'last_month'
|
|
lines = self.report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
expected_result,
|
|
options,
|
|
)
|
|
# Custom
|
|
options['date']['filter'] = 'custom'
|
|
lines = self.report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
expected_result,
|
|
options,
|
|
)
|
|
|
|
def test_financial_report_single_company(self):
|
|
line_id = self._get_basic_line_dict_id_from_report_line_ref('account_reports.account_financial_report_bank_view0')
|
|
self.report.filter_multi_company = 'disabled'
|
|
options = self._generate_options(self.report, fields.Date.from_string('2019-01-01'), fields.Date.from_string('2019-12-31'))
|
|
options['unfolded_lines'] = [line_id]
|
|
|
|
lines = self.report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
[
|
|
('ASSETS', 50.0),
|
|
('Current Assets', -650.0),
|
|
('Bank and Cash Accounts', -1300.0),
|
|
('code2 account2', -1300.0),
|
|
('Total Bank and Cash Accounts', -1300.0),
|
|
('Receivables', 1350.0),
|
|
('Current Assets', 400.0),
|
|
('Prepayments', -1100.0),
|
|
('Total Current Assets', -650.0),
|
|
('Plus Fixed Assets', 0.0),
|
|
('Plus Non-current Assets', 700.0),
|
|
('Total ASSETS', 50.0),
|
|
|
|
('LIABILITIES', -200.0),
|
|
('Current Liabilities', -200.0),
|
|
('Current Liabilities', 0.0),
|
|
('Payables', -200.0),
|
|
('Total Current Liabilities', -200.0),
|
|
('Plus Non-current Liabilities', 0.0),
|
|
('Total LIABILITIES', -200.0),
|
|
|
|
('EQUITY', 250.0),
|
|
('Unallocated Earnings', -550.0),
|
|
('Current Year Unallocated Earnings', -800.0),
|
|
('Current Year Earnings', 0.0),
|
|
('Current Year Allocated Earnings', -800.0),
|
|
('Total Current Year Unallocated Earnings', -800.0),
|
|
('Previous Years Unallocated Earnings', 250.0),
|
|
('Total Unallocated Earnings', -550.0),
|
|
('Retained Earnings', 800.0),
|
|
('Total EQUITY', 250.0),
|
|
|
|
('LIABILITIES + EQUITY', 50.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
unfolded_lines = self.report._get_unfolded_lines(lines, line_id)
|
|
self.assertLinesValues(
|
|
unfolded_lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
[
|
|
('Bank and Cash Accounts', -1300.0),
|
|
('code2 account2', -1300.0),
|
|
('Total Bank and Cash Accounts', -1300.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_financial_report_multi_company_currency(self):
|
|
line_id = self._get_basic_line_dict_id_from_report_line_ref('account_reports.account_financial_report_bank_view0')
|
|
options = self._generate_options(self.report, fields.Date.from_string('2019-01-01'), fields.Date.from_string('2019-12-31'))
|
|
options['unfolded_lines'] = [line_id]
|
|
|
|
lines = self.report._get_lines(options)
|
|
self.assertLinesValues(
|
|
lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
[
|
|
('ASSETS', 50.0),
|
|
('Current Assets', -4150.0),
|
|
('Bank and Cash Accounts', -3300.0),
|
|
('code102 account102', -2000.0),
|
|
('code2 account2', -1300.0),
|
|
('Total Bank and Cash Accounts', -3300.0),
|
|
('Receivables', 2350.0),
|
|
('Current Assets', 400.0),
|
|
('Prepayments', -3600.0),
|
|
('Total Current Assets', -4150.0),
|
|
('Plus Fixed Assets', 0.0),
|
|
('Plus Non-current Assets', 4200.0),
|
|
('Total ASSETS', 50.0),
|
|
|
|
('LIABILITIES', -200.0),
|
|
('Current Liabilities', -200.0),
|
|
('Current Liabilities', 0.0),
|
|
('Payables', -200.0),
|
|
('Total Current Liabilities', -200.0),
|
|
('Plus Non-current Liabilities', 0.0),
|
|
('Total LIABILITIES', -200.0),
|
|
|
|
('EQUITY', 250.0),
|
|
('Unallocated Earnings', -550.0),
|
|
('Current Year Unallocated Earnings', -800.0),
|
|
('Current Year Earnings', 0.0),
|
|
('Current Year Allocated Earnings', -800.0),
|
|
('Total Current Year Unallocated Earnings', -800.0),
|
|
('Previous Years Unallocated Earnings', 250.0),
|
|
('Total Unallocated Earnings', -550.0),
|
|
('Retained Earnings', 800.0),
|
|
('Total EQUITY', 250.0),
|
|
|
|
('LIABILITIES + EQUITY', 50.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
unfolded_lines = self.report._get_unfolded_lines(lines, line_id)
|
|
self.assertLinesValues(
|
|
unfolded_lines,
|
|
# Name Balance
|
|
[ 0, 1],
|
|
[
|
|
('Bank and Cash Accounts', -3300.0),
|
|
('code102 account102', -2000.0),
|
|
('code2 account2', -1300.0),
|
|
('Total Bank and Cash Accounts', -3300.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_financial_report_comparison(self):
|
|
line_id = self._get_basic_line_dict_id_from_report_line_ref('account_reports.account_financial_report_bank_view0')
|
|
options = self._generate_options(self.report, fields.Date.from_string('2019-01-01'), fields.Date.from_string('2019-12-31'))
|
|
options = self._update_comparison_filter(options, self.report, 'custom', 1, date_to=fields.Date.from_string('2018-12-31'))
|
|
options['unfolded_lines'] = [line_id]
|
|
|
|
lines = self.report._get_lines(options)
|
|
|
|
self.assertGrowthComparisonValues(
|
|
lines,
|
|
[
|
|
('ASSETS', '-80.0%', -1),
|
|
('Current Assets', '27.7%', -1),
|
|
('Bank and Cash Accounts', '10.0%', -1),
|
|
('code102 account102', '0.0%', 0),
|
|
('code2 account2', '30.0%', -1),
|
|
('Total Bank and Cash Accounts', '10.0%', -1),
|
|
('Receivables', '4.4%', 1),
|
|
('Current Assets', 'n/a', 0),
|
|
('Prepayments', '44.0%', -1),
|
|
('Total Current Assets', '27.7%', -1),
|
|
('Plus Fixed Assets', '0.0%', 0),
|
|
('Plus Non-current Assets', '20.0%', 1),
|
|
('Total ASSETS', '-80.0%', -1),
|
|
|
|
('LIABILITIES', 'n/a', 0),
|
|
('Current Liabilities', 'n/a', 0),
|
|
('Current Liabilities', '0.0%', 0),
|
|
('Payables', 'n/a', 0),
|
|
('Total Current Liabilities', 'n/a', 0),
|
|
('Plus Non-current Liabilities', '0.0%', 0),
|
|
('Total LIABILITIES', 'n/a', 0),
|
|
|
|
('EQUITY', '0.0%', 0),
|
|
('Unallocated Earnings', '-320.0%', -1),
|
|
('Current Year Unallocated Earnings', '-420.0%', -1),
|
|
('Current Year Earnings', '-100.0%', -1),
|
|
('Current Year Allocated Earnings', 'n/a', 0),
|
|
('Total Current Year Unallocated Earnings', '-420.0%', -1),
|
|
('Previous Years Unallocated Earnings', 'n/a', 0),
|
|
('Total Unallocated Earnings', '-320.0%', -1),
|
|
('Retained Earnings', 'n/a', 0),
|
|
('Total EQUITY', '0.0%', 0),
|
|
|
|
|
|
('LIABILITIES + EQUITY', '-80.0%', 1),
|
|
]
|
|
)
|
|
|
|
def test_financial_report_comparison_multi_company_currency_multi_rates(self):
|
|
# Set up a new company with a new foreign currency and a new partner.
|
|
other_currency = self.env['res.currency'].create({
|
|
'name': 'TEST',
|
|
'symbol': 'T',
|
|
})
|
|
other_company_data = self.setup_company_data('other_company_data', currency_id=other_currency.id)
|
|
self.env['res.currency.rate'].create([
|
|
{
|
|
'currency_id': other_currency.id,
|
|
'name': '2021-01-01',
|
|
'rate': 3.0,
|
|
}, {
|
|
'currency_id': other_currency.id,
|
|
'name': '2022-01-01',
|
|
'rate': 2.0,
|
|
}
|
|
])
|
|
partner = self.env['res.partner'].create({'name': 'I am a partner', 'company_id': False})
|
|
|
|
# Create and post a journal entry linked to the new partner, for the new company.
|
|
other_company_move_2021 = self.env['account.move'].with_company(other_company_data['company']).create({
|
|
'move_type': 'entry',
|
|
'date': fields.Date.from_string('2021-01-01'),
|
|
'line_ids': [
|
|
(0, 0, {'debit': 1500.0, 'credit': 0.0, 'account_id': other_company_data['default_account_receivable'].id, 'partner_id': partner.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 1500.0, 'account_id': other_company_data['default_account_assets'].id, 'partner_id': partner.id}),
|
|
],
|
|
})
|
|
other_company_move_2021.action_post()
|
|
|
|
# Create a simple report having one line, filtering on the new partner and considering only the positive balance line (so the total is not 0).
|
|
simple_report = self.env['account.report'].create({
|
|
'name': 'Simple Report',
|
|
'filter_date_range': False,
|
|
'filter_multi_company': 'selector',
|
|
|
|
'column_ids': [
|
|
Command.create({
|
|
'name': 'Balance',
|
|
'expression_label': 'balance',
|
|
'sequence': 1
|
|
})
|
|
],
|
|
|
|
'line_ids': [
|
|
Command.create({
|
|
'name': 'The Report Line',
|
|
'sequence': 1,
|
|
'hierarchy_level': 0,
|
|
'groupby': 'account_id',
|
|
'foldable': True,
|
|
'expression_ids': [Command.clear(), Command.create({
|
|
'label': 'balance',
|
|
'engine': 'domain',
|
|
'formula': ['&', ('partner_id', '=', partner.id), ('balance', '>=', 0)],
|
|
'subformula': 'sum',
|
|
'date_scope': 'from_beginning'
|
|
})]
|
|
})
|
|
]
|
|
})
|
|
basic_line_dict_id = self._get_basic_line_dict_id_from_report_line(simple_report.line_ids[0])
|
|
options = self._generate_options(simple_report, fields.Date.from_string('2022-01-01'), fields.Date.from_string('2022-12-31'))
|
|
options = self._update_comparison_filter(options, simple_report, 'custom', 1, date_to=fields.Date.from_string('2021-12-31'))
|
|
options['unfolded_lines'] = [basic_line_dict_id]
|
|
|
|
lines = simple_report._get_lines(options)
|
|
|
|
self.assertLinesValues(
|
|
lines,
|
|
[ 0, 1, 2],
|
|
[
|
|
('The Report Line', 750, 500),
|
|
('121000 Account Receivable', 750, 500),
|
|
('Total The Report Line', 750, 500),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_financial_report_horizontal_group(self):
|
|
line_id = self._get_basic_line_dict_id_from_report_line_ref('account_reports.account_financial_report_receivable0')
|
|
self.report.horizontal_group_ids |= self.horizontal_group
|
|
|
|
options = self._generate_options(
|
|
self.report,
|
|
fields.Date.from_string('2019-01-01'),
|
|
fields.Date.from_string('2019-12-31'),
|
|
default_options={
|
|
'unfolded_lines': [line_id],
|
|
'selected_horizontal_group_id': self.horizontal_group.id,
|
|
}
|
|
)
|
|
options = self._update_comparison_filter(options, self.report, 'custom', 1, date_to=fields.Date.from_string('2018-12-31'))
|
|
|
|
lines = self.report._get_lines(options)
|
|
self.assertHeadersValues(
|
|
options['column_headers'],
|
|
[
|
|
['As of 12/31/2019', 'As of 12/31/2018'],
|
|
['partner_a', 'partner_b'],
|
|
['code0 account0', 'code1 account1'],
|
|
]
|
|
)
|
|
self.assertLinesValues(
|
|
lines,
|
|
[ 0, 1, 2, 3, 4, 5, 6, 7, 8],
|
|
[
|
|
('ASSETS', 1300.0, 0.0, 25.0, 0.0, 1250.0, 0.0, 0.0, 0.0),
|
|
('Current Assets', 1300.0, 0.0, 25.0, 0.0, 1250.0, 0.0, 0.0, 0.0),
|
|
('Bank and Cash Accounts', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Receivables', 1300.0, 0.0, 25.0, 0.0, 1250.0, 0.0, 0.0, 0.0),
|
|
('code0 account0', 1300.0, 0.0, 25.0, 0.0, 1250.0, 0.0, 0.0, 0.0),
|
|
('Total Receivables', 1300.0, 0.0, 25.0, 0.0, 1250.0, 0.0, 0.0, 0.0),
|
|
('Current Assets', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Prepayments', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Total Current Assets', 1300.0, 0.0, 25.0, 0.0, 1250.0, 0.0, 0.0, 0.0),
|
|
('Plus Fixed Assets', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Plus Non-current Assets', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Total ASSETS', 1300.0, 0.0, 25.0, 0.0, 1250.0, 0.0, 0.0, 0.0),
|
|
|
|
('LIABILITIES', 0.0, 0.0, 0.0, -200.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Current Liabilities', 0.0, 0.0, 0.0, -200.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Current Liabilities', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Payables', 0.0, 0.0, 0.0, -200.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Total Current Liabilities', 0.0, 0.0, 0.0, -200.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Plus Non-current Liabilities', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Total LIABILITIES', 0.0, 0.0, 0.0, -200.0, 0.0, 0.0, 0.0, 0.0),
|
|
|
|
('EQUITY', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Unallocated Earnings', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Current Year Unallocated Earnings', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Current Year Earnings', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Current Year Allocated Earnings', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Total Current Year Unallocated Earnings',0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Previous Years Unallocated Earnings', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Total Unallocated Earnings', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Retained Earnings', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
('Total EQUITY', 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
|
|
|
('LIABILITIES + EQUITY', 0.0, 0.0, 0.0, -200.0, 0.0, 0.0, 0.0, 0.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
def test_hide_if_zero_with_no_formulas(self):
|
|
"""
|
|
Check if a report line stays displayed when hide_if_zero is True and no formulas
|
|
is set on the line but has some child which have balance != 0
|
|
We check also if the line is hidden when all its children have balance == 0
|
|
"""
|
|
account1, account2 = self.env['account.account'].create([{
|
|
'name': "test_financial_report_1",
|
|
'code': "42241",
|
|
'account_type': "asset_fixed",
|
|
}, {
|
|
'name': "test_financial_report_2",
|
|
'code': "42242",
|
|
'account_type': "asset_fixed",
|
|
}])
|
|
|
|
moves = self.env['account.move'].create([
|
|
{
|
|
'move_type': 'entry',
|
|
'date': '2019-04-01',
|
|
'line_ids': [
|
|
(0, 0, {'debit': 3.0, 'credit': 0.0, 'account_id': account1.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 3.0, 'account_id': self.company_data['default_account_revenue'].id}),
|
|
],
|
|
},
|
|
{
|
|
'move_type': 'entry',
|
|
'date': '2019-05-01',
|
|
'line_ids': [
|
|
(0, 0, {'debit': 0.0, 'credit': 1.0, 'account_id': account2.id}),
|
|
(0, 0, {'debit': 1.0, 'credit': 0.0, 'account_id': self.company_data['default_account_revenue'].id}),
|
|
],
|
|
},
|
|
{
|
|
'move_type': 'entry',
|
|
'date': '2019-04-01',
|
|
'line_ids': [
|
|
(0, 0, {'debit': 0.0, 'credit': 3.0, 'account_id': account2.id}),
|
|
(0, 0, {'debit': 3.0, 'credit': 0.0, 'account_id': self.company_data['default_account_revenue'].id}),
|
|
],
|
|
},
|
|
])
|
|
moves.action_post()
|
|
moves.line_ids.flush_recordset()
|
|
|
|
report = self.env["account.report"].create({
|
|
'name': "test_financial_report_sum",
|
|
'column_ids': [
|
|
Command.create({
|
|
'name': "Balance",
|
|
'expression_label': 'balance',
|
|
'sequence': 1,
|
|
}),
|
|
],
|
|
'line_ids': [
|
|
Command.create({
|
|
'name': "Title",
|
|
'code': 'TT',
|
|
'hide_if_zero': True,
|
|
'sequence': 0,
|
|
'children_ids': [
|
|
Command.create({
|
|
'name': "report_line_1",
|
|
'code': 'TEST_L1',
|
|
'sequence': 1,
|
|
'expression_ids': [
|
|
Command.create({
|
|
'label': 'balance',
|
|
'engine': 'domain',
|
|
'formula': f"[('account_id', '=', {account1.id})]",
|
|
'subformula': 'sum',
|
|
'date_scope': 'normal',
|
|
}),
|
|
],
|
|
}),
|
|
Command.create({
|
|
'name': "report_line_2",
|
|
'code': 'TEST_L2',
|
|
'sequence': 2,
|
|
'expression_ids': [
|
|
Command.create({
|
|
'label': 'balance',
|
|
'engine': 'domain',
|
|
'formula': f"[('account_id', '=', {account2.id})]",
|
|
'subformula': 'sum',
|
|
'date_scope': 'normal',
|
|
}),
|
|
],
|
|
}),
|
|
]
|
|
}),
|
|
],
|
|
})
|
|
|
|
# TODO without this, the create() puts newIds in the sublines, and flushing doesn't help. Seems to be an ORM bug.
|
|
self.env.invalidate_all()
|
|
|
|
options = self._generate_options(report, fields.Date.from_string('2019-05-01'), fields.Date.from_string('2019-05-01'))
|
|
options = self._update_comparison_filter(options, report, 'previous_period', 2)
|
|
|
|
self.assertLinesValues(
|
|
report._get_lines(options),
|
|
[ 0, 1, 2, 3],
|
|
[
|
|
("Title", '', '', ''),
|
|
("report_line_1", 3.0, 3.0, 0.0),
|
|
("report_line_2", -4.0, -3.0, 0.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
move = self.env['account.move'].create({
|
|
'move_type': 'entry',
|
|
'date': '2019-05-01',
|
|
'line_ids': [
|
|
(0, 0, {'debit': 0.0, 'credit': 3.0, 'account_id': account1.id}),
|
|
(0, 0, {'debit': 4.0, 'credit': 0.0, 'account_id': account2.id}),
|
|
(0, 0, {'debit': 0.0, 'credit': 1.0, 'account_id': self.company_data['default_account_revenue'].id}),
|
|
],
|
|
})
|
|
|
|
move.action_post()
|
|
move.line_ids.flush_recordset()
|
|
|
|
# With the comparison still on, the lines shouldn't be hidden
|
|
self.assertLinesValues(
|
|
report._get_lines(options),
|
|
[ 0, 1, 2, 3],
|
|
[
|
|
("Title", '', '', ''),
|
|
("report_line_1", 0.0, 3.0, 0.0),
|
|
("report_line_2", 0.0, -3.0, 0.0),
|
|
],
|
|
options,
|
|
)
|
|
|
|
# Removing the comparison should hide the lines, as they will be 0 in every considered period (the current one)
|
|
options = self._update_comparison_filter(options, report, 'previous_period', 0)
|
|
self.assertLinesValues(report._get_lines(options), [0, 1, 2, 3], [], options)
|
|
|
|
def test_option_hierarchy(self):
|
|
""" Check that the report lines are correct when the option "Hierarchy and subtotals is ticked"""
|
|
self.env['account.group'].create({
|
|
'name': 'Sales',
|
|
'code_prefix_start': '40',
|
|
'code_prefix_end': '49',
|
|
})
|
|
|
|
move = self.env['account.move'].create({
|
|
'date': '2020-02-02',
|
|
'line_ids': [
|
|
Command.create({
|
|
'account_id': self.company_data['default_account_revenue'].id,
|
|
'name': 'name',
|
|
})
|
|
],
|
|
})
|
|
move.action_post()
|
|
move.line_ids.flush_recordset()
|
|
profit_and_loss_report = self.env.ref('account_reports.profit_and_loss')
|
|
line_id = self._get_basic_line_dict_id_from_report_line_ref('account_reports.account_financial_report_income0')
|
|
options = self._generate_options(profit_and_loss_report, '2020-02-01', '2020-02-28')
|
|
options['unfolded_lines'] = [line_id]
|
|
options['hierarchy'] = True
|
|
self.env.company.totals_below_sections = False
|
|
lines = profit_and_loss_report._get_lines(options)
|
|
|
|
unfolded_lines = profit_and_loss_report._get_unfolded_lines(lines, line_id)
|
|
unfolded_lines = [{'name': line['name'], 'level': line['level']} for line in unfolded_lines]
|
|
|
|
self.assertEqual(
|
|
unfolded_lines,
|
|
[
|
|
{'level': 5, 'name': 'Operating Income'},
|
|
{'level': 6, 'name': '40-49 Sales'},
|
|
{'level': 7, 'name': '400000 Product Sales'},
|
|
]
|
|
)
|
|
|
|
def test_option_hierarchy_with_no_group_lines(self):
|
|
""" Check that the report lines of 'No Group' have correct ids with the option 'Hierarchy and subtotals' """
|
|
self.env['account.group'].create({
|
|
'name': 'Sales',
|
|
'code_prefix_start': '45',
|
|
'code_prefix_end': '49',
|
|
})
|
|
|
|
move = self.env['account.move'].create({
|
|
'date': '2020-02-02',
|
|
'line_ids': [
|
|
Command.create({
|
|
'account_id': self.company_data['default_account_revenue'].id,
|
|
'name': 'name',
|
|
})
|
|
],
|
|
})
|
|
move.action_post()
|
|
move.line_ids.flush_recordset()
|
|
profit_and_loss_report = self.env.ref('account_reports.profit_and_loss')
|
|
line_id = self._get_basic_line_dict_id_from_report_line_ref('account_reports.account_financial_report_income0')
|
|
options = self._generate_options(profit_and_loss_report, '2020-02-01', '2020-02-28')
|
|
options['unfolded_lines'] = [line_id]
|
|
options['hierarchy'] = True
|
|
self.env.company.totals_below_sections = False
|
|
lines = profit_and_loss_report._get_lines(options)
|
|
lines_array = [{'name': line['name'], 'level': line['level']} for line in lines]
|
|
|
|
self.assertEqual(
|
|
lines_array,
|
|
[
|
|
{'name': 'Net Profit', 'level': 0},
|
|
{'name': 'Income', 'level': 0},
|
|
{'name': 'Gross Profit', 'level': 3},
|
|
{'name': 'Operating Income', 'level': 5},
|
|
{'name': '(No Group)', 'level': 6},
|
|
{'name': '400000 Product Sales', 'level': 7},
|
|
{'name': 'Cost of Revenue', 'level': 5},
|
|
{'name': 'Other Income', 'level': 3},
|
|
{'name': 'Expenses', 'level': 0},
|
|
{'name': 'Expenses', 'level': 3},
|
|
{'name': 'Depreciation', 'level': 3}
|
|
]
|
|
)
|
|
|
|
self.assertEqual(lines[4]['id'], lines[3]['id'] + '|' + '~account.group~')
|