Browse Source

[account_financial_report][IMP] Adds the following features, available in 11.0

- Introduce dependency with module account_group from OCA/account-financial-tools
All reports:
- Rename field to hide accounts at 0 to 'hide_account_at_0'
Trial Balance:
- Add hierarchy levels.
- Add possibility to filter by hierarchy levels
- XLSX format will show the hierarchy levels in bold

General Ledger:
- Add the possibility to filter by analytic tags
- Fixes an error on the default date
Journal Ledger:
- The filter on Journals is now optional. If the user does not choose
a journal, by default it will display all journals.

Aged Partner Balance:
- Fixes an error on the default date
pull/485/head
Jordi Ballester Alomar 6 years ago
parent
commit
0ed18d6c02
  1. 3
      account_financial_report_qweb/__manifest__.py
  2. 31
      account_financial_report_qweb/models/account_group.py
  3. 51
      account_financial_report_qweb/report/abstract_report_xlsx.py
  4. 386
      account_financial_report_qweb/report/general_ledger.py
  5. 2
      account_financial_report_qweb/report/general_ledger_xlsx.py
  6. 4
      account_financial_report_qweb/report/open_items.py
  7. 2
      account_financial_report_qweb/report/open_items_xlsx.py
  8. 4
      account_financial_report_qweb/report/templates/general_ledger.xml
  9. 4
      account_financial_report_qweb/report/templates/open_items.xml
  10. 198
      account_financial_report_qweb/report/templates/trial_balance.xml
  11. 290
      account_financial_report_qweb/report/trial_balance.py
  12. 19
      account_financial_report_qweb/report/trial_balance_xlsx.py
  13. 40
      account_financial_report_qweb/tests/test_general_ledger.py
  14. 4
      account_financial_report_qweb/tests/test_open_items.py
  15. 8
      account_financial_report_qweb/tests/test_trial_balance.py
  16. 3
      account_financial_report_qweb/wizard/aged_partner_balance_wizard.py
  17. 4
      account_financial_report_qweb/wizard/general_ledger_wizard.py
  18. 2
      account_financial_report_qweb/wizard/general_ledger_wizard_view.xml
  19. 9
      account_financial_report_qweb/wizard/journal_report_wizard.py
  20. 7
      account_financial_report_qweb/wizard/open_items_wizard.py
  21. 2
      account_financial_report_qweb/wizard/open_items_wizard_view.xml
  22. 48
      account_financial_report_qweb/wizard/trial_balance_wizard.py
  23. 5
      account_financial_report_qweb/wizard/trial_balance_wizard_view.xml

3
account_financial_report_qweb/__manifest__.py

