Files
odoo_source/addons/account/tests/test_account_bank_statement.py
T
Cedric Snauwaert 5b7cff06f7 [FIX] account: don't recompute ending balance of last statement
Previously a task was created to prevent holes between bank statement,
meaning that starting balance should always be the same as previous
ending balance. The goal was that during synchronization or imports,
we could add statement lines in previous statement and not have to
recompute manually the full chain of starting and ending balance of
next statements entries. This works fine with online synchronization
as we always write after creating the statements the balance
of the account on the latest statements to detect missing stmts,
however if we create stmts by hand, it is possible that we have the
following case:

Statement on 10 January with a starting and ending balance of 100 and 200
respectively. We are missing 2 statements with a line of 50 each before that
date. So we create the first missing statement at date: 8 January with a
starting balance 0 and ending balance 50, this will recompute the starting
and ending balance of next statement and overwrite the values to 50 and 150
(starting and ending balance respectively). At that time the system will say
that everything is normal but we are still missing a stmt and we are not seeing
it.

The way to fix this is by not touching the ending balance of the last
stmt entry during the computation, that way we can still detect that there is
an error and that 50€ are still missing.

closes odoo/odoo#48000

X-original-commit: b97b4f4217989e8cae5c32be0d62c11d36eaf1d7
Signed-off-by: Cedric Snauwaert (csn) <csn@openerp.com>
2020-03-19 10:30:43 +00:00

245 lines
12 KiB
Python

