Update indentation, remove empty lines from header. Update test. Update pylint. Remove company_id on computing accounts, since account.group is not a company based model, filtering accounts is done on trial balance report. Update account variables. Improve condition in padding on accounts. Add option to print hierarchy based on defined accounts/computed accounts. Add VAT report, hierarchy from tax tags ans taxes. Fix pylint, xlsx report generation header. Update code to select code_prefix or name. Update code to select code_prefix or name. Update code to select code_prefix or name. Fix domain in base amounts in vat report. Change trial balance code_prefix or name. Update trail balance, add tests for vat report. Update pylint, amounts as monetary, many2one option on generation excels. Update pulint. Add VAT Report in readme. Add VAT Report in readme. Update array_agg. Update array_agg. Update array_agg. Add option in VAT Report to be printed on Tax Tags - Tax Groups. Add widget to hierarchy_on on trial balance.
408 lines
14 KiB
Python
408 lines
14 KiB
Python
# Author: Julien Coux
|
|
# Copyright 2016 Camptocamp SA
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
|
|
import logging
|
|
|
|
from odoo.tests import common
|
|
from odoo.tools import test_reports
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AbstractTest(common.TransactionCase):
|
|
"""Common technical tests for all reports."""
|
|
at_install = False
|
|
post_install = True
|
|
|
|
accounts = {}
|
|
|
|
def with_context(self, *args, **kwargs):
|
|
context = dict(args[0] if args else self.env.context, **kwargs)
|
|
self.env = self.env(context=context)
|
|
return self
|
|
|
|
def _chart_template_create(self):
|
|
transfer_account_id = self.env['account.account.template'].create({
|
|
'code': '000',
|
|
'name': 'Liquidity Transfers',
|
|
'reconcile': True,
|
|
'user_type_id': self.ref(
|
|
"account.data_account_type_current_assets"),
|
|
})
|
|
self.chart = self.env['account.chart.template'].create({
|
|
'name': 'Test COA',
|
|
'code_digits': 4,
|
|
'bank_account_code_prefix': 1014,
|
|
'cash_account_code_prefix': 1014,
|
|
'currency_id': self.ref('base.USD'),
|
|
'transfer_account_id': transfer_account_id.id,
|
|
})
|
|
transfer_account_id.update({
|
|
'chart_template_id': self.chart.id,
|
|
})
|
|
self.env['ir.model.data'].create({
|
|
'res_id': transfer_account_id.id,
|
|
'model': transfer_account_id._name,
|
|
'name': 'Liquidity Transfers',
|
|
})
|
|
act = self.env['account.account.template'].create({
|
|
'code': '001',
|
|
'name': 'Expenses',
|
|
'user_type_id': self.ref("account.data_account_type_expenses"),
|
|
'chart_template_id': self.chart.id,
|
|
'reconcile': True,
|
|
})
|
|
self.env['ir.model.data'].create({
|
|
'res_id': act.id,
|
|
'model': act._name,
|
|
'name': 'expenses',
|
|
})
|
|
act = self.env['account.account.template'].create({
|
|
'code': '002',
|
|
'name': 'Product Sales',
|
|
'user_type_id': self.ref("account.data_account_type_revenue"),
|
|
'chart_template_id': self.chart.id,
|
|
'reconcile': True,
|
|
})
|
|
self.env['ir.model.data'].create({
|
|
'res_id': act.id,
|
|
'model': act._name,
|
|
'name': 'sales',
|
|
})
|
|
act = self.env['account.account.template'].create({
|
|
'code': '003',
|
|
'name': 'Account Receivable',
|
|
'user_type_id': self.ref("account.data_account_type_receivable"),
|
|
'chart_template_id': self.chart.id,
|
|
'reconcile': True,
|
|
})
|
|
self.env['ir.model.data'].create({
|
|
'res_id': act.id,
|
|
'model': act._name,
|
|
'name': 'receivable',
|
|
})
|
|
act = self.env['account.account.template'].create({
|
|
'code': '004',
|
|
'name': 'Account Payable',
|
|
'user_type_id': self.ref("account.data_account_type_payable"),
|
|
'chart_template_id': self.chart.id,
|
|
'reconcile': True,
|
|
})
|
|
self.env['ir.model.data'].create({
|
|
'res_id': act.id,
|
|
'model': act._name,
|
|
'name': 'payable',
|
|
})
|
|
|
|
def _add_chart_of_accounts(self):
|
|
self.company = self.env['res.company'].create({
|
|
'name': 'Spanish test company',
|
|
'external_report_layout': 'standard',
|
|
})
|
|
self.env.ref('base.group_multi_company').write({
|
|
'users': [(4, self.env.uid)],
|
|
})
|
|
self.env.user.write({
|
|
'company_ids': [(4, self.company.id)],
|
|
'company_id': self.company.id,
|
|
})
|
|
self.with_context(
|
|
company_id=self.company.id, force_company=self.company.id)
|
|
wizard = self.env['wizard.multi.charts.accounts'].create({
|
|
'company_id': self.company.id,
|
|
'chart_template_id': self.chart.id,
|
|
'code_digits': 4,
|
|
'currency_id': self.ref('base.USD'),
|
|
'transfer_account_id': self.chart.transfer_account_id.id,
|
|
})
|
|
wizard.onchange_chart_template_id()
|
|
wizard.execute()
|
|
self.revenue = self.env['account.account'].search(
|
|
[('user_type_id', '=', self.ref(
|
|
"account.data_account_type_revenue"))], limit=1)
|
|
self.expense = self.env['account.account'].search(
|
|
[('user_type_id', '=', self.ref(
|
|
"account.data_account_type_expenses"))], limit=1)
|
|
self.receivable = self.env['account.account'].search(
|
|
[('user_type_id', '=', self.ref(
|
|
"account.data_account_type_receivable"))], limit=1)
|
|
self.payable = self.env['account.account'].search(
|
|
[('user_type_id', '=', self.ref(
|
|
"account.data_account_type_payable"))], limit=1)
|
|
return True
|
|
|
|
def _journals_create(self):
|
|
self.journal_sale = self.env['account.journal'].create({
|
|
'company_id': self.company.id,
|
|
'name': 'Test journal for sale',
|
|
'type': 'sale',
|
|
'code': 'TSALE',
|
|
'default_debit_account_id': self.revenue.id,
|
|
'default_credit_account_id': self.revenue.id,
|
|
})
|
|
self.journal_purchase = self.env['account.journal'].create({
|
|
'company_id': self.company.id,
|
|
'name': 'Test journal for purchase',
|
|
'type': 'purchase',
|
|
'code': 'TPUR',
|
|
'default_debit_account_id': self.expense.id,
|
|
'default_credit_account_id': self.expense.id,
|
|
})
|
|
return True
|
|
|
|
def _invoice_create(self):
|
|
self.partner = self.env['res.partner'].create({
|
|
'name': 'Test partner',
|
|
'company_id': self.company.id,
|
|
'property_account_receivable_id': self.receivable.id,
|
|
'property_account_payable_id': self.payable.id,
|
|
})
|
|
|
|
# customer invoice
|
|
customer_invoice_lines = [(0, False, {
|
|
'name': 'Test description #1',
|
|
'account_id': self.revenue.id,
|
|
'quantity': 1.0,
|
|
'price_unit': 100.0,
|
|
}), (0, False, {
|
|
'name': 'Test description #2',
|
|
'account_id': self.revenue.id,
|
|
'quantity': 2.0,
|
|
'price_unit': 25.0,
|
|
})]
|
|
self.invoice_out = self.env['account.invoice'].create({
|
|
'partner_id': self.partner.id,
|
|
'type': 'out_invoice',
|
|
'invoice_line_ids': customer_invoice_lines,
|
|
'account_id': self.partner.property_account_receivable_id.id,
|
|
'journal_id': self.journal_sale.id,
|
|
})
|
|
self.invoice_out.action_invoice_open()
|
|
|
|
# vendor bill
|
|
vendor_invoice_lines = [(0, False, {
|
|
'name': 'Test description #1',
|
|
'account_id': self.revenue.id,
|
|
'quantity': 1.0,
|
|
'price_unit': 100.0,
|
|
}), (0, False, {
|
|
'name': 'Test description #2',
|
|
'account_id': self.revenue.id,
|
|
'quantity': 2.0,
|
|
'price_unit': 25.0,
|
|
})]
|
|
self.invoice_in = self.env['account.invoice'].create({
|
|
'partner_id': self.partner.id,
|
|
'type': 'in_invoice',
|
|
'invoice_line_ids': vendor_invoice_lines,
|
|
'account_id': self.partner.property_account_payable_id.id,
|
|
'journal_id': self.journal_purchase.id,
|
|
})
|
|
self.invoice_in.action_invoice_open()
|
|
|
|
def setUp(self):
|
|
super(AbstractTest, self).setUp()
|
|
|
|
self.with_context()
|
|
self._chart_template_create()
|
|
self._add_chart_of_accounts()
|
|
self._journals_create()
|
|
self._invoice_create()
|
|
|
|
self.model = self._getReportModel()
|
|
|
|
self.qweb_report_name = self._getQwebReportName()
|
|
self.xlsx_report_name = self._getXlsxReportName()
|
|
self.xlsx_action_name = self._getXlsxReportActionName()
|
|
|
|
self.report_title = self._getReportTitle()
|
|
|
|
self.base_filters = self._getBaseFilters()
|
|
self.additional_filters = self._getAdditionalFiltersToBeTested()
|
|
|
|
self.report = self.model.create(self.base_filters)
|
|
self.report.compute_data_for_report()
|
|
|
|
def test_html(self):
|
|
test_reports.try_report(self.env.cr, self.env.uid,
|
|
self.qweb_report_name,
|
|
[self.report.id],
|
|
report_type='qweb-html')
|
|
|
|
def test_qweb(self):
|
|
test_reports.try_report(self.env.cr, self.env.uid,
|
|
self.qweb_report_name,
|
|
[self.report.id],
|
|
report_type='qweb-pdf')
|
|
|
|
def test_xlsx(self):
|
|
test_reports.try_report(self.env.cr, self.env.uid,
|
|
self.xlsx_report_name,
|
|
[self.report.id],
|
|
report_type='xlsx')
|
|
|
|
def test_print(self):
|
|
self.report.print_report('qweb')
|
|
self.report.print_report('xlsx')
|
|
|
|
def test_02_generation_report_html(self):
|
|
"""Check if report HTML is correctly generated"""
|
|
|
|
# Check if returned report action is correct
|
|
report_type = 'qweb-html'
|
|
report_action = self.report.print_report(report_type)
|
|
self.assertDictContainsSubset(
|
|
{
|
|
'type': 'ir.actions.report',
|
|
'report_name': self.qweb_report_name,
|
|
'report_type': 'qweb-html',
|
|
},
|
|
report_action
|
|
)
|
|
|
|
# Check if report template is correct
|
|
report = self.env['ir.actions.report'].search(
|
|
[('report_name', '=', self.qweb_report_name),
|
|
('report_type', '=', report_type)], limit=1)
|
|
self.assertEqual(report.report_type, 'qweb-html')
|
|
|
|
rep = report.render(self.report.ids, {})
|
|
|
|
self.assertTrue(self.report_title.encode('utf8') in rep[0])
|
|
self.assertTrue(
|
|
self.report.account_ids[0].name.encode('utf8') in rep[0]
|
|
)
|
|
|
|
def test_04_compute_data(self):
|
|
"""Check that the SQL queries work with all filters options"""
|
|
|
|
for filters in [{}] + self.additional_filters:
|
|
current_filter = self.base_filters.copy()
|
|
current_filter.update(filters)
|
|
|
|
report = self.model.create(current_filter)
|
|
report.compute_data_for_report()
|
|
|
|
self.assertGreaterEqual(len(report.account_ids), 1)
|
|
|
|
# Same filters with only one account
|
|
current_filter = self.base_filters.copy()
|
|
current_filter.update(filters)
|
|
current_filter.update({
|
|
'filter_account_ids':
|
|
[(6, 0, report.account_ids[0].account_id.ids)],
|
|
})
|
|
|
|
report2 = self.model.create(current_filter)
|
|
report2.compute_data_for_report()
|
|
|
|
self.assertEqual(len(report2.account_ids), 1)
|
|
self.assertEqual(report2.account_ids.name,
|
|
report.account_ids[0].name)
|
|
|
|
if self._partner_test_is_possible(filters):
|
|
# Same filters with only one partner
|
|
report_partner_ids = report.account_ids.mapped('partner_ids')
|
|
partner_ids = report_partner_ids.mapped('partner_id')
|
|
|
|
current_filter = self.base_filters.copy()
|
|
current_filter.update(filters)
|
|
current_filter.update({
|
|
'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
|
|
})
|
|
|
|
report3 = self.model.create(current_filter)
|
|
report3.compute_data_for_report()
|
|
|
|
self.assertGreaterEqual(len(report3.account_ids), 1)
|
|
|
|
report_partner_ids3 = report3.account_ids.mapped('partner_ids')
|
|
partner_ids3 = report_partner_ids3.mapped('partner_id')
|
|
|
|
self.assertEqual(len(partner_ids3), 1)
|
|
self.assertEqual(
|
|
partner_ids3.name,
|
|
partner_ids[0].name
|
|
)
|
|
|
|
# Same filters with only one partner and one account
|
|
report_partner_ids = report3.account_ids.mapped('partner_ids')
|
|
report_account_id = report_partner_ids.filtered(
|
|
lambda p: p.partner_id
|
|
)[0].report_account_id
|
|
|
|
current_filter = self.base_filters.copy()
|
|
current_filter.update(filters)
|
|
current_filter.update({
|
|
'filter_account_ids':
|
|
[(6, 0, report_account_id.account_id.ids)],
|
|
'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
|
|
})
|
|
|
|
report4 = self.model.create(current_filter)
|
|
report4.compute_data_for_report()
|
|
|
|
self.assertEqual(len(report4.account_ids), 1)
|
|
self.assertEqual(report4.account_ids.name,
|
|
report_account_id.account_id.name)
|
|
|
|
report_partner_ids4 = report4.account_ids.mapped('partner_ids')
|
|
partner_ids4 = report_partner_ids4.mapped('partner_id')
|
|
|
|
self.assertEqual(len(partner_ids4), 1)
|
|
self.assertEqual(
|
|
partner_ids4.name,
|
|
partner_ids[0].name
|
|
)
|
|
|
|
def _partner_test_is_possible(self, filters):
|
|
"""
|
|
:return:
|
|
a boolean to indicate if partner test is possible
|
|
with current filters
|
|
"""
|
|
return True
|
|
|
|
def _getReportModel(self):
|
|
"""
|
|
:return: the report model name
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def _getQwebReportName(self):
|
|
"""
|
|
:return: the qweb report name
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def _getXlsxReportName(self):
|
|
"""
|
|
:return: the xlsx report name
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def _getXlsxReportActionName(self):
|
|
"""
|
|
:return: the xlsx report action name
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def _getReportTitle(self):
|
|
"""
|
|
:return: the report title displayed into the report
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def _getBaseFilters(self):
|
|
"""
|
|
:return: the minimum required filters to generate report
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
def _getAdditionalFiltersToBeTested(self):
|
|
"""
|
|
:return: the additional filters to generate report variants
|
|
"""
|
|
raise NotImplementedError()
|