@ -5,7 +5,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'QWeb Financial Reports',
'version': '10.0.1.5.3',
'version': '10.0.2.0.0',
'category': 'Reporting',
'summary': 'OCA Financial Reports',
'author': 'Camptocamp SA,'
@ -16,6 +16,7 @@
"website": "https://odoo-community.org/",
'depends': [
'account',
'account_group', # account-financial-tools
'date_range',
'report_xlsx',
'report',

31
account_financial_report_qweb/models/account_group.py

@ -0,0 +1,31 @@
# coding: utf-8
# Copyright 2018 Eficent
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class AccountGroup(models.Model):
_inherit = 'account.group'
group_child_ids = fields.One2many(
comodel_name='account.group',
inverse_name='parent_id',
string='Child Groups')
compute_account_ids = fields.Many2many(
'account.account',
compute='_compute_group_accounts',
string="Accounts", store=True)
@api.multi
@api.depends('code_prefix', 'account_ids', 'account_ids.code',
'group_child_ids', 'group_child_ids.account_ids.code')
def _compute_group_accounts(self):
account_obj = self.env['account.account']
accounts = account_obj.search([])
for group in self:
prefix = group.code_prefix if group.code_prefix else group.name
gr_acc = accounts.filtered(
lambda a: a.code.startswith(prefix)).ids
group.compute_account_ids = [(6, 0, gr_acc)]

51
account_financial_report_qweb/report/abstract_report_xlsx.py

@ -23,6 +23,7 @@ class AbstractReportXslx(ReportXlsx):
# Formats
self.format_right = None
self.format_left = None
self.format_right_bold_italic = None
self.format_bold = None
self.format_header_left = None
@ -43,6 +44,7 @@ class AbstractReportXslx(ReportXlsx):
self._define_formats(workbook)
report_name = self._get_report_name()
report_footer = self._get_report_footer()
filters = self._get_report_filters(report)
self.columns = self._get_report_columns(report)
@ -57,6 +59,8 @@ class AbstractReportXslx(ReportXlsx):
self._generate_report_content(workbook, report)
self._write_report_footer(report_footer)
def add_sheet(self, workbook, sheet_name):
return workbook.add_worksheet(sheet_name)
@ -80,6 +84,7 @@ class AbstractReportXslx(ReportXlsx):
"""
self.format_bold = workbook.add_format({'bold': True})
self.format_right = workbook.add_format({'align': 'right'})
self.format_left = workbook.add_format({'align': 'left'})
self.format_right_bold_italic = workbook.add_format(
{'align': 'right', 'bold': True, 'italic': True}
)
@ -107,6 +112,9 @@ class AbstractReportXslx(ReportXlsx):
self.format_amount = workbook.add_format()
self.format_amount.set_num_format(
'#,##0.'+'0'*currency_id.decimal_places)
self.format_amount_bold = workbook.add_format({'bold': True})
self.format_amount_bold.set_num_format(
'#,##0.'+'0'*currency_id.decimal_places)
self.format_percent_bold_italic = workbook.add_format(
{'bold': True, 'italic': True}
)
@ -135,6 +143,18 @@ class AbstractReportXslx(ReportXlsx):
)
self.row_pos += 3
def _write_report_footer(self, footer):
"""Write report footer .
Columns are defined with `_get_report_columns` method.
"""
if footer:
self.row_pos += 1
self.sheet.merge_range(
self.row_pos, 0, self.row_pos, len(self.columns) - 1,
footer, self.format_left
)
self.row_pos += 1
def _write_filters(self, filters):
"""Write one line per filters on starting on current line.
Columns number for filter name is defined
@ -188,10 +208,20 @@ class AbstractReportXslx(ReportXlsx):
value = getattr(line_object, column['field'])
cell_type = column.get('type', 'string')
if cell_type == 'string':
self.sheet.write_string(self.row_pos, col_pos, value or '')
if hasattr(line_object, 'account_group_id') and \
line_object.account_group_id:
self.sheet.write_string(self.row_pos, col_pos, value or '',
self.format_bold)
else:
self.sheet.write_string(self.row_pos, col_pos, value or '')
elif cell_type == 'amount':
if hasattr(line_object, 'account_group_id') and \
line_object.account_group_id:
cell_format = self.format_amount_bold
else:
cell_format = self.format_amount
self.sheet.write_number(
self.row_pos, col_pos, float(value), self.format_amount
self.row_pos, col_pos, float(value), cell_format
)
elif cell_type == 'amount_currency':
if line_object.currency_id:
@ -288,10 +318,16 @@ class AbstractReportXslx(ReportXlsx):
def _get_currency_amt_format(self, line_object):
""" Return amount format specific for each currency. """
format_amt = getattr(self, 'format_amount')
if hasattr(line_object, 'account_group_id') and \
line_object.account_group_id:
format_amt = getattr(self, 'format_amount_bold')
field_prefix = 'format_amount_bold'
else:
format_amt = getattr(self, 'format_amount')
field_prefix = 'format_amount'
if line_object.currency_id:
field_name = \
'format_amount_%s' % line_object.currency_id.name
'%s_%s' % (field_prefix, line_object.currency_id.name)
if hasattr(self, field_name):
format_amt = getattr(self, field_name)
else:
@ -333,6 +369,13 @@ class AbstractReportXslx(ReportXlsx):
"""
raise NotImplementedError()
def _get_report_footer(self):
"""
Allow to define the report footer.
:return: the report footer
"""
return False
def _get_report_columns(self, report):
"""
Allow to define the report columns

386
account_financial_report_qweb/report/general_ledger.py

@ -29,7 +29,7 @@ class GeneralLedgerReport(models.TransientModel):
date_to = fields.Date()
fy_start_date = fields.Date()
only_posted_moves = fields.Boolean()
hide_account_balance_at_0 = fields.Boolean()
hide_account_at_0 = fields.Boolean()
foreign_currency = fields.Boolean()
show_analytic_tags = fields.Boolean()
company_id = fields.Many2one(comodel_name='res.company')
@ -552,7 +552,7 @@ WHERE
OR f.balance IS NOT NULL AND f.balance != 0
)
"""
if self.hide_account_balance_at_0:
if self.hide_account_at_0:
query_inject_account += """
AND
f.balance IS NOT NULL AND f.balance != 0
@ -613,7 +613,7 @@ AND
tuple(self.filter_cost_center_ids.ids),
)
query_inject_account_params += (
self.id or 'NULL',
self.id,
self.env.uid,
)
self.env.cr.execute(query_inject_account, query_inject_account_params)
@ -934,7 +934,7 @@ WHERE
OR f.balance IS NOT NULL AND f.balance != 0
)
"""
if self.hide_account_balance_at_0:
if self.hide_account_at_0:
query_inject_partner += """
AND
f.balance IS NOT NULL AND f.balance != 0
@ -1559,224 +1559,208 @@ WHERE
}
self.env.cr.execute(query_update_analytic_tags, params)
def _get_unaffected_earnings_account_sub_subquery_sum_initial(
self
):
""" Return subquery used to compute sum amounts on
unaffected earnings accounts """
sub_subquery_sum_amounts = """
def _inject_unaffected_earnings_account_values(self):
"""Inject the report values of the unaffected earnings account
for report_general_ledger_qweb_account."""
# Fetch the profit and loss accounts
query_unaffected_earnings_account_ids = """
SELECT a.id
FROM account_account as a
INNER JOIN account_account_type as at
ON at.id = a.user_type_id
WHERE at.include_initial_balance = FALSE
"""
self.env.cr.execute(query_unaffected_earnings_account_ids)
pl_account_ids = [r[0] for r in self.env.cr.fetchall()]
unaffected_earnings_account_ids = \
pl_account_ids + [self.unaffected_earnings_account.id]
# Fetch the current fiscal year start date
date = fields.Datetime.from_string(self.date_from)
res = self.company_id.compute_fiscalyear_dates(date)
fy_start_date = res['date_from']
query_select_previous_fy_unaffected_earnings_params = {
'date_to': fy_start_date,
'company_id': self.company_id.id,
'account_ids': tuple(unaffected_earnings_account_ids),
'analytic_tag_ids': tuple(self.filter_analytic_tag_ids.ids),
}
query_select_previous_fy_unaffected_earnings = ''
q_analytic_tags = ''
if self.filter_analytic_tag_ids:
q_analytic_tags = """
WITH move_lines_on_tags AS
(
SELECT
SUM(ml.balance) AS initial_balance,
0.0 AS final_balance
DISTINCT ml.id AS ml_id
FROM
account_account a
INNER JOIN
account_account_type at ON a.user_type_id = at.id
INNER JOIN
account_move_line ml
ON a.id = ml.account_id
AND ml.date < %(date_from)s
"""
if self.only_posted_moves:
sub_subquery_sum_amounts += """
INNER JOIN
account_move m ON ml.move_id = m.id AND m.state = 'posted'
"""
if self.filter_cost_center_ids:
sub_subquery_sum_amounts += """
account_analytic_tag_account_move_line_rel atml
ON atml.account_move_line_id = ml.id
INNER JOIN
account_analytic_account aa
account_analytic_tag aat
ON
ml.analytic_account_id = aa.id
AND aa.id IN %(cost_center_ids)s
"""
if self.filter_analytic_tag_ids:
sub_subquery_sum_amounts += """
INNER JOIN
move_lines_on_tags ON ml.id = move_lines_on_tags.ml_id
"""
sub_subquery_sum_amounts += """
atml.account_analytic_tag_id = aat.id
WHERE
a.company_id = %(company_id)s
AND
a.id IN %(unaffected_earnings_account_ids)s
aat.id IN %(analytic_tag_ids)s
)
"""
query_select_previous_fy_unaffected_earnings += q_analytic_tags
query_select_previous_fy_unaffected_earnings += """
SELECT sum(ml.balance) as balance
FROM account_move_line as ml
INNER JOIN account_move as am
ON am.id = ml.move_id
INNER JOIN account_journal j
ON am.journal_id = j.id
"""
if self.filter_journal_ids:
sub_subquery_sum_amounts += """
AND
ml.journal_id in %(filter_journal_ids)s """
return sub_subquery_sum_amounts
def _get_unaffected_earnings_account_sub_subquery_sum_final(self):
""" Return subquery used to compute sum amounts on
unaffected earnings accounts """
sub_subquery_sum_amounts = """
SELECT
0.0 AS initial_balance,
SUM(ml.balance) AS final_balance
"""
sub_subquery_sum_amounts += """
FROM
account_account a
INNER JOIN
account_account_type at ON a.user_type_id = at.id
INNER JOIN
account_move_line ml
ON a.id = ml.account_id
AND ml.date <= %(date_to)s
"""
if self.only_posted_moves:
sub_subquery_sum_amounts += """
INNER JOIN
account_move m ON ml.move_id = m.id AND m.state = 'posted'
"""
if self.filter_cost_center_ids:
sub_subquery_sum_amounts += """
INNER JOIN
account_analytic_account aa
ON
ml.analytic_account_id = aa.id
AND aa.id IN %(cost_center_ids)s
"""
if self.filter_analytic_tag_ids:
sub_subquery_sum_amounts += """
INNER JOIN
move_lines_on_tags ON ml.id = move_lines_on_tags.ml_id
query_select_previous_fy_unaffected_earnings += """
INNER JOIN account_analytic_account aa
ON aml.analytic_account_id = aa.id
AND aa.id IN %(cost_center_ids)s
"""
sub_subquery_sum_amounts += """
WHERE
a.company_id = %(company_id)s
AND
a.id IN %(unaffected_earnings_account_ids)s
query_select_previous_fy_unaffected_earnings_params[
'cost_center_ids'] = tuple(self.filter_cost_center_ids.ids)
if self.filter_analytic_tag_ids:
query_select_previous_fy_unaffected_earnings += """
INNER JOIN move_lines_on_tags ON ml.id =
move_lines_on_tags.ml_id
"""
query_select_previous_fy_unaffected_earnings += """
WHERE ml.date < %(date_to)s
AND ml.company_id = %(company_id)s
AND ml.account_id IN %(account_ids)s
"""
if self.filter_journal_ids:
sub_subquery_sum_amounts += """
AND
ml.journal_id in %(filter_journal_ids)s
"""
return sub_subquery_sum_amounts
def _inject_unaffected_earnings_account_values(self):
"""Inject the report values of the unaffected earnings account
for report_general_ledger_qweb_account."""
subquery_sum_amounts = """
query_select_previous_fy_unaffected_earnings += """
AND j.id IN %(journal_ids)s
"""
query_select_previous_fy_unaffected_earnings_params[
'journal_ids'] = tuple(self.filter_journal_ids.ids)
if self.only_posted_moves:
query_select_previous_fy_unaffected_earnings += """
AND am.state = 'posted'
"""
self.env.cr.execute(
query_select_previous_fy_unaffected_earnings,
query_select_previous_fy_unaffected_earnings_params)
res = self.env.cr.fetchone()
unaffected_earnings_initial_balance = res[0] or 0.0
# Now select the current period unaffected earnings,
# excluding the current period P&L.
query_select_period_unaffected_earnings_params = {
'date_from': self.date_from,
'date_to': self.date_to,
'company_id': self.company_id.id,
'unaffected_earnings_id': self.unaffected_earnings_account.id,
'analytic_tag_ids': tuple(self.filter_analytic_tag_ids.ids),
}
query_select_period_unaffected_earnings = ''
if self.filter_analytic_tag_ids:
query_select_period_unaffected_earnings += q_analytic_tags
query_select_period_unaffected_earnings += """
SELECT
SUM(COALESCE(sub.initial_balance, 0.0)) AS initial_balance,
SUM(COALESCE(sub.final_balance, 0.0)) AS final_balance
FROM
(
sum(ml.debit) as sum_debit,
sum(ml.credit) as sum_credit,
sum(ml.balance) as balance
FROM account_move_line as ml
INNER JOIN account_move as am
ON am.id = ml.move_id
INNER JOIN account_journal j
ON am.journal_id = j.id
"""
# Initial balances
subquery_sum_amounts += \
self._get_unaffected_earnings_account_sub_subquery_sum_initial()
subquery_sum_amounts += """
UNION
"""
subquery_sum_amounts += \
self._get_unaffected_earnings_account_sub_subquery_sum_final()
subquery_sum_amounts += """
) sub
if self.filter_cost_center_ids:
query_select_period_unaffected_earnings += """
INNER JOIN account_analytic_account aa
ON aml.analytic_account_id = aa.id
AND aa.id IN %(cost_center_ids)s
"""
query_select_period_unaffected_earnings_params[
'cost_center_ids'] = tuple(self.filter_cost_center_ids.ids)
if self.filter_analytic_tag_ids:
query_select_period_unaffected_earnings += """
INNER JOIN move_lines_on_tags
ON ml.id = move_lines_on_tags.ml_id
"""
query_select_period_unaffected_earnings += """
WHERE am.date >= %(date_from)s
AND ml.date <= %(date_to)s
AND ml.company_id = %(company_id)s
AND ml.account_id = %(unaffected_earnings_id)s
"""
if self.filter_journal_ids:
query_select_period_unaffected_earnings += """
AND j.id IN %(journal_ids)s
"""
query_select_period_unaffected_earnings_params[
'journal_ids'] = tuple(self.filter_journal_ids.ids)
if self.only_posted_moves:
query_select_period_unaffected_earnings += """
AND am.state = 'posted'
"""
self.env.cr.execute(query_select_period_unaffected_earnings,
query_select_period_unaffected_earnings_params)
res = self.env.cr.fetchone()
unaffected_earnings_period_debit = res[0] or 0.0
unaffected_earnings_period_credit = res[1] or 0.0
unaffected_earnings_period_balance = res[2] or 0.0
# pylint: disable=sql-injection
query_inject_account = """
WITH
"""
if self.filter_analytic_tag_ids:
query_inject_account += """
move_lines_on_tags AS
(
SELECT
DISTINCT ml.id AS ml_id
FROM
account_account a
INNER JOIN
account_move_line ml
ON a.id = ml.account_id
INNER JOIN
account_analytic_tag_account_move_line_rel atml
ON atml.account_move_line_id = ml.id
INNER JOIN
account_analytic_tag aat
ON
atml.account_analytic_tag_id = aat.id
WHERE
aat.id IN %(analytic_tag_ids)s
),
"""
query_inject_account += """
sum_amounts AS ( """ + subquery_sum_amounts + """ )
INSERT INTO
report_general_ledger_qweb_account
(
report_id,
create_uid,
create_date,
account_id,
code,
name,
is_partner_account,
initial_balance,
final_balance,
currency_id
INSERT INTO
report_general_ledger_qweb_account (
report_id,
create_uid,
create_date,
account_id,
code,
name,
is_partner_account,
initial_debit,
initial_credit,
initial_balance,
final_debit,
final_credit,
final_balance
)
VALUES (
%(report_id)s,
%(user_id)s,
NOW(),
%(account_id)s,
%(code)s,
%(name)s,
False,
%(initial_debit)s,
%(initial_credit)s,
%(initial_balance)s,
%(final_debit)s,
%(final_credit)s,
%(final_balance)s
)
SELECT
%(report_id)s AS report_id,
%(user_id)s AS create_uid,
NOW() AS create_date,
a.id AS account_id,
a.code,
a.name,
False AS is_partner_account,
COALESCE(i.initial_balance, 0.0) AS initial_balance,
COALESCE(i.final_balance, 0.0) AS final_balance,
c.id as currency_id
FROM
account_account a
LEFT JOIN
res_currency c ON c.id = a.currency_id,
sum_amounts i
WHERE
a.company_id = %(company_id)s
AND a.id = %(unaffected_earnings_account_id)s
"""
query_inject_account_params = {}
if self.filter_analytic_tag_ids:
query_inject_account_params['analytic_tag_ids'] = \
tuple(self.filter_analytic_tag_ids.ids)
query_inject_account_params.update({
'date_from': self.date_from,
'date_to': self.date_to,
'fy_start_date': self.fy_start_date,
})
if self.filter_cost_center_ids:
query_inject_account_params['cost_center_ids'] = \
tuple(self.filter_cost_center_ids.ids)
query_inject_account_params['company_id'] = self.company_id.id
query_inject_account_params['unaffected_earnings_account_id'] = \
self.unaffected_earnings_account.id
query_inject_account_params['report_id'] = self.id
query_inject_account_params['user_id'] = self.env.uid
if self.filter_journal_ids:
query_inject_account_params['filter_journal_ids'] = (tuple(
self.filter_journal_ids.ids,
),)
# Fetch the profit and loss accounts
query_unaffected_earnings_account_ids = """
SELECT a.id
FROM account_account as a
INNER JOIN account_account_type as at
ON at.id = a.user_type_id
WHERE at.include_initial_balance = FALSE
"""
self.env.cr.execute(query_unaffected_earnings_account_ids)
pl_account_ids = [r[0] for r in self.env.cr.fetchall()]
query_inject_account_params['unaffected_earnings_account_ids'] = \
tuple(pl_account_ids + [self.unaffected_earnings_account.id])
initial_debit = unaffected_earnings_initial_balance >= 0 and \
unaffected_earnings_initial_balance or 0
initial_credit = unaffected_earnings_initial_balance < 0 and \
-1 * unaffected_earnings_initial_balance or 0
final_balance = unaffected_earnings_initial_balance + \
unaffected_earnings_period_balance
query_inject_account_params = {
'report_id': self.id,
'user_id': self.env.uid,
'account_id': self.unaffected_earnings_account.id,
'code': self.unaffected_earnings_account.code,
'name': self.unaffected_earnings_account.name,
'initial_debit': initial_debit,
'initial_credit': initial_credit,
'initial_balance': unaffected_earnings_initial_balance,
'final_debit': initial_debit + unaffected_earnings_period_debit,
'final_credit': initial_credit + unaffected_earnings_period_credit,
'final_balance': final_balance,
}
self.env.cr.execute(query_inject_account,
query_inject_account_params)

2
account_financial_report_qweb/report/general_ledger_xlsx.py

@ -89,7 +89,7 @@ class GeneralLedgerXslx(abstract_report_xlsx.AbstractReportXslx):
],
[
_('Account balance at 0 filter'),
_('Hide') if report.hide_account_balance_at_0 else _('Show'),
_('Hide') if report.hide_account_at_0 else _('Show'),
],
[
_('Centralize filter'),

4
account_financial_report_qweb/report/open_items.py

@ -22,7 +22,7 @@ class OpenItemsReport(models.TransientModel):
# Filters fields, used for data computation
date_at = fields.Date()
only_posted_moves = fields.Boolean()
hide_account_balance_at_0 = fields.Boolean()
hide_account_at_0 = fields.Boolean()
foreign_currency = fields.Boolean()
company_id = fields.Many2one(comodel_name='res.company')
filter_account_ids = fields.Many2many(comodel_name='account.account')
@ -188,7 +188,7 @@ class OpenItemsReportCompute(models.TransientModel):
self._inject_line_values(only_empty_partner_line=True)
self._clean_partners_and_accounts()
self._compute_partners_and_accounts_cumul()
if self.hide_account_balance_at_0:
if self.hide_account_at_0:
self._clean_partners_and_accounts(
only_delete_account_balance_at_0=True
)

2
account_financial_report_qweb/report/open_items_xlsx.py

@ -63,7 +63,7 @@ class OpenItemsXslx(abstract_report_xlsx.AbstractReportXslx):
_('All posted entries') if report.only_posted_moves else _(
'All entries')],
[_('Account balance at 0 filter'),
_('Hide') if report.hide_account_balance_at_0 else _('Show')],
_('Hide') if report.hide_account_at_0 else _('Show')],
[_('Show foreign currency'),
_('Yes') if report.foreign_currency else _('No')],
]

4
account_financial_report_qweb/report/templates/general_ledger.xml

@ -93,8 +93,8 @@
<t t-if="not o.only_posted_moves">All entries</t>
</div>
<div class="act_as_cell">
<t t-if="o.hide_account_balance_at_0">Hide</t>
<t t-if="not o.hide_account_balance_at_0">Show</t>
<t t-if="o.hide_account_at_0">Hide</t>
<t t-if="not o.hide_account_at_0">Show</t>
</div>
<div class="act_as_cell">
<t t-if="o.centralize">Yes</t>

4
account_financial_report_qweb/report/templates/open_items.xml

@ -75,8 +75,8 @@
<t t-if="not o.only_posted_moves">All entries</t>
</div>
<div class="act_as_cell">
<t t-if="o.hide_account_balance_at_0">Hide</t>
<t t-if="not o.hide_account_balance_at_0">Show</t>
<t t-if="o.hide_account_at_0">Hide</t>
<t t-if="not o.hide_account_at_0">Show</t>
</div>
</div>
</div>

198
account_financial_report_qweb/report/templates/trial_balance.xml

@ -27,20 +27,29 @@
<!-- Display account lines -->
<t t-if="not show_partner_details">
<div class="act_as_table data_table" style="width: 1325px !important;">
<div class="act_as_table data_table" style="width: 100%;">
<!-- Display account header -->
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_lines_header"/>
<!-- Display each lines -->
<t t-foreach="o.account_ids" t-as="line">
<t t-foreach="o.account_ids.filtered(lambda a: not a.hide_line)" t-as="line">
<t t-set="type" t-value='"account_type"'/>
<!-- Adapt -->
<t t-set="style" t-value="'font-size:8px;'"/>
<t t-set="padding" t-value="line.level * 4"/>
<t t-set="style" t-value="'font-size: ' + str(14 - line.level) + 'px; margin-left: ' + str(line.level * 4) + 'px;'"/>
<t t-if="o.hide_account_at_0">
<t t-set="style" t-value="'font-size: 14px;'"/>
</t>
<t t-if="o.hierarchy_on != 'none'">
<t t-set="style" t-value="'font-size: ' + str(14 - line.level) + 'px; margin-left: ' + str(line.level * 4) + 'px;'"/>
</t>
<t t-if="line.account_group_id">
<t t-set="style" t-value="style + 'font-weight: bold; color: blue;'"/>
</t>
<!-- Display account lines -->
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_line"/>
<!-- Adapt style -->
</t>
</div>
</t>
@ -94,13 +103,13 @@
</t>
</div>
</template>
<template id="account_financial_report_qweb.report_trial_balance_qweb_filters">
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_row labels">
<div class="act_as_cell">Date range filter</div>
<div class="act_as_cell">Target moves filter</div>
<div class="act_as_cell">Account balance at 0 filter</div>
<div class="act_as_cell">Limit hierarchy levels</div>
</div>
<div class="act_as_row">
<div class="act_as_cell">
@ -111,9 +120,17 @@
<t t-if="not o.only_posted_moves">All entries</t>
</div>
<div class="act_as_cell">
<t t-if="o.hide_account_balance_at_0">Hide</t>
<t t-if="not o.hide_account_balance_at_0">Show</t>
<t t-if="o.hide_account_at_0">Hide</t>
<t t-if="not o.hide_account_at_0">Show</t>
</div>
<div class="act_as_cell">
<t t-if="o.limit_hierarchy_level">
Level <span t-field="o.show_hierarchy_level"/>
</t>
<t t-if="not o.limit_hierarchy_level">
No limit
</t>
</div>
</div>
</div>
</template>
@ -141,6 +158,8 @@
<div class="act_as_cell" style="width: 9.64%;">Debit</div>
<!--## Credit-->
<div class="act_as_cell" style="width: 9.64%;">Credit</div>
<!--## Period balance-->
<div class="act_as_cell" style="width: 9.64%;">Period balance</div>
<!--## Ending balance-->
<div class="act_as_cell" style="width: 9.64%;">Ending balance</div>
<t t-if="foreign_currency">
@ -170,6 +189,16 @@
<t t-att-style="style" t-raw="line.code"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="res_model" t-value="'account.group'"/>
<span>
<a t-att-data-active-id="line.account_group_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
t-att-style="style">
<t t-att-style="style" t-raw="line.code"/></a>
</span>
</t>
</div>
</t>
<!--## Account/Partner-->
@ -186,6 +215,16 @@
<t t-att-style="style" t-raw="line.name"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="res_model" t-value="'account.group'"/>
<span>
<a t-att-data-active-id="line.account_group_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
t-att-style="style">
<t t-att-style="style" t-raw="line.name"/></a>
</span>
</t>
</t>
<t t-if="type == 'partner_type'">
<t t-set="account_or_partner_line" t-value="line.report_account_id"/>
@ -214,6 +253,18 @@
<t t-att-style="style" t-raw="line.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="domain"
t-value="[('account_id', 'in', line.compute_account_ids.ids),
('date', '&lt;', o.date_from)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</t>
<t t-if="type == 'partner_type'">
<t t-set="domain"
@ -246,6 +297,20 @@
<t t-att-style="style" t-raw="line.debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="domain"
t-value="[('account_id', 'in', line.compute_account_ids.ids),
('date', '&gt;=', line.report_id.date_from),
('date', '&lt;=', line.report_id.date_to),
('debit', '&lt;&gt;', 0)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</t>
<t t-if="type == 'partner_type'">
<t t-set="domain"
@ -280,6 +345,20 @@
<t t-att-style="style" t-raw="line.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="domain"
t-value="[('account_id', 'in', line.compute_account_ids.ids),
('date', '&gt;=', line.report_id.date_from),
('date', '&lt;=', line.report_id.date_to),
('credit', '&lt;&gt;', 0)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</t>
<t t-if="type == 'partner_type'">
<t t-set="domain"
@ -297,6 +376,51 @@
</span>
</t>
</div>
<!--## Period balance-->
<div class="act_as_cell amount">
<t t-if="type == 'account_type'">
<t t-if="line.account_id">
<t t-set="domain"
t-value="[('account_id', '=', line.account_id.id),
('date', '&gt;=', line.report_id.date_from),
('date', '&lt;=', line.report_id.date_to)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="domain"
t-value="[('account_id', 'in', line.compute_account_ids.ids),
('date', '&gt;=', line.report_id.date_from),
('date', '&lt;=', line.report_id.date_to)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</t>
<t t-if="type == 'partner_type'">
<t t-set="domain"
t-value="[('account_id', '=', line.report_account_id.account_id.id),
('partner_id', '=', line.partner_id.id),
('date', '&gt;=', line.report_account_id.report_id.date_from),
('date', '&lt;=', line.report_account_id.report_id.date_to)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</div>
<!--## Ending balance-->
<div class="act_as_cell amount">
<t t-if="type == 'account_type'">
@ -311,6 +435,17 @@
<t t-att-style="style" t-raw="line.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="domain"
t-value="[('account_id', 'in', line.compute_account_ids.ids)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</t>
<t t-if="type == 'partner_type'">
<t t-set="domain"
@ -323,7 +458,7 @@
t-att-style="style">
<t t-att-style="style" t-raw="line.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</t>
</div>
<t t-if="foreign_currency">
<t t-if="account_or_partner_line.currency_id">
@ -335,9 +470,20 @@
<div class="act_as_cell amount">
<t t-if="type == 'account_type'">
<t t-if="line.account_id">
<t t-set="domain"
t-value="[('account_id', '=', line.account_id.id)]"/>
<span>
<t t-set="domain"
t-value="[('account_id', '=', line.account_id.id)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="domain"
t-value="[('account_id', 'in', line.compute_account_ids.ids)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
@ -363,9 +509,20 @@
<div class="act_as_cell amount">
<t t-if="type == 'account_type'">
<t t-if="line.account_id">
<t t-set="domain"
t-value="[('account_id', '=', line.account_id.id)]"/>
<span>
<t t-set="domain"
t-value="[('account_id', '=', line.account_id.id)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
t-att-style="style">
<t t-att-style="style" t-raw="line.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a>
</span>
</t>
<t t-if="line.account_group_id">
<t t-set="domain"
t-value="[('account_id', 'in', line.compute_account_ids.ids)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
@ -456,6 +613,21 @@
<t t-att-style="style" t-raw="account.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</div>
<!--## Period Balance -->
<div class="act_as_cell amount" style="width: 9.64%;">
<t t-set="domain"
t-value="[('account_id', '=', account.account_id.id),
('date', '&gt;=', account.report_id.date_from),
('date', '&lt;=', account.report_id.date_to),
('period_balance', '&lt;&gt;', 0)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
t-att-style="style">
<t t-att-style="style" t-raw="account.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</div>
<!--## Ending balance-->
<div class="act_as_cell amount" style="width: 9.64%;">
<t t-set="domain"

290
account_financial_report_qweb/report/trial_balance.py

@ -24,14 +24,29 @@ class TrialBalanceReport(models.TransientModel):
date_to = fields.Date()
fy_start_date = fields.Date()
only_posted_moves = fields.Boolean()
hide_account_balance_at_0 = fields.Boolean()
hide_account_at_0 = fields.Boolean()
foreign_currency = fields.Boolean()
company_id = fields.Many2one(comodel_name='res.company')
filter_account_ids = fields.Many2many(comodel_name='account.account')
filter_partner_ids = fields.Many2many(comodel_name='res.partner')
filter_journal_ids = fields.Many2many(comodel_name='account.journal')
show_partner_details = fields.Boolean()
hierarchy_on = fields.Selection(
[('computed', 'Computed Accounts'),
('relation', 'Child Accounts'),
('none', 'No hierarchy')],
string='Hierarchy On',
required=True,
default='computed',
help="""Computed Accounts: Use when the account group have codes
that represent prefixes of the actual accounts.\n
Child Accounts: Use when your account groups are hierarchical.\n
No hierarchy: Use to display just the accounts, without any grouping.
""", period_balance=fields.Float(digits=(16, 2))
)
limit_hierarchy_level = fields.Boolean('Limit hierarchy levels')
show_hierarchy_level = fields.Integer('Hierarchy Levels to display',
default=1)
# General Ledger Report Data fields,
# used as base for compute the data reports
general_ledger_id = fields.Many2one(
@ -49,17 +64,17 @@ class TrialBalanceReportAccount(models.TransientModel):
_name = 'report_trial_balance_qweb_account'
_inherit = 'report_qweb_abstract'
_order = 'code ASC'
_order = 'sequence, code ASC, name'
report_id = fields.Many2one(
comodel_name='report_trial_balance_qweb',
ondelete='cascade',
index=True
)
hide_line = fields.Boolean(compute='_compute_hide_line')
# Data fields, used to keep link with real object
sequence = fields.Integer(index=True, default=0)
level = fields.Integer(index=True, default=0)
sequence = fields.Integer(index=True, default=1)
level = fields.Integer(index=True, default=1)
# Data fields, used to keep link with real object
account_id = fields.Many2one(
@ -67,6 +82,20 @@ class TrialBalanceReportAccount(models.TransientModel):
index=True
)
account_group_id = fields.Many2one(
'account.group',
index=True
)
parent_id = fields.Many2one(
'account.group',
index=True
)
child_account_ids = fields.Char(
string="Accounts")
compute_account_ids = fields.Many2many(
'account.account',
string="Accounts", store=True)
# Data fields, used for report display
code = fields.Char()
name = fields.Char()
@ -75,6 +104,7 @@ class TrialBalanceReportAccount(models.TransientModel):
initial_balance_foreign_currency = fields.Float(digits=(16, 2))
debit = fields.Float(digits=(16, 2))
credit = fields.Float(digits=(16, 2))
period_balance = fields.Float(digits=(16, 2))
currency_id = fields.Many2one(comodel_name='res.currency')
final_balance = fields.Float(digits=(16, 2))
final_balance_foreign_currency = fields.Float(digits=(16, 2))
@ -85,6 +115,21 @@ class TrialBalanceReportAccount(models.TransientModel):
inverse_name='report_account_id'
)
@api.multi
def _compute_hide_line(self):
for rec in self:
report = rec.report_id
rec.hide_line = False
if report.hide_account_at_0 and (
not rec.initial_balance and
not rec.final_balance and
not rec.debit and
not rec.credit):
rec.hide_line = True
elif report.limit_hierarchy_level and \
rec.level > report.show_hierarchy_level:
rec.hide_line = True
class TrialBalanceReportPartner(models.TransientModel):
@ -110,6 +155,7 @@ class TrialBalanceReportPartner(models.TransientModel):
initial_balance_foreign_currency = fields.Float(digits=(16, 2))
debit = fields.Float(digits=(16, 2))
credit = fields.Float(digits=(16, 2))
period_balance = fields.Float(digits=(16, 2))
currency_id = fields.Many2one(comodel_name='res.currency')
final_balance = fields.Float(digits=(16, 2))
final_balance_foreign_currency = fields.Float(digits=(16, 2))
@ -169,7 +215,7 @@ class TrialBalanceReportCompute(models.TransientModel):
'date_from': self.date_from,
'date_to': self.date_to,
'only_posted_moves': self.only_posted_moves,
'hide_account_balance_at_0': self.hide_account_balance_at_0,
'hide_account_at_0': self.hide_account_at_0,
'foreign_currency': self.foreign_currency,
'company_id': self.company_id.id,
'filter_account_ids': [(6, 0, account_ids.ids)],
@ -201,8 +247,21 @@ class TrialBalanceReportCompute(models.TransientModel):
self._inject_account_values(account_ids)
if self.show_partner_details:
self._inject_partner_values()
# Refresh cache because all data are computed with SQL requests
self.invalidate_cache()
if not self.filter_account_ids:
if self.hierarchy_on != 'none':
self._inject_account_group_values()
if self.hierarchy_on == 'computed':
self._update_account_group_computed_values()
else:
self._update_account_group_child_values()
self._update_account_sequence()
self._add_account_group_account_values()
self.refresh()
if not self.filter_account_ids and self.hierarchy_on != 'none':
self._compute_group_accounts()
else:
for line in self.account_ids:
line.write({'level': 0})
def _inject_account_values(self, account_ids):
"""Inject report values for report_trial_balance_qweb_account"""
@ -214,11 +273,13 @@ INSERT INTO
create_uid,
create_date,
account_id,
parent_id,
code,
name,
initial_balance,
debit,
credit,
period_balance,
final_balance,
currency_id,
initial_balance_foreign_currency,
@ -229,11 +290,13 @@ SELECT
%s AS create_uid,
NOW() AS create_date,
acc.id,
acc.group_id,
acc.code,
acc.name,
coalesce(rag.initial_balance, 0) AS initial_balance,
coalesce(rag.final_debit - rag.initial_debit, 0) AS debit,
coalesce(rag.final_credit - rag.initial_credit, 0) AS credit,
coalesce(rag.final_balance - rag.initial_balance, 0) AS period_balance,
coalesce(rag.final_balance, 0) AS final_balance,
rag.currency_id AS currency_id,
coalesce(rag.initial_balance_foreign_currency, 0)
@ -247,9 +310,6 @@ FROM
WHERE
acc.id in %s
"""
if self.hide_account_balance_at_0:
query_inject_account += """ AND
final_balance IS NOT NULL AND final_balance != 0"""
query_inject_account_params = (
self.id,
self.env.uid,
@ -273,6 +333,7 @@ INSERT INTO
initial_balance_foreign_currency,
debit,
credit,
period_balance,
final_balance,
final_balance_foreign_currency
)
@ -286,6 +347,7 @@ SELECT
rpg.initial_balance_foreign_currency AS initial_balance_foreign_currency,
rpg.final_debit - rpg.initial_debit AS debit,
rpg.final_credit - rpg.initial_credit AS credit,
rpg.final_balance - rpg.initial_balance AS period_balance,
rpg.final_balance AS final_balance,
rpg.final_balance_foreign_currency AS final_balance_foreign_currency
FROM
@ -304,3 +366,207 @@ AND ra.report_id = %s
self.id,
)
self.env.cr.execute(query_inject_partner, query_inject_partner_params)
def _inject_account_group_values(self):
"""Inject report values for report_trial_balance_qweb_account"""
query_inject_account_group = """
INSERT INTO
report_trial_balance_qweb_account
(
report_id,
create_uid,
create_date,
account_group_id,
parent_id,
code,
name,
sequence,
level
)
SELECT
%s AS report_id,
%s AS create_uid,
NOW() AS create_date,
accgroup.id,
accgroup.parent_id,
coalesce(accgroup.code_prefix, accgroup.name),
accgroup.name,
accgroup.parent_left * 100000,
accgroup.level
FROM
account_group accgroup"""
query_inject_account_params = (
self.id,
self.env.uid,
)
self.env.cr.execute(query_inject_account_group,
query_inject_account_params)
def _update_account_group_child_values(self):
"""Compute values for report_trial_balance_qweb_account group
in child."""
query_update_account_group = """
WITH computed AS (WITH RECURSIVE cte AS (
SELECT account_group_id, code, account_group_id AS parent_id,
initial_balance, initial_balance_foreign_currency, debit, credit,
period_balance, final_balance, final_balance_foreign_currency
FROM report_trial_balance_qweb_account
WHERE report_id = %s
GROUP BY report_trial_balance_qweb_account.id
UNION ALL
SELECT c.account_group_id, c.code, p.account_group_id,
p.initial_balance, p.initial_balance_foreign_currency, p.debit, p.credit,
p.period_balance, p.final_balance, p.final_balance_foreign_currency
FROM cte c
JOIN report_trial_balance_qweb_account p USING (parent_id)
WHERE p.report_id = %s
)
SELECT account_group_id, code,
sum(initial_balance) AS initial_balance,
sum(initial_balance_foreign_currency) AS initial_balance_foreign_currency,
sum(debit) AS debit,
sum(credit) AS credit,
sum(debit) - sum(credit) AS period_balance,
sum(final_balance) AS final_balance,
sum(final_balance_foreign_currency) AS final_balance_foreign_currency
FROM cte
GROUP BY cte.account_group_id, cte.code
ORDER BY account_group_id
)
UPDATE report_trial_balance_qweb_account
SET initial_balance = computed.initial_balance,
initial_balance_foreign_currency =
computed.initial_balance_foreign_currency,
debit = computed.debit,
credit = computed.credit,
period_balance = computed.period_balance,
final_balance = computed.final_balance,
final_balance_foreign_currency =
computed.final_balance_foreign_currency
FROM computed
WHERE report_trial_balance_qweb_account.account_group_id =
computed.account_group_id
AND report_trial_balance_qweb_account.report_id = %s
"""
query_update_account_params = (self.id, self.id, self.id,)
self.env.cr.execute(query_update_account_group,
query_update_account_params)
def _add_account_group_account_values(self):
"""Compute values for report_trial_balance_qweb_account group in
child."""
query_update_account_group = """
DROP AGGREGATE IF EXISTS array_concat_agg(anyarray);
CREATE AGGREGATE array_concat_agg(anyarray) (
SFUNC = array_cat,
STYPE = anyarray
);
WITH aggr AS(WITH computed AS (WITH RECURSIVE cte AS (
SELECT account_group_id, account_group_id AS parent_id,
ARRAY[account_id]::int[] as child_account_ids
FROM report_trial_balance_qweb_account
WHERE report_id = %s
GROUP BY report_trial_balance_qweb_account.id
UNION ALL
SELECT c.account_group_id, p.account_group_id, ARRAY[p.account_id]::int[]
FROM cte c
JOIN report_trial_balance_qweb_account p USING (parent_id)
WHERE p.report_id = %s
)
SELECT account_group_id,
array_concat_agg(DISTINCT child_account_ids)::int[] as child_account_ids
FROM cte
GROUP BY cte.account_group_id, cte.child_account_ids
ORDER BY account_group_id
)
SELECT account_group_id,
array_concat_agg(DISTINCT child_account_ids)::int[]
AS child_account_ids from computed
GROUP BY account_group_id)
UPDATE report_trial_balance_qweb_account
SET child_account_ids = aggr.child_account_ids
FROM aggr
WHERE report_trial_balance_qweb_account.account_group_id =
aggr.account_group_id
AND report_trial_balance_qweb_account.report_id = %s
"""
query_update_account_params = (self.id, self.id, self.id,)
self.env.cr.execute(query_update_account_group,
query_update_account_params)
def _update_account_group_computed_values(self):
"""Compute values for report_trial_balance_qweb_account group
in compute."""
query_update_account_group = """
WITH RECURSIVE accgroup AS
(SELECT
accgroup.id,
sum(coalesce(ra.initial_balance, 0)) as initial_balance,
sum(coalesce(ra.initial_balance_foreign_currency, 0))
as initial_balance_foreign_currency,
sum(coalesce(ra.debit, 0)) as debit,
sum(coalesce(ra.credit, 0)) as credit,
sum(coalesce(ra.debit, 0)) - sum(coalesce(ra.credit, 0)) as period_balance,
sum(coalesce(ra.final_balance, 0)) as final_balance,
sum(coalesce(ra.final_balance_foreign_currency, 0))
as final_balance_foreign_currency
FROM
account_group accgroup
LEFT OUTER JOIN account_account AS acc
ON strpos(acc.code, accgroup.code_prefix) = 1
LEFT OUTER JOIN report_trial_balance_qweb_account AS ra
ON ra.account_id = acc.id
WHERE ra.report_id = %s
GROUP BY accgroup.id
)
UPDATE report_trial_balance_qweb_account
SET initial_balance = accgroup.initial_balance,
initial_balance_foreign_currency =
accgroup.initial_balance_foreign_currency,
debit = accgroup.debit,
credit = accgroup.credit,
period_balance = accgroup.period_balance,
final_balance = accgroup.final_balance,
final_balance_foreign_currency =
accgroup.final_balance_foreign_currency
FROM accgroup
WHERE report_trial_balance_qweb_account.account_group_id = accgroup.id
"""
query_update_account_params = (self.id,)
self.env.cr.execute(query_update_account_group,
query_update_account_params)
def _update_account_sequence(self):
"""Compute sequence, level for report_trial_balance_qweb_
account account."""
query_update_account_group = """
UPDATE report_trial_balance_qweb_account
SET sequence = newline.sequence + 1,
level = newline.level + 1
FROM report_trial_balance_qweb_account as newline
WHERE newline.account_group_id = report_trial_balance_qweb_account.parent_id
AND report_trial_balance_qweb_account.report_id = newline.report_id
AND report_trial_balance_qweb_account.account_id is not null
AND report_trial_balance_qweb_account.report_id = %s"""
query_update_account_params = (self.id,)
self.env.cr.execute(query_update_account_group,
query_update_account_params)
def _compute_group_accounts(self):
groups = self.account_ids.filtered(
lambda a: a.account_group_id is not False)
for group in groups:
if self.hierarchy_on == 'compute':
group.compute_account_ids = \
group.account_group_id.compute_account_ids
else:
if group.child_account_ids:
chacc = group.child_account_ids.replace(
'}', '').replace('{', '').split(',')
if 'NULL' in chacc:
chacc.remove('NULL')
if chacc:
group.compute_account_ids = [
(6, 0, [int(g) for g in chacc])]

