Browse Source

add an extra line for P&L application so that the trial balance zeroes in the

balance, and total debits = total credits
pull/481/head
Jordi Ballester Alomar 6 years ago
parent
commit
6110d0e78c
  1. 24
      account_financial_report/report/abstract_report_xlsx.py
  2. 5
      account_financial_report/report/templates/trial_balance.xml
  3. 132
      account_financial_report/report/trial_balance.py
  4. 7
      account_financial_report/report/trial_balance_xlsx.py
  5. 111
      account_financial_report/tests/test_trial_balance.py

24
account_financial_report/report/abstract_report_xlsx.py

@ -21,6 +21,7 @@ class AbstractReportXslx(models.AbstractModel):
# Formats # Formats
self.format_right = None self.format_right = None
self.format_left = None
self.format_right_bold_italic = None self.format_right_bold_italic = None
self.format_bold = None self.format_bold = None
self.format_header_left = None self.format_header_left = None
@ -41,6 +42,7 @@ class AbstractReportXslx(models.AbstractModel):
self._define_formats(workbook) self._define_formats(workbook)
report_name = self._get_report_name() report_name = self._get_report_name()
report_footer = self._get_report_footer()
filters = self._get_report_filters(report) filters = self._get_report_filters(report)
self.columns = self._get_report_columns(report) self.columns = self._get_report_columns(report)
self.workbook = workbook self.workbook = workbook
@ -54,6 +56,8 @@ class AbstractReportXslx(models.AbstractModel):
self._generate_report_content(workbook, report) self._generate_report_content(workbook, report)
self._write_report_footer(report_footer)
def _define_formats(self, workbook): def _define_formats(self, workbook):
""" Add cell formats to current workbook. """ Add cell formats to current workbook.
Those formats can be used on all cell. Those formats can be used on all cell.
@ -71,6 +75,7 @@ class AbstractReportXslx(models.AbstractModel):
""" """
self.format_bold = workbook.add_format({'bold': True}) self.format_bold = workbook.add_format({'bold': True})
self.format_right = workbook.add_format({'align': 'right'}) self.format_right = workbook.add_format({'align': 'right'})
self.format_left = workbook.add_format({'align': 'left'})
self.format_right_bold_italic = workbook.add_format( self.format_right_bold_italic = workbook.add_format(
{'align': 'right', 'bold': True, 'italic': True} {'align': 'right', 'bold': True, 'italic': True}
) )
@ -120,6 +125,18 @@ class AbstractReportXslx(models.AbstractModel):
) )
self.row_pos += 3 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): def _write_filters(self, filters):
"""Write one line per filters on starting on current line. """Write one line per filters on starting on current line.
Columns number for filter name is defined Columns number for filter name is defined
@ -322,6 +339,13 @@ class AbstractReportXslx(models.AbstractModel):
""" """
raise NotImplementedError() 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): def _get_report_columns(self, report):
""" """
Allow to define the report columns Allow to define the report columns

5
account_financial_report/report/templates/trial_balance.xml

@ -104,9 +104,8 @@
</div> </div>
</template> </template>
<template id="account_financial_report.report_trial_balance_footer"> <template id="account_financial_report.report_trial_balance_footer">
(*) This report automates the application of the current period Profit and Loss balances to the Undistributed Profit/Loss account.
Therefore to check the correctness of the Trial Balance, consider that the Total Ending Balance is
going to be equal to the period's total Profit &amp; Loss, instead of zero.
(*) This report applies the current year Profit and Loss balances to the Undistributed Profit/Loss account.
To ensure that the Trial Balance totals total to zero, this line represents the reversal of the current year P &amp; L Balance.
</template> </template>
<template id="account_financial_report.report_trial_balance_filters"> <template id="account_financial_report.report_trial_balance_filters">

132
account_financial_report/report/trial_balance.py