from odoo.addons.account.tests.common import AccountTestCommon
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestBankStatement(AccountTestCommon):
def setUp(self):
super(TestBankStatement, self).setUp()
self.bs_model = self.env['account.bank.statement']
self.bsl_model = self.env['account.bank.statement.line']
self.partner = self.env['res.partner'].create({'name': 'test'})
self.journal = self.env['account.journal'].create({
'name': 'BnkJournal',
'type': 'bank'
})
self.journal2 = self.env['account.journal'].create({
'name': 'BnkJournal2',
'type': 'bank'
})
self.cashjournal = self.env['account.journal'].create({
'name': 'CashJournal',
'type': 'cash'
})
self.number = 1
def create_bank_statement(self, date, line_amount, balance_end_real=False, journal=False):
vals = {
'name': 'BNK' + str(self.number),
'date': date,
'line_ids': [(0, 0, {
'name': '_',
'amount': line_amount,
})],
'journal_id': journal or self.journal.id
}
if balance_end_real:
vals['balance_end_real'] = balance_end_real
self.number += 1
return self.bs_model.create(vals)
def test_compute_balance_end_real_with_lines(self):
bnk1 = self.create_bank_statement('2019-01-02', 100)
self.assertEqual(bnk1.balance_start, 0)
# Balance is automatically computed when creating statement with the lines
self.assertEqual(bnk1.balance_end_real, 100)
self.assertEqual(bnk1.balance_end, 100)
def test_compute_balance_end_real_without_lines(self):
vals = {
'name': 'BNK' + str(self.number),
'date': '2019-01-01',
'journal_id': self.journal.id
}
bnk1 = self.bs_model.create(vals)
self.assertEqual(bnk1.balance_start, 0)
self.assertEqual(bnk1.balance_end_real, 0)
self.assertEqual(bnk1.balance_end, 0)
# Add a line
self.bsl_model.create({
'name': '_',
'amount': 10,
'statement_id': bnk1.id
})
self.assertEqual(bnk1.balance_start, 0)
# balance_end_real should not have changed
self.assertEqual(bnk1.balance_end_real, 0)
# Compute balance should have been computed
self.assertEqual(bnk1.balance_end, 10)
def test_create_new_statement(self):
# Create first statement on 1/1/2019
bnk1 = self.create_bank_statement('2019-01-02', 100)
self.assertEqual(bnk1.balance_start, 0)
# Balance is automatically computed when creating statement with the lines
self.assertEqual(bnk1.balance_end_real, 100)
self.assertEqual(bnk1.balance_end, 100)
self.assertEqual(bnk1.previous_statement_id.id, False)
# Create a new statement after that one
bnk2 = self.create_bank_statement('2019-01-10', 50)
self.assertEqual(bnk2.balance_start, 100)
self.assertEqual(bnk2.balance_end_real, 150)
self.assertEqual(bnk2.balance_end, 150)
self.assertEqual(bnk2.previous_statement_id.id, bnk1.id)
# Create new statement with given ending balance
bnk3 = self.create_bank_statement('2019-01-15', 25, 200)
self.assertEqual(bnk3.balance_end_real, 200)
self.assertEqual(bnk3.balance_start, 150)
self.assertEqual(bnk3.balance_end, 175)
self.assertEqual(bnk3.previous_statement_id.id, bnk2.id)
bnk4 = self.create_bank_statement('2019-01-03', 100)
self.assertEqual(bnk4.balance_start, 100)
self.assertEqual(bnk4.balance_end_real, 200)
self.assertEqual(bnk4.balance_end, 200)
self.assertEqual(bnk4.previous_statement_id.id, bnk1.id)
# Bnk2 should have changed its previous statement
self.assertEqual(bnk2.previous_statement_id.id, bnk4.id)
# The starting balance and balance_end_real should have been recomputed
self.assertEqual(bnk2.balance_start, 200)
self.assertEqual(bnk2.balance_end_real, 250)
self.assertEqual(bnk2.balance_end, 250)
# The starting balance and balance_end_real of next entries should also have been recomputed
# and since we are propagating an update, the balance_end_real should have been recomputed to
# the correct value
self.assertEqual(bnk3.balance_start, 250)
self.assertEqual(bnk3.balance_end_real, 200) # This should not have been recomputed as this is the last of the chain
self.assertEqual(bnk3.balance_end, 275)
bnk3.balance_end_real = 275 # Correct ending balance
# Change date of bank stmt4 to be the last
self.assertEqual(bnk4.balance_end_real, 200) #Check balance before moving it to the last
bnk4.date = '2019-01-20'
self.assertEqual(bnk1.previous_statement_id.id, False)
self.assertEqual(bnk2.previous_statement_id.id, bnk1.id)
self.assertEqual(bnk3.previous_statement_id.id, bnk2.id)
self.assertEqual(bnk4.previous_statement_id.id, bnk3.id)
self.assertEqual(bnk1.balance_start, 0)
self.assertEqual(bnk2.balance_start, 100)
self.assertEqual(bnk3.balance_start, 150)
self.assertEqual(bnk4.balance_start, 175)
self.assertEqual(bnk1.balance_end_real, 100)
self.assertEqual(bnk2.balance_end_real, 150)
self.assertEqual(bnk3.balance_end_real, 175)
self.assertEqual(bnk4.balance_end_real, 200) # This should not have change
bnk4.balance_end_real = 275 # Correct ending balance
# Move bnk3 to first position
bnk3.date = '2019-01-01'
self.assertEqual(bnk3.previous_statement_id.id, False)
self.assertEqual(bnk1.previous_statement_id.id, bnk3.id)
self.assertEqual(bnk2.previous_statement_id.id, bnk1.id)
self.assertEqual(bnk4.previous_statement_id.id, bnk2.id)
self.assertEqual(bnk3.balance_start, 0)
self.assertEqual(bnk1.balance_start, 25)
self.assertEqual(bnk2.balance_start, 125)
self.assertEqual(bnk4.balance_start, 175)
self.assertEqual(bnk3.balance_end_real, 25)
self.assertEqual(bnk1.balance_end_real, 125)
self.assertEqual(bnk2.balance_end_real, 175)
self.assertEqual(bnk4.balance_end_real, 275)
# Change bnk1 and bnk2
bnk1.date = '2019-01-11'
self.assertEqual(bnk3.previous_statement_id.id, False)
self.assertEqual(bnk2.previous_statement_id.id, bnk3.id)
self.assertEqual(bnk1.previous_statement_id.id, bnk2.id)
self.assertEqual(bnk4.previous_statement_id.id, bnk1.id)
self.assertEqual(bnk3.balance_start, 0)
self.assertEqual(bnk2.balance_start, 25)
self.assertEqual(bnk1.balance_start, 75)
self.assertEqual(bnk4.balance_start, 175)
self.assertEqual(bnk3.balance_end_real, 25)
self.assertEqual(bnk2.balance_end_real, 75)
self.assertEqual(bnk1.balance_end_real, 175)
self.assertEqual(bnk4.balance_end_real, 275)
def test_create_statements_in_different_journal(self):
# Bank statement create in two different journal should not link with each other
bnk1 = self.create_bank_statement('2019-01-01', 100, 100)
bnk2 = self.create_bank_statement('2019-01-10', 50)
bnk1other = self.create_bank_statement('2019-01-02', 20, 20, self.journal2.id)
bnk2other = self.create_bank_statement('2019-01-12', 10, False, self.journal2.id)
self.assertEqual(bnk1.previous_statement_id.id, False)
self.assertEqual(bnk2.previous_statement_id.id, bnk1.id)
self.assertEqual(bnk1.balance_start, 0)
self.assertEqual(bnk2.balance_start, 100)
self.assertEqual(bnk2.balance_end_real, 150)
self.assertEqual(bnk1other.previous_statement_id.id, False)
self.assertEqual(bnk2other.previous_statement_id.id, bnk1other.id)
self.assertEqual(bnk1other.balance_start, 0)
self.assertEqual(bnk2other.balance_start, 20)
self.assertEqual(bnk2other.balance_end_real, 30)
def test_statement_cash_journal(self):
# Entry in cash journal should not recompute the balance_end_real
cash1 = self.create_bank_statement('2019-01-01', 100, 100, self.cashjournal.id)
cash2 = self.create_bank_statement('2019-01-03', 100, False, self.cashjournal.id)
self.assertEqual(cash1.balance_start, 0)
self.assertEqual(cash1.balance_end_real, 100)
self.assertEqual(cash2.balance_start, 100)
self.assertEqual(cash2.balance_end_real, 0)
cash2.balance_end_real = 1000
self.assertEqual(cash2.balance_end_real, 1000)
# add cash entry in between, should recompute starting balance of cash2 entry but not ending balance
cash3 = self.create_bank_statement('2019-01-02', 100, 200, self.cashjournal.id)
self.assertEqual(cash3.balance_start, 100)
self.assertEqual(cash3.balance_end_real, 200)
self.assertEqual(cash2.balance_start, 200)
self.assertEqual(cash2.balance_end_real, 1000)
def test_is_valid_balance_start(self):
bnk1 = self.create_bank_statement('2019-01-01', 100, 100.0000001)
bnk2 = self.create_bank_statement('2019-01-10', 50)
bnk2.write({'balance_start': 100})
self.assertTrue(bnk2.is_valid_balance_start)
bnk2.write({'balance_start': 100.01})
self.assertFalse(bnk2.is_valid_balance_start)
def test_unlink_bank_statement(self):
bnk1 = self.create_bank_statement('2019-01-02', 100)
bnk2 = self.create_bank_statement('2019-01-10', 50)
bnk3 = self.create_bank_statement('2019-01-15', 25)
bnk4 = self.create_bank_statement('2019-01-21', 100)
bnk5 = self.create_bank_statement('2019-01-22', 100)
self.assertEqual(bnk1.previous_statement_id.id, False)
self.assertEqual(bnk2.previous_statement_id.id, bnk1.id)
self.assertEqual(bnk3.previous_statement_id.id, bnk2.id)
self.assertEqual(bnk4.previous_statement_id.id, bnk3.id)
self.assertEqual(bnk5.previous_statement_id.id, bnk4.id)
self.assertEqual(bnk1.balance_start, 0)
self.assertEqual(bnk1.balance_end_real, 100)
self.assertEqual(bnk2.balance_start, 100)
self.assertEqual(bnk2.balance_end_real, 150)
self.assertEqual(bnk3.balance_start, 150)
self.assertEqual(bnk3.balance_end_real, 175)
self.assertEqual(bnk4.balance_start, 175)
self.assertEqual(bnk4.balance_end_real, 275)
self.assertEqual(bnk5.balance_start, 275)
self.assertEqual(bnk5.balance_end_real, 375)
# Delete bnk2 and check that previous_statement_id and balance are correct
bnk2.unlink()
self.assertEqual(bnk1.previous_statement_id.id, False)
self.assertEqual(bnk3.previous_statement_id.id, bnk1.id)
self.assertEqual(bnk4.previous_statement_id.id, bnk3.id)
self.assertEqual(bnk5.previous_statement_id.id, bnk4.id)
self.assertEqual(bnk3.balance_start, 100)
self.assertEqual(bnk3.balance_end_real, 125)
self.assertEqual(bnk4.balance_start, 125)
self.assertEqual(bnk4.balance_end_real, 225)
self.assertEqual(bnk5.balance_start, 225)
self.assertEqual(bnk5.balance_end_real, 375) # Ending balance of last statement should not have changed
# Delete bnk1 bnk3 and bnk4 at the same time and check that balance are correct
(bnk1 + bnk3 + bnk4).unlink()
self.assertEqual(bnk5.previous_statement_id.id, False)
self.assertEqual(bnk5.balance_start, 0)
self.assertEqual(bnk5.balance_end_real, 375) # Ending balance of last statement should not have changed