19
account_financial_report_qweb/report/trial_balance_xlsx.py

@ -35,7 +35,11 @@ class TrialBalanceXslx(abstract_report_xlsx.AbstractReportXslx):
'field': 'credit',
'type': 'amount',
'width': 14},
5: {'header': _('Ending balance'),
5: {'header': _('Period balance'),
'field': 'period_balance',
'type': 'amount',
'width': 14},
6: {'header': _('Ending balance'),
'field': 'final_balance',
'type': 'amount',
'width': 14},
@ -72,7 +76,11 @@ class TrialBalanceXslx(abstract_report_xlsx.AbstractReportXslx):
'field': 'credit',
'type': 'amount',
'width': 14},
4: {'header': _('Ending balance'),
4: {'header': _('Period balance'),
'field': 'period_balance',
'type': 'amount',
'width': 14},
5: {'header': _('Ending balance'),
'field': 'final_balance',
'type': 'amount',
'width': 14},
@ -103,9 +111,12 @@ class TrialBalanceXslx(abstract_report_xlsx.AbstractReportXslx):
_('All posted entries') if report.only_posted_moves
else _('All entries')],
[_('Account balance at 0 filter'),
_('Hide') if report.hide_account_balance_at_0 else _('Show')],
_('Hide') if report.hide_account_at_0 else _('Show')],
[_('Show foreign currency'),
_('Yes') if report.foreign_currency else _('No')],
[_('Limit hierarchy levels'),
_('Level %s' % report.show_hierarchy_level) if
report.limit_hierarchy_level else _('No limit')],
]
def _get_col_count_filter_name(self):
@ -121,7 +132,7 @@ class TrialBalanceXslx(abstract_report_xlsx.AbstractReportXslx):
self.write_array_header()
# For each account
for account in report.account_ids:
for account in report.account_ids.filtered(lambda a: not a.hide_line):
if not report.show_partner_details:
# Display account lines
self.write_line(account, 'account')

