Browse Source

Fix initial balance computation

pull/264/head
Akim Juillerat 8 years ago
parent
commit
9a3ff2d1e9
  1. 1
      account_financial_report_qweb/README.rst
  2. 85
      account_financial_report_qweb/report/general_ledger.py
  3. 345
      account_financial_report_qweb/tests/test_general_ledger.py

1
account_financial_report_qweb/README.rst

@ -50,6 +50,7 @@ Contributors
* Francesco Apruzzese <opencode@e-ware.org>
* Lorenzo Battistini <lorenzo.battistini@agilebg.com>
* Julien Coux <julien.coux@camptocamp.com>
* Akim Juillerat <akim.juillerat@camptocamp.com>
Much of the work in this module was done at a sprint in Sorrento, Italy in
April 2016.

85
account_financial_report_qweb/report/general_ledger.py

@ -263,7 +263,8 @@ class GeneralLedgerReportCompute(models.TransientModel):
# Refresh cache because all data are computed with SQL requests
self.refresh()
def _get_account_sub_subquery_sum_amounts(self, include_initial_balance):
def _get_account_sub_subquery_sum_amounts(
self, include_initial_balance, date_included):
""" Return subquery used to compute sum amounts on accounts """
sub_subquery_sum_amounts = """
SELECT
@ -278,9 +279,17 @@ class GeneralLedgerReportCompute(models.TransientModel):
INNER JOIN
account_move_line ml
ON a.id = ml.account_id
AND ml.date <= %s
"""
if date_included:
sub_subquery_sum_amounts += """
AND ml.date <= %s
"""
else:
sub_subquery_sum_amounts += """
AND ml.date < %s
"""
if not include_initial_balance:
sub_subquery_sum_amounts += """
AND at.include_initial_balance != TRUE AND ml.date >= %s
@ -309,8 +318,8 @@ class GeneralLedgerReportCompute(models.TransientModel):
"""
return sub_subquery_sum_amounts
def _inject_account_values(self):
"""Inject report values for report_general_ledger_qweb_account."""
def _get_final_account_sub_subquery_sum_amounts(self, date_included):
""" Return final subquery used to compute sum amounts on accounts """
subquery_sum_amounts = """
SELECT
sub.account_id AS account_id,
@ -321,19 +330,23 @@ class GeneralLedgerReportCompute(models.TransientModel):
(
"""
subquery_sum_amounts += self._get_account_sub_subquery_sum_amounts(
include_initial_balance=False
include_initial_balance=False, date_included=date_included
)
subquery_sum_amounts += """
UNION
"""
subquery_sum_amounts += self._get_account_sub_subquery_sum_amounts(
include_initial_balance=True
include_initial_balance=True, date_included=date_included
)
subquery_sum_amounts += """
) sub
GROUP BY
sub.account_id
"""
return subquery_sum_amounts
def _inject_account_values(self):
"""Inject report values for report_general_ledger_qweb_account."""
query_inject_account = """
WITH
accounts AS
@ -386,10 +399,18 @@ WITH
GROUP BY
a.id
"""
init_subquery = self._get_final_account_sub_subquery_sum_amounts(
date_included=False
)
final_subquery = self._get_final_account_sub_subquery_sum_amounts(
date_included=True
)
query_inject_account += """
),
initial_sum_amounts AS ( """ + subquery_sum_amounts + """ ),
final_sum_amounts AS ( """ + subquery_sum_amounts + """ )
initial_sum_amounts AS ( """ + init_subquery + """ ),
final_sum_amounts AS ( """ + final_subquery + """ )
INSERT INTO
report_general_ledger_qweb_account
(
@ -496,7 +517,7 @@ AND
self.env.cr.execute(query_inject_account, query_inject_account_params)
def _get_partner_sub_subquery_sum_amounts(
self, only_empty_partner, include_initial_balance
self, only_empty_partner, include_initial_balance, date_included
):
""" Return subquery used to compute sum amounts on partners """
sub_subquery_sum_amounts = """
@ -511,8 +532,15 @@ AND
INNER JOIN
account_move_line ml
ON ap.account_id = ml.account_id
"""
if date_included:
sub_subquery_sum_amounts += """
AND ml.date <= %s
"""
"""
else:
sub_subquery_sum_amounts += """
AND ml.date < %s
"""
if not only_empty_partner:
sub_subquery_sum_amounts += """
AND ap.partner_id = ml.partner_id
@ -548,11 +576,10 @@ AND
"""
return sub_subquery_sum_amounts
def _inject_partner_values(self, only_empty_partner=False):
""" Inject report values for report_general_ledger_qweb_partner.
def _get_final_partner_sub_subquery_sum_amounts(self, only_empty_partner,
date_included):
"""Return final subquery used to compute sum amounts on partners"""
Only for "partner" accounts (payable and receivable).
"""
subquery_sum_amounts = """
SELECT
@ -566,20 +593,30 @@ AND
"""
subquery_sum_amounts += self._get_partner_sub_subquery_sum_amounts(
only_empty_partner,
include_initial_balance=False
include_initial_balance=False,
date_included=date_included
)
subquery_sum_amounts += """
UNION
"""
subquery_sum_amounts += self._get_partner_sub_subquery_sum_amounts(
only_empty_partner,
include_initial_balance=True
include_initial_balance=True,
date_included=date_included
)
subquery_sum_amounts += """
) sub
GROUP BY
sub.account_id, sub.partner_id
"""
return subquery_sum_amounts
def _inject_partner_values(self, only_empty_partner=False):
""" Inject report values for report_general_ledger_qweb_partner.
Only for "partner" accounts (payable and receivable).
"""
query_inject_partner = """
WITH
accounts_partners AS
@ -645,6 +682,16 @@ WITH
AND
p.id IN %s
"""
init_subquery = self._get_final_partner_sub_subquery_sum_amounts(
only_empty_partner,
date_included=False
)
final_subquery = self._get_final_partner_sub_subquery_sum_amounts(
only_empty_partner,
date_included=True
)
query_inject_partner += """
GROUP BY
ra.id,
@ -652,8 +699,8 @@ WITH
p.id,
at.include_initial_balance
),
initial_sum_amounts AS ( """ + subquery_sum_amounts + """ ),
final_sum_amounts AS ( """ + subquery_sum_amounts + """ )
initial_sum_amounts AS ( """ + init_subquery + """ ),
final_sum_amounts AS ( """ + final_subquery + """ )
INSERT INTO
report_general_ledger_qweb_partner
(
@ -1190,7 +1237,7 @@ WHERE id = %s
INNER JOIN
account_move_line ml
ON a.id = ml.account_id
AND ml.date <= %s
AND ml.date < %s
"""
if not include_initial_balance:

345
account_financial_report_qweb/tests/test_general_ledger.py

@ -5,6 +5,7 @@
import time
from . import abstract_test
from odoo.tests.common import TransactionCase
class TestGeneralLedger(abstract_test.AbstractTest):
@ -50,3 +51,347 @@ class TestGeneralLedger(abstract_test.AbstractTest):
'centralize': True
},
]
class TestGeneralLedgerReport(TransactionCase):
def setUp(self):
super(TestGeneralLedgerReport, self).setUp()
self.previous_fy_date_end = '2015-12-31'
self.fy_date_start = '2016-01-01'
self.fy_date_end = '2016-12-31'
self.receivable_account = self.env['account.account'].search([
('user_type_id.name', '=', 'Receivable')
], limit=1)
self.income_account = self.env['account.account'].search([
('user_type_id.name', '=', 'Income')
], limit=1)
self.unaffected_account = self.env['account.account'].search([
(
'user_type_id',
'=',
self.env.ref('account.data_unaffected_earnings').id
)], limit=1)
def _add_move(
self,
date,
receivable_debit,
receivable_credit,
income_debit,
income_credit,
unaffected_debit=0,
unaffected_credit=0
):
move_name = 'expense accrual'
journal = self.env['account.journal'].search([
('code', '=', 'MISC')])
partner = self.env.ref('base.res_partner_12')
move_vals = {
'journal_id': journal.id,
'partner_id': partner.id,
'name': move_name,
'date': date,
'line_ids': [
(0, 0, {
'name': move_name,
'debit': receivable_debit,
'credit': receivable_credit,
'account_id': self.receivable_account.id}),
(0, 0, {
'name': move_name,
'debit': income_debit,
'credit': income_credit,
'account_id': self.income_account.id}),
(0, 0, {
'name': move_name,
'debit': unaffected_debit,
'credit': unaffected_credit,
'account_id': self.unaffected_account.id}),
]}
move = self.env['account.move'].create(move_vals)
move.post()
def _get_report_lines(self, with_partners=False):
company = self.env.ref('base.main_company')
general_ledger = self.env['report_general_ledger_qweb'].create({
'date_from': self.fy_date_start,
'date_to': self.fy_date_end,
'only_posted_moves': True,
'hide_account_balance_at_0': False,
'company_id': company.id,
'fy_start_date': self.fy_date_start,
})
general_ledger.compute_data_for_report(
with_line_details=True, with_partners=with_partners
)
lines = {}
report_account_model = self.env['report_general_ledger_qweb_account']
lines['receivable'] = report_account_model.search([
('report_id', '=', general_ledger.id),
('account_id', '=', self.receivable_account.id),
])
lines['income'] = report_account_model.search([
('report_id', '=', general_ledger.id),
('account_id', '=', self.income_account.id),
])
lines['unaffected'] = report_account_model.search([
('report_id', '=', general_ledger.id),
('account_id', '=', self.unaffected_account.id),
])
if with_partners:
report_partner_model = self.env[
'report_general_ledger_qweb_partner'
]
lines['partner_receivable'] = report_partner_model.search([
('report_account_id', '=', lines['receivable'].id),
('partner_id', '=', self.env.ref('base.res_partner_12').id),
])
return lines
def test_01_account_balance(self):
# Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['receivable']), 0)
self.assertEqual(len(lines['income']), 0)
# Add a move at the previous day of the first day of fiscal year
# to check the initial balance
self._add_move(
date=self.previous_fy_date_end,
receivable_debit=1000,
receivable_credit=0,
income_debit=0,
income_credit=1000
)
# Re Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['receivable']), 1)
self.assertEqual(len(lines['income']), 0)
# Check the initial and final balance
self.assertEqual(lines['receivable'].initial_debit, 1000)
self.assertEqual(lines['receivable'].initial_credit, 0)
self.assertEqual(lines['receivable'].initial_balance, 1000)
self.assertEqual(lines['receivable'].final_debit, 1000)
self.assertEqual(lines['receivable'].final_credit, 0)
self.assertEqual(lines['receivable'].final_balance, 1000)
# Add reversale move of the initial move the first day of fiscal year
# to check the first day of fiscal year is not used
# to compute the initial balance
self._add_move(
date=self.fy_date_start,
receivable_debit=0,
receivable_credit=1000,
income_debit=1000,
income_credit=0
)
# Re Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['receivable']), 1)
self.assertEqual(len(lines['income']), 1)
# Check the initial and final balance
self.assertEqual(lines['receivable'].initial_debit, 1000)
self.assertEqual(lines['receivable'].initial_credit, 0)
self.assertEqual(lines['receivable'].initial_balance, 1000)
self.assertEqual(lines['receivable'].final_debit, 1000)
self.assertEqual(lines['receivable'].final_credit, 1000)
self.assertEqual(lines['receivable'].final_balance, 0)
self.assertEqual(lines['income'].initial_debit, 0)
self.assertEqual(lines['income'].initial_credit, 0)
self.assertEqual(lines['income'].initial_balance, 0)
self.assertEqual(lines['income'].final_debit, 1000)
self.assertEqual(lines['income'].final_credit, 0)
self.assertEqual(lines['income'].final_balance, 1000)
# Add another move at the end day of fiscal year
# to check that it correctly used on report
self._add_move(
date=self.fy_date_end,
receivable_debit=0,
receivable_credit=1000,
income_debit=1000,
income_credit=0
)
# Re Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['receivable']), 1)
self.assertEqual(len(lines['income']), 1)
# Check the initial and final balance
self.assertEqual(lines['receivable'].initial_debit, 1000)
self.assertEqual(lines['receivable'].initial_credit, 0)
self.assertEqual(lines['receivable'].initial_balance, 1000)
self.assertEqual(lines['receivable'].final_debit, 1000)
self.assertEqual(lines['receivable'].final_credit, 2000)
self.assertEqual(lines['receivable'].final_balance, -1000)
self.assertEqual(lines['income'].initial_debit, 0)
self.assertEqual(lines['income'].initial_credit, 0)
self.assertEqual(lines['income'].initial_balance, 0)
self.assertEqual(lines['income'].final_debit, 2000)
self.assertEqual(lines['income'].final_credit, 0)
self.assertEqual(lines['income'].final_balance, 2000)
def test_02_partner_balance(self):
# Generate the general ledger line
lines = self._get_report_lines(with_partners=True)
self.assertEqual(len(lines['partner_receivable']), 0)
# Add a move at the previous day of the first day of fiscal year
# to check the initial balance
self._add_move(
date=self.previous_fy_date_end,
receivable_debit=1000,
receivable_credit=0,
income_debit=0,
income_credit=1000
)
# Re Generate the general ledger line
lines = self._get_report_lines(with_partners=True)
self.assertEqual(len(lines['partner_receivable']), 1)
# Check the initial and final balance
self.assertEqual(lines['partner_receivable'].initial_debit, 1000)
self.assertEqual(lines['partner_receivable'].initial_credit, 0)
self.assertEqual(lines['partner_receivable'].initial_balance, 1000)
self.assertEqual(lines['partner_receivable'].final_debit, 1000)
self.assertEqual(lines['partner_receivable'].final_credit, 0)
self.assertEqual(lines['partner_receivable'].final_balance, 1000)
# Add reversale move of the initial move the first day of fiscal year
# to check the first day of fiscal year is not used
# to compute the initial balance
self._add_move(
date=self.fy_date_start,
receivable_debit=0,
receivable_credit=1000,
income_debit=1000,
income_credit=0
)
# Re Generate the general ledger line
lines = self._get_report_lines(with_partners=True)
self.assertEqual(len(lines['partner_receivable']), 1)
# Check the initial and final balance
self.assertEqual(lines['partner_receivable'].initial_debit, 1000)
self.assertEqual(lines['partner_receivable'].initial_credit, 0)
self.assertEqual(lines['partner_receivable'].initial_balance, 1000)
self.assertEqual(lines['partner_receivable'].final_debit, 1000)
self.assertEqual(lines['partner_receivable'].final_credit, 1000)
self.assertEqual(lines['partner_receivable'].final_balance, 0)
# Add another move at the end day of fiscal year
# to check that it correctly used on report
self._add_move(
date=self.fy_date_end,
receivable_debit=0,
receivable_credit=1000,
income_debit=1000,
income_credit=0
)
# Re Generate the general ledger line
lines = self._get_report_lines(with_partners=True)
self.assertEqual(len(lines['partner_receivable']), 1)
# Check the initial and final balance
self.assertEqual(lines['partner_receivable'].initial_debit, 1000)
self.assertEqual(lines['partner_receivable'].initial_credit, 0)
self.assertEqual(lines['partner_receivable'].initial_balance, 1000)
self.assertEqual(lines['partner_receivable'].final_debit, 1000)
self.assertEqual(lines['partner_receivable'].final_credit, 2000)
self.assertEqual(lines['partner_receivable'].final_balance, -1000)
def test_03_unaffected_account_balance(self):
# Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['unaffected']), 1)
# 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_balance, 0)
self.assertEqual(lines['unaffected'].final_debit, 0)
self.assertEqual(lines['unaffected'].final_credit, 0)
self.assertEqual(lines['unaffected'].final_balance, 0)
# Add a move at the previous day of the first day of fiscal year
# to check the initial balance
self._add_move(
date=self.previous_fy_date_end,
receivable_debit=1000,
receivable_credit=0,
income_debit=0,
income_credit=1000
)
# Re Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['unaffected']), 1)
# 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_balance, -1000)
self.assertEqual(lines['unaffected'].final_debit, -0)
self.assertEqual(lines['unaffected'].final_credit, 0)
self.assertEqual(lines['unaffected'].final_balance, -1000)
# Add reversale move of the initial move the first day of fiscal year
# to check the first day of fiscal year is not used
# to compute the initial balance
self._add_move(
date=self.fy_date_start,
receivable_debit=0,
receivable_credit=0,
income_debit=0,
income_credit=1000,
unaffected_debit=1000,
unaffected_credit=0
)
# Re Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['unaffected']), 1)
# 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_balance, -1000)
self.assertEqual(lines['unaffected'].final_debit, 1000)
self.assertEqual(lines['unaffected'].final_credit, 0)
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
self._add_move(
date=self.fy_date_end,
receivable_debit=3000,
receivable_credit=0,
income_debit=0,
income_credit=0,
unaffected_debit=0,
unaffected_credit=3000
)
# Re Generate the general ledger line
lines = self._get_report_lines()
self.assertEqual(len(lines['unaffected']), 1)
# 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_balance, -1000)
self.assertEqual(lines['unaffected'].final_debit, 1000)
self.assertEqual(lines['unaffected'].final_credit, 3000)
self.assertEqual(lines['unaffected'].final_balance, -3000)
Loading…
Cancel
Save