@ -317,6 +317,10 @@ WHERE
('company_id', '=', self.company_id.id) ('company_id', '=', self.company_id.id)
]) ])
if self.filter_account_ids and unaffected_earnings_account not in \
self.filter_account_ids:
return True
query_unaffected_earnings_account_ids = """ query_unaffected_earnings_account_ids = """
SELECT a.id SELECT a.id
FROM account_account as a FROM account_account as a
@ -332,11 +336,17 @@ WHERE
SELECT sum(aml.debit) as sum_debit, SELECT sum(aml.debit) as sum_debit,
sum(aml.credit) as sum_credit sum(aml.credit) as sum_credit
FROM account_move_line as aml FROM account_move_line as aml
WHERE date >= %(date_from)s
AND date <= %(date_to)s
AND company_id = %(company_id)s
AND account_id IN %(account_ids)s
INNER JOIN account_move as am
ON am.id = aml.move_id
WHERE aml.date >= %(date_from)s
AND aml.date <= %(date_to)s
AND aml.company_id = %(company_id)s
AND aml.account_id IN %(account_ids)s
""" """
if self.only_posted_moves:
query_select_period_balances += """
AND am.state = 'posted'
"""
query_select_period_balances_params = { query_select_period_balances_params = {
'date_from': self.date_from, 'date_from': self.date_from,
'date_to': self.date_to, 'date_to': self.date_to,
@ -346,8 +356,6 @@ WHERE
self.env.cr.execute(query_select_period_balances, self.env.cr.execute(query_select_period_balances,
query_select_period_balances_params) query_select_period_balances_params)
sum_debit, sum_credit = self.env.cr.fetchone() sum_debit, sum_credit = self.env.cr.fetchone()
unaffected_earnings_account_name = \
'%s (*)' % unaffected_earnings_account.name
query_update_unaffected_earnings_account = """ query_update_unaffected_earnings_account = """
UPDATE report_trial_balance_account UPDATE report_trial_balance_account
SET SET
@ -361,10 +369,120 @@ WHERE
'sum_credit': sum_credit, 'sum_credit': sum_credit,
'unaffected_earning_account_id': unaffected_earnings_account.id, 'unaffected_earning_account_id': unaffected_earnings_account.id,
'unaffected_earnings_account_name': 'unaffected_earnings_account_name':
unaffected_earnings_account_name
unaffected_earnings_account.name,
} }
self.env.cr.execute(query_update_unaffected_earnings_account, self.env.cr.execute(query_update_unaffected_earnings_account,
query_update_unaffected_earnings_account_params) query_update_unaffected_earnings_account_params)
# P&L allocated in the current fiscal year.
date = fields.Datetime.from_string(self.date_from)
res = self.company_id.compute_fiscalyear_dates(date)
fy_start_date = res['date_from']
# Fetch the initial balance
query_select_initial_pl_balance = """
SELECT
sum(aml.balance) as sum_balance
FROM
account_move_line as aml
INNER JOIN
account_move as am
ON am.id = aml.move_id
WHERE aml.date >= %(date_from)s
AND aml.date < %(date_to)s
AND aml.company_id = %(company_id)s
AND aml.account_id IN %(account_ids)s
"""
if self.only_posted_moves:
query_select_initial_pl_balance += """
AND am.state = 'posted'
"""
query_select_initial_pl_balance_params = {
'date_from': fy_start_date,
'date_to': self.date_from,
'company_id': self.company_id.id,
'account_ids': tuple(pl_account_ids),
}
self.env.cr.execute(query_select_initial_pl_balance,
query_select_initial_pl_balance_params)
res = self.env.cr.fetchone()
allocated_pl_initial_balance = res[0] or 0.0
# Fetch the period balance
query_select_period_pl_balance = """
SELECT
sum(aml.debit) as sum_debit,
sum(aml.credit) as sum_credit
FROM account_move_line as aml
INNER JOIN account_move as am
ON am.id = aml.move_id
WHERE am.date >= %(date_from)s
AND aml.date <= %(date_to)s
AND aml.company_id = %(company_id)s
AND aml.account_id IN %(account_ids)s
"""
if self.only_posted_moves:
query_select_period_pl_balance += """
AND am.state = 'posted'
"""
query_select_period_pl_balance_params = {
'date_from': self.date_from,
'date_to': self.date_to,
'company_id': self.company_id.id,
'account_ids': tuple(pl_account_ids),
}
self.env.cr.execute(query_select_period_pl_balance,
query_select_period_pl_balance_params)
res = self.env.cr.fetchone()
allocated_pl_debit = res[0] or 0.0
allocated_pl_credit = res[1] or 0.0
allocated_pl_period_balance = allocated_pl_credit - allocated_pl_debit
allocated_pl_final_balance = \
allocated_pl_initial_balance + allocated_pl_period_balance
allocated_pl_initial_balance = allocated_pl_initial_balance * -1
query_inject_pl_allocation = """
INSERT INTO
report_trial_balance_account (
report_id,
create_uid,
create_date,
account_id,
code,
name,
initial_balance,
debit,
credit,
period_balance,
final_balance,
initial_balance_foreign_currency,
final_balance_foreign_currency)
VALUES (
%(report_id)s,
%(create_uid)s,
NOW(),
%(account_id)s,
%(code)s,
%(name)s,
%(initial_balance)s,
%(debit)s,
%(credit)s,
%(period_balance)s,
%(final_balance)s,
0.0,
0.0
)
"""
query_inject_pl_allocation_params = {
'report_id': self.id,
'create_uid': self.env.uid,
'account_id': unaffected_earnings_account.id,
'code': unaffected_earnings_account.code,
'name': '%s (*)' % unaffected_earnings_account.name,
'initial_balance': allocated_pl_initial_balance,
'debit': allocated_pl_credit,
'credit': allocated_pl_debit,
'period_balance': allocated_pl_period_balance,
'final_balance': allocated_pl_final_balance
}
self.env.cr.execute(query_inject_pl_allocation,
query_inject_pl_allocation_params)
def _inject_partner_values(self): def _inject_partner_values(self):
"""Inject report values for report_trial_balance_partner""" """Inject report values for report_trial_balance_partner"""