40
account_financial_report_qweb/tests/test_general_ledger.py

@ -42,14 +42,14 @@ class TestGeneralLedger(a_t_f_c.AbstractTestForeignCurrency):
def _getAdditionalFiltersToBeTested(self):
additional_filters = [
{'only_posted_moves': True},
{'hide_account_balance_at_0': True},
{'hide_account_at_0': True},
{'centralize': True},
{'only_posted_moves': True, 'hide_account_balance_at_0': True},
{'only_posted_moves': True, 'hide_account_at_0': True},
{'only_posted_moves': True, 'centralize': True},
{'hide_account_balance_at_0': True, 'centralize': True},
{'hide_account_at_0': True, 'centralize': True},
{
'only_posted_moves': True,
'hide_account_balance_at_0': True,
'hide_account_at_0': True,
'centralize': True
},
]
@ -155,7 +155,7 @@ class TestGeneralLedgerReport(common.TransactionCase):
'date_from': self.fy_date_start,
'date_to': self.fy_date_end,
'only_posted_moves': True,
'hide_account_balance_at_0': False,
'hide_account_at_0': False,
'company_id': company.id,
'fy_start_date': self.fy_date_start,
})
@ -377,10 +377,10 @@ class TestGeneralLedgerReport(common.TransactionCase):
# Check the initial and final balance
self.assertEqual(lines['unaffected'].initial_debit, 0)
self.assertEqual(lines['unaffected'].initial_credit, 0)
self.assertEqual(lines['unaffected'].initial_credit, 1000)
self.assertEqual(lines['unaffected'].initial_balance, -1000)
self.assertEqual(lines['unaffected'].final_debit, -0)
self.assertEqual(lines['unaffected'].final_credit, 0)
self.assertEqual(lines['unaffected'].final_debit, 0)
self.assertEqual(lines['unaffected'].final_credit, 1000)
self.assertEqual(lines['unaffected'].final_balance, -1000)
# Add reversale move of the initial move the first day of fiscal year
@ -402,11 +402,11 @@ class TestGeneralLedgerReport(common.TransactionCase):
# Check the initial and final balance
self.assertEqual(lines['unaffected'].initial_debit, 0)
self.assertEqual(lines['unaffected'].initial_credit, 0)
self.assertEqual(lines['unaffected'].initial_credit, 1000)
self.assertEqual(lines['unaffected'].initial_balance, -1000)
self.assertEqual(lines['unaffected'].final_debit, 0)
self.assertEqual(lines['unaffected'].final_credit, 0)
self.assertEqual(lines['unaffected'].final_balance, -1000)
self.assertEqual(lines['unaffected'].final_debit, 1000)
self.assertEqual(lines['unaffected'].final_credit, 1000)
self.assertEqual(lines['unaffected'].final_balance, 0)
# Add another move at the end day of fiscal year
# to check that it correctly used on report
@ -426,11 +426,11 @@ class TestGeneralLedgerReport(common.TransactionCase):
# Check the initial and final balance
self.assertEqual(lines['unaffected'].initial_debit, 0)
self.assertEqual(lines['unaffected'].initial_credit, 0)
self.assertEqual(lines['unaffected'].initial_credit, 1000)
self.assertEqual(lines['unaffected'].initial_balance, -1000)
self.assertEqual(lines['unaffected'].final_debit, 0)
self.assertEqual(lines['unaffected'].final_credit, 0)
self.assertEqual(lines['unaffected'].final_balance, -4000)
self.assertEqual(lines['unaffected'].final_debit, 1000)
self.assertEqual(lines['unaffected'].final_credit, 4000)
self.assertEqual(lines['unaffected'].final_balance, -3000)
def test_04_unaffected_account_balance_2_years(self):
# Generate the general ledger line
@ -460,10 +460,10 @@ class TestGeneralLedgerReport(common.TransactionCase):
self.assertEqual(len(lines['unaffected']), 1)
# Check the initial and final balance
self.assertEqual(lines['unaffected'].initial_debit, 0)
self.assertEqual(lines['unaffected'].initial_debit, 1000)
self.assertEqual(lines['unaffected'].initial_credit, 0)
self.assertEqual(lines['unaffected'].initial_balance, 1000)
self.assertEqual(lines['unaffected'].final_debit, 0)
self.assertEqual(lines['unaffected'].final_debit, 1000)
self.assertEqual(lines['unaffected'].final_credit, 0)
self.assertEqual(lines['unaffected'].final_balance, 1000)
@ -493,9 +493,9 @@ class TestGeneralLedgerReport(common.TransactionCase):
self.assertEqual(len(lines['unaffected']), 1)
# Check the initial and final balance
self.assertEqual(lines['unaffected'].initial_debit, 0)
self.assertEqual(lines['unaffected'].initial_debit, 500)
self.assertEqual(lines['unaffected'].initial_credit, 0)
self.assertEqual(lines['unaffected'].initial_balance, 500)
self.assertEqual(lines['unaffected'].final_debit, 0)
self.assertEqual(lines['unaffected'].final_debit, 500)
self.assertEqual(lines['unaffected'].final_credit, 0)
self.assertEqual(lines['unaffected'].final_balance, 500)