7
account_financial_report/report/trial_balance_xlsx.py

@ -13,6 +13,13 @@ class TrialBalanceXslx(models.AbstractModel):
def _get_report_name(self): def _get_report_name(self):
return _('Trial Balance') return _('Trial Balance')
def _get_report_footer(self):
return _('(*) This report applies the current year Profit and Loss '
'balances to the Undistributed Profit/Loss account.'
'To ensure that the Trial Balance totals total to zero, '
'this line represents the reversal of the current year '
'P&L Balance.')
def _get_report_columns(self, report): def _get_report_columns(self, report):
if not report.show_partner_details: if not report.show_partner_details:
res = { res = {

111
account_financial_report/tests/test_trial_balance.py

@ -63,8 +63,6 @@ class TestTrialBalance(a_t_f_c.AbstractTestForeignCurrency):
return 'show_partner_details' in filters return 'show_partner_details' in filters
@common.at_install(False)
@common.post_install(True)
class TestTrialBalanceReport(common.TransactionCase): class TestTrialBalanceReport(common.TransactionCase):
def setUp(self): def setUp(self):
@ -500,3 +498,112 @@ class TestTrialBalanceReport(common.TransactionCase):
self.assertEqual(lines['partner_receivable'].debit, 0) self.assertEqual(lines['partner_receivable'].debit, 0)
self.assertEqual(lines['partner_receivable'].credit, 2000) self.assertEqual(lines['partner_receivable'].credit, 2000)
self.assertEqual(lines['partner_receivable'].final_balance, -1000) self.assertEqual(lines['partner_receivable'].final_balance, -1000)
def test_04_undistributed_pl(self):
# Generate the trial balance and check that we have 2 lines for the
# undistributed P&L.
move_name = 'journal previous fy'
journal = self.env['account.journal'].search([], limit=1)
move_vals = {
'journal_id': journal.id,
'name': move_name,
'date': self.previous_fy_date_end,
'line_ids': [
(0, 0, {
'name': move_name,
'debit': 0.0,
'credit': 1000.0,
'account_id': self.account100.id}),
(0, 0, {
'name': move_name,
'debit': 1000.0,
'credit': 0.0,
'account_id': self.account110.id})
]}
move = self.env['account.move'].create(move_vals)
move.post()
# Generate the trial balance line
report_account_model = self.env['report_trial_balance_account']
company = self.env.ref('base.main_company')
trial_balance = self.env['report_trial_balance'].create({
'date_from': self.date_start,
'date_to': self.date_end,
'only_posted_moves': True,
'hide_account_balance_at_0': False,
'hierarchy_on': 'none',
'company_id': company.id,
'fy_start_date': self.fy_date_start,
})
trial_balance.compute_data_for_report()
unaffected_balance_lines = report_account_model.search([
('report_id', '=', trial_balance.id),
('account_id', '=', self.account110.id),
])
self.assertEqual(len(unaffected_balance_lines), 2)
self.assertEqual(unaffected_balance_lines[0].initial_balance, 1000)
self.assertEqual(unaffected_balance_lines[0].debit, 0)
self.assertEqual(unaffected_balance_lines[0].credit, 0)
self.assertEqual(unaffected_balance_lines[0].final_balance, 1000)
# Test P&L Allocation
self.assertEqual(unaffected_balance_lines[1].initial_balance, 0)
self.assertEqual(unaffected_balance_lines[1].debit, 0)
self.assertEqual(unaffected_balance_lines[1].credit, 0)
self.assertEqual(unaffected_balance_lines[1].final_balance, 0)
# Add a P&L Move
move_name = 'current year pl move'
journal = self.env['account.journal'].search([], limit=1)
move_vals = {
'journal_id': journal.id,
'name': move_name,
'date': self.date_start,
'line_ids': [
(0, 0, {
'name': move_name,
'debit': 0.0,
'credit': 1000.0,
'account_id': self.account300.id}),
(0, 0, {
'name': move_name,
'debit': 1000.0,
'credit': 0.0,
'account_id': self.account100.id})
]}
move = self.env['account.move'].create(move_vals)
move.post()
# Re Generate the trial balance line
trial_balance = self.env['report_trial_balance'].create({
'date_from': self.date_start,
'date_to': self.date_end,
'only_posted_moves': True,
'hide_account_balance_at_0': False,
'hierarchy_on': 'none',
'company_id': company.id,
'fy_start_date': self.fy_date_start,
})
trial_balance.compute_data_for_report()
unaffected_balance_lines = report_account_model.search([
('report_id', '=', trial_balance.id),
('account_id', '=', self.account110.id),
])
# The unaffected earnings account is affected by this new entry
self.assertEqual(len(unaffected_balance_lines), 2)
self.assertEqual(unaffected_balance_lines[0].initial_balance, 1000)
self.assertEqual(unaffected_balance_lines[0].debit, 0)
self.assertEqual(unaffected_balance_lines[0].credit, 1000)
self.assertEqual(unaffected_balance_lines[0].final_balance, 0)
# The P&L is affected by this new entry, basically reversing the
# P&L balances.
self.assertEqual(unaffected_balance_lines[1].initial_balance, 0)
self.assertEqual(unaffected_balance_lines[1].debit, 1000)
self.assertEqual(unaffected_balance_lines[1].credit, 0)
self.assertEqual(unaffected_balance_lines[1].final_balance, 1000)
# The totals for the Trial Balance are zero
all_lines = report_account_model.search([
('report_id', '=', trial_balance.id),
])
self.assertEqual(sum(all_lines.mapped('initial_balance')), 0)
self.assertEqual(sum(all_lines.mapped('final_balance')), 0)
self.assertEqual(sum(all_lines.mapped('debit')),
sum(all_lines.mapped('credit')))
Loading…
Cancel
Save