4
account_financial_report_qweb/tests/test_open_items.py

@ -37,6 +37,6 @@ class TestOpenItems(a_t_f_c.AbstractTestForeignCurrency):
def _getAdditionalFiltersToBeTested(self):
return [
{'only_posted_moves': True},
{'hide_account_balance_at_0': True},
{'only_posted_moves': True, 'hide_account_balance_at_0': True},
{'hide_account_at_0': True},
{'only_posted_moves': True, 'hide_account_at_0': True},
]

8
account_financial_report_qweb/tests/test_trial_balance.py

@ -41,14 +41,14 @@ class TestTrialBalance(a_t_f_c.AbstractTestForeignCurrency):
def _getAdditionalFiltersToBeTested(self):
return [
{'only_posted_moves': True},
{'hide_account_balance_at_0': True},
{'hide_account_at_0': True},
{'show_partner_details': True},
{'only_posted_moves': True, 'hide_account_balance_at_0': True},
{'only_posted_moves': True, 'hide_account_at_0': True},
{'only_posted_moves': True, 'show_partner_details': True},
{'hide_account_balance_at_0': True, 'show_partner_details': True},
{'hide_account_at_0': True, 'show_partner_details': True},
{
'only_posted_moves': True,
'hide_account_balance_at_0': True,
'hide_account_at_0': True,
'show_partner_details': True
},
]

3
account_financial_report_qweb/wizard/aged_partner_balance_wizard.py

@ -4,7 +4,6 @@
# Copyright 2016 Camptocamp SA, Onestein B.V.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from datetime import datetime
from odoo import api, fields, models
from odoo.tools.safe_eval import safe_eval
@ -21,7 +20,7 @@ class AgedPartnerBalance(models.TransientModel):
string='Company'
)
date_at = fields.Date(required=True,
default=fields.Date.to_string(datetime.today()))
default=fields.Date.context_today)
target_move = fields.Selection([('posted', 'All Posted Entries'),
('all', 'All Entries')],
string='Target Moves',

4
account_financial_report_qweb/wizard/general_ledger_wizard.py

@ -38,7 +38,7 @@ class GeneralLedgerReportWizard(models.TransientModel):
)
centralize = fields.Boolean(string='Activate centralization',
default=True)
hide_account_balance_at_0 = fields.Boolean(
hide_account_at_0 = fields.Boolean(
string='Hide account ending balance at 0',
help='Use this filter to hide an account or a partner '
'with an ending balance at 0. '
@ -181,7 +181,7 @@ class GeneralLedgerReportWizard(models.TransientModel):
'date_from': self.date_from,
'date_to': self.date_to,
'only_posted_moves': self.target_move == 'posted',
'hide_account_balance_at_0': self.hide_account_balance_at_0,
'hide_account_at_0': self.hide_account_at_0,
'foreign_currency': self.foreign_currency,
'show_analytic_tags': self.show_analytic_tags,
'company_id': self.company_id.id,

2
account_financial_report_qweb/wizard/general_ledger_wizard_view.xml

@ -22,7 +22,7 @@
<group name="other_filters">
<field name="target_move" widget="radio"/>
<field name="centralize"/>
<field name="hide_account_balance_at_0"/>
<field name="hide_account_at_0"/>
<field name="foreign_currency"/>
<field name="show_analytic_tags"/>
</group>

9
account_financial_report_qweb/wizard/journal_report_wizard.py

@ -36,7 +36,7 @@ class JournalReportWizard(models.TransientModel):
comodel_name='account.journal',
string="Journals",
domain="[('company_id', '=', company_id)]",
required=True,
required=False,
)
move_target = fields.Selection(
selection='_get_move_targets',
@ -119,13 +119,18 @@ class JournalReportWizard(models.TransientModel):
@api.multi
def _prepare_report_journal(self):
self.ensure_one()
journals = self.journal_ids
if not journals:
# Not selecting a journal means that we'll display all journals
journals = self.env['account.journal'].search(
[('company_id', '=', self.company_id.id)])
return {
'date_from': self.date_from,
'date_to': self.date_to,
'move_target': self.move_target,
'foreign_currency': self.foreign_currency,
'company_id': self.company_id.id,
'journal_ids': [(6, 0, self.journal_ids.ids)],
'journal_ids': [(6, 0, journals.ids)],
'sort_option': self.sort_option,
'group_option': self.group_option,
'with_account_name': self.with_account_name,

7
account_financial_report_qweb/wizard/open_items_wizard.py

@ -4,7 +4,6 @@
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from datetime import datetime
from odoo import models, fields, api
from odoo.tools.safe_eval import safe_eval
@ -21,7 +20,7 @@ class OpenItemsReportWizard(models.TransientModel):
string='Company'
)
date_at = fields.Date(required=True,
default=fields.Date.to_string(datetime.today()))
default=fields.Date.context_today)
target_move = fields.Selection([('posted', 'All Posted Entries'),
('all', 'All Entries')],
string='Target Moves',
@ -32,7 +31,7 @@ class OpenItemsReportWizard(models.TransientModel):
string='Filter accounts',
domain=[('reconcile', '=', True)],
)
hide_account_balance_at_0 = fields.Boolean(
hide_account_at_0 = fields.Boolean(
string='Hide account ending balance at 0',
help='Use this filter to hide an account or a partner '
'with an ending balance at 0. '
@ -122,7 +121,7 @@ class OpenItemsReportWizard(models.TransientModel):
return {
'date_at': self.date_at,
'only_posted_moves': self.target_move == 'posted',
'hide_account_balance_at_0': self.hide_account_balance_at_0,
'hide_account_at_0': self.hide_account_at_0,
'foreign_currency': self.foreign_currency,
'company_id': self.company_id.id,
'filter_account_ids': [(6, 0, self.account_ids.ids)],

2
account_financial_report_qweb/wizard/open_items_wizard_view.xml

@ -16,7 +16,7 @@
</group>
<group name="other_filters">
<field name="target_move" widget="radio"/>
<field name="hide_account_balance_at_0"/>
<field name="hide_account_at_0"/>
<field name="foreign_currency"/>
</group>
</group>

48
account_financial_report_qweb/wizard/trial_balance_wizard.py

@ -2,10 +2,12 @@
# Author: Julien Coux
# Copyright 2016 Camptocamp SA
# Copyright 2017 Akretion - Alexis de Lattre
# Copyright 2018 Eficent Business and IT Consuting Services, S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, fields, api
from odoo import api, fields, models, _
from odoo.tools.safe_eval import safe_eval
from odoo.exceptions import UserError
class TrialBalanceReportWizard(models.TransientModel):
@ -31,16 +33,31 @@ class TrialBalanceReportWizard(models.TransientModel):
string='Target Moves',
required=True,
default='all')
hierarchy_on = fields.Selection(
[('computed', 'Computed Accounts'),
('relation', 'Child Accounts'),
('none', 'No hierarchy')],
string='Hierarchy On',
required=True,
default='computed',
help="""Computed Accounts: Use when the account group have codes
that represent prefixes of the actual accounts.\n
Child Accounts: Use when your account groups are hierarchical.\n
No hierarchy: Use to display just the accounts, without any grouping.
""",
)
limit_hierarchy_level = fields.Boolean('Limit hierarchy levels')
show_hierarchy_level = fields.Integer('Hierarchy Levels to display',
default=1)
account_ids = fields.Many2many(
comodel_name='account.account',
string='Filter accounts',
)
hide_account_balance_at_0 = fields.Boolean(
string='Hide account ending balance at 0',
help='Use this filter to hide an account or a partner '
'with an ending balance at 0. '
'If partners are filtered, '
'debits and credits totals will not match the trial balance.'
hide_account_at_0 = fields.Boolean(
string='Hide accounts at 0', default=True,
help='When this option is enabled, the trial balance will '
'not display accounts that have initial balance = '
'debit = credit = end balance = 0',
)
receivable_accounts_only = fields.Boolean()
payable_accounts_only = fields.Boolean()
@ -66,6 +83,14 @@ class TrialBalanceReportWizard(models.TransientModel):
'will display initial and final balance in that currency.'
)
@api.multi
@api.constrains('hierarchy_on', 'show_hierarchy_level')
def _check_show_hierarchy_level(self):
for rec in self:
if rec.hierarchy_on != 'none' and rec.show_hierarchy_level <= 0:
raise UserError(_('The hierarchy level to filter on must be '
'greater than 0.'))
@api.depends('date_from')
def _compute_fy_start_date(self):
for wiz in self.filtered('date_from'):
@ -131,10 +156,10 @@ class TrialBalanceReportWizard(models.TransientModel):
"""Handle partners change."""
if self.show_partner_details:
self.receivable_accounts_only = self.payable_accounts_only = True
self.hide_account_balance_at_0 = True
self.hide_account_at_0 = True
else:
self.receivable_accounts_only = self.payable_accounts_only = False
self.hide_account_balance_at_0 = False
self.hide_account_at_0 = False
@api.multi
def button_export_html(self):
@ -171,13 +196,16 @@ class TrialBalanceReportWizard(models.TransientModel):
'date_from': self.date_from,
'date_to': self.date_to,
'only_posted_moves': self.target_move == 'posted',
'hide_account_balance_at_0': self.hide_account_balance_at_0,
'hide_account_at_0': self.hide_account_at_0,
'foreign_currency': self.foreign_currency,
'company_id': self.company_id.id,
'filter_account_ids': [(6, 0, self.account_ids.ids)],
'filter_partner_ids': [(6, 0, self.partner_ids.ids)],
'filter_journal_ids': [(6, 0, self.journal_ids.ids)],
'fy_start_date': self.fy_start_date,
'hierarchy_on': self.hierarchy_on,
'limit_hierarchy_level': self.limit_hierarchy_level,
'show_hierarchy_level': self.show_hierarchy_level,
'show_partner_details': self.show_partner_details,
}

5
account_financial_report_qweb/wizard/trial_balance_wizard_view.xml

@ -21,8 +21,11 @@
</group>
<group name="other_filters">
<field name="target_move" widget="radio"/>
<field name="hide_account_balance_at_0"/>
<field name="hide_account_at_0"/>
<field name="show_partner_details"/>
<field name="hierarchy_on" widget="radio" attrs="{'invisible':[('show_partner_details','=',True)]}"/>
<field name="limit_hierarchy_level" attrs="{'invisible':['|', ('hierarchy_on','=','none'),('show_partner_details','=',True)]}"/>
<field name="show_hierarchy_level" attrs="{'invisible':[('limit_hierarchy_level','=', False)]}"/>
<field name="foreign_currency"/>
</group>
</group>

Loading…
Cancel
Save