[FIX] account: Fix creation of statement with zero amount/amount_currency
During the migration, it could happen some statement lines are created with a zero amount in company currency or foreign currency. It this specific case, we can't retrieve the correct amounts by multiplying the statement line conversion rate because X * 0 is always zero. This commit ensures the amounts are well preserved in such case. X-original-commit: a75bc7fdf014daf965cad72917ac475cbf83f6ac
This commit is contained in:
@@ -657,8 +657,10 @@ class AccountBankStatementLine(models.Model):
|
||||
# use the foreign currency set on the statement line.
|
||||
|
||||
amount_currency = amount_residual_currency
|
||||
balance_journal_currency = (amount_currency / statement_line_rate) if statement_line_rate else 0.0
|
||||
balance = journal_currency._convert(balance_journal_currency, company_currency, journal.company_id, self.date)
|
||||
if statement_line_rate:
|
||||
balance = journal_currency._convert(amount_currency / statement_line_rate, company_currency, journal.company_id, self.date)
|
||||
else:
|
||||
balance = amount_residual
|
||||
|
||||
elif currency_id == journal_currency.id and self.foreign_currency_id == company_currency:
|
||||
|
||||
@@ -666,10 +668,15 @@ class AccountBankStatementLine(models.Model):
|
||||
# There is also a foreign currency set on the statement line that is the same as the company one.
|
||||
# Then, the journal item to create will use the company's currency.
|
||||
|
||||
amount_currency = amount_residual_currency
|
||||
balance = amount_currency * statement_line_rate
|
||||
currency_id = False
|
||||
amount_currency = 0.0
|
||||
if statement_line_rate:
|
||||
amount_currency = amount_residual_currency
|
||||
balance = amount_currency * statement_line_rate
|
||||
currency_id = False
|
||||
amount_currency = 0.0
|
||||
else:
|
||||
balance = amount_residual
|
||||
currency_id = False
|
||||
amount_currency = 0.0
|
||||
|
||||
elif currency_id == journal_currency.id and self.foreign_currency_id != company_currency:
|
||||
|
||||
@@ -677,20 +684,30 @@ class AccountBankStatementLine(models.Model):
|
||||
# There is also a foreign currency set on the statement line.
|
||||
# The residual amount will be convert to the foreign currency set on the statement line.
|
||||
|
||||
amount_currency = amount_residual_currency
|
||||
balance = journal_currency._convert(amount_currency, company_currency, journal.company_id, self.date)
|
||||
amount_currency *= statement_line_rate
|
||||
currency_id = self.foreign_currency_id.id
|
||||
if statement_line_rate:
|
||||
journal_amount_currency = amount_residual_currency
|
||||
balance = journal_currency._convert(journal_amount_currency, company_currency, journal.company_id, self.date)
|
||||
amount_currency = journal_amount_currency * statement_line_rate
|
||||
currency_id = self.foreign_currency_id.id
|
||||
else:
|
||||
amount_currency = amount_residual_currency
|
||||
balance = amount_residual
|
||||
currency_id = self.foreign_currency_id.id
|
||||
|
||||
else:
|
||||
|
||||
# Whatever the currency set on the journal item passed as parameter, the counterpart line
|
||||
# will be expressed in the foreign currency set on the statement line.
|
||||
|
||||
balance = amount_residual
|
||||
amount_currency = company_currency._convert(balance, journal_currency, journal.company_id, self.date)
|
||||
amount_currency *= statement_line_rate
|
||||
currency_id = self.foreign_currency_id.id
|
||||
if statement_line_rate:
|
||||
balance = amount_residual
|
||||
journal_amount_currency = company_currency._convert(balance, journal_currency, journal.company_id, self.date)
|
||||
amount_currency = journal_amount_currency * statement_line_rate
|
||||
currency_id = self.foreign_currency_id.id
|
||||
else:
|
||||
amount_currency = amount_residual_currency
|
||||
balance = amount_residual
|
||||
currency_id = self.foreign_currency_id.id
|
||||
|
||||
elif self.foreign_currency_id and not journal_currency:
|
||||
|
||||
@@ -698,12 +715,17 @@ class AccountBankStatementLine(models.Model):
|
||||
# In that case, the 'amount' set on the statement line is expressed in the company's currency
|
||||
# and is used as conversion rate between the company's currency and the foreign currency.
|
||||
|
||||
if currency_id == self.foreign_currency_id.id:
|
||||
amount_currency = amount_residual_currency
|
||||
balance = amount_currency / statement_line_rate if statement_line_rate else 0.0
|
||||
if statement_line_rate:
|
||||
if currency_id == self.foreign_currency_id.id:
|
||||
amount_currency = amount_residual_currency
|
||||
balance = amount_currency / statement_line_rate
|
||||
else:
|
||||
balance = amount_residual
|
||||
amount_currency = balance * statement_line_rate
|
||||
currency_id = self.foreign_currency_id.id
|
||||
else:
|
||||
balance = amount_residual
|
||||
amount_currency = balance * statement_line_rate
|
||||
amount_currency = amount_residual_currency
|
||||
currency_id = self.foreign_currency_id.id
|
||||
|
||||
elif not self.foreign_currency_id and journal_currency:
|
||||
@@ -740,9 +762,12 @@ class AccountBankStatementLine(models.Model):
|
||||
|
||||
if self.foreign_currency_id == company_currency:
|
||||
amount_currency = 0.0
|
||||
elif statement_line_rate:
|
||||
journal_amount_currency = company_currency._convert(balance, journal_currency, journal.company_id, self.date)
|
||||
amount_currency = journal_amount_currency * statement_line_rate
|
||||
currency_id = self.foreign_currency_id.id
|
||||
else:
|
||||
amount_currency = company_currency._convert(balance, journal_currency, journal.company_id, self.date)
|
||||
amount_currency *= statement_line_rate
|
||||
amount_currency = amount_residual_currency
|
||||
currency_id = self.foreign_currency_id.id
|
||||
|
||||
elif self.foreign_currency_id and not journal_currency:
|
||||
@@ -750,8 +775,11 @@ class AccountBankStatementLine(models.Model):
|
||||
# Different currencies set on the company and the statement line.
|
||||
# Record the counterpart line using the foreign currency.
|
||||
|
||||
amount_currency = balance * statement_line_rate
|
||||
currency_id = self.foreign_currency_id.id
|
||||
if statement_line_rate:
|
||||
amount_currency = balance * statement_line_rate
|
||||
else:
|
||||
amount_currency = amount_residual_currency
|
||||
|
||||
elif not self.foreign_currency_id and journal_currency:
|
||||
|
||||
@@ -800,9 +828,18 @@ class AccountBankStatementLine(models.Model):
|
||||
counterpart_vals = {
|
||||
'name': self.payment_ref,
|
||||
'account_id': counterpart_account_id,
|
||||
'amount_residual': liquidity_line_vals['debit'] - liquidity_line_vals['credit'],
|
||||
}
|
||||
|
||||
if liquidity_line_vals['currency_id']:
|
||||
if self.foreign_currency_id and self.foreign_currency_id != self.company_currency_id:
|
||||
# Ensure the counterpart will have exactly the same amount in foreign currency as the amount set in the
|
||||
# statement line to avoid some rounding issues when making a currency conversion.
|
||||
|
||||
counterpart_vals.update({
|
||||
'currency_id': self.foreign_currency_id.id,
|
||||
'amount_residual_currency': self.amount_currency,
|
||||
})
|
||||
elif liquidity_line_vals['currency_id']:
|
||||
# Ensure the counterpart will have a balance exactly equals to the amount in journal currency.
|
||||
# This avoid some rounding issues when the currency rate between two currencies is not symmetrical.
|
||||
# E.g:
|
||||
@@ -811,10 +848,8 @@ class AccountBankStatementLine(models.Model):
|
||||
|
||||
counterpart_vals.update({
|
||||
'currency_id': liquidity_line_vals['currency_id'],
|
||||
'balance': -liquidity_line_vals['amount_currency'],
|
||||
'amount_residual_currency': liquidity_line_vals['amount_currency'],
|
||||
})
|
||||
else:
|
||||
counterpart_vals['balance'] = liquidity_line_vals['credit'] - liquidity_line_vals['debit']
|
||||
|
||||
counterpart_line_vals = self._prepare_counterpart_move_line_vals(counterpart_vals)
|
||||
return [liquidity_line_vals, counterpart_line_vals]
|
||||
@@ -861,6 +896,9 @@ class AccountBankStatementLine(models.Model):
|
||||
@api.constrains('amount', 'amount_currency', 'currency_id', 'foreign_currency_id', 'journal_id')
|
||||
def _check_amounts_currencies(self):
|
||||
''' Ensure the consistency the specified amounts and the currencies. '''
|
||||
if self._context.get('skip_check_amounts_currencies'):
|
||||
return
|
||||
|
||||
for st_line in self:
|
||||
if st_line.journal_id != st_line.statement_id.journal_id:
|
||||
raise ValidationError(_('The journal of a statement line must always be the same as the bank statement one.'))
|
||||
|
||||
@@ -518,6 +518,150 @@ class TestAccountBankStatementLine(TestAccountBankStatementCommon):
|
||||
{'debit': 0.0, 'credit': 80.0, 'amount_currency': 0.0, 'currency_id': False},
|
||||
)
|
||||
|
||||
def test_zero_amount_journal_curr_1_statement_curr_2(self):
|
||||
self.bank_journal_2.currency_id = self.currency_1
|
||||
|
||||
statement = self.env['account.bank.statement'].with_context(skip_check_amounts_currencies=True).create({
|
||||
'name': 'test_statement',
|
||||
'date': '2019-01-01',
|
||||
'journal_id': self.bank_journal_2.id,
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': '2019-01-01',
|
||||
'payment_ref': 'line_1',
|
||||
'partner_id': self.partner_a.id,
|
||||
'foreign_currency_id': self.currency_2.id,
|
||||
'amount': 0.0,
|
||||
'amount_currency': 10.0,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
self.assertRecordValues(statement.line_ids.move_id.line_ids, [
|
||||
{'debit': 0.0, 'credit': 0.0, 'amount_currency': 10.0, 'currency_id': self.currency_2.id},
|
||||
{'debit': 0.0, 'credit': 0.0, 'amount_currency': -10.0, 'currency_id': self.currency_2.id},
|
||||
])
|
||||
|
||||
def test_zero_amount_currency_journal_curr_1_statement_curr_2(self):
|
||||
self.bank_journal_2.currency_id = self.currency_1
|
||||
|
||||
statement = self.env['account.bank.statement'].with_context(skip_check_amounts_currencies=True).create({
|
||||
'name': 'test_statement',
|
||||
'date': '2019-01-01',
|
||||
'journal_id': self.bank_journal_2.id,
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': '2019-01-01',
|
||||
'payment_ref': 'line_1',
|
||||
'partner_id': self.partner_a.id,
|
||||
'foreign_currency_id': self.currency_2.id,
|
||||
'amount': 10.0,
|
||||
'amount_currency': 0.0,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
self.assertRecordValues(statement.line_ids.move_id.line_ids, [
|
||||
{'debit': 10.0, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': self.currency_2.id},
|
||||
{'debit': 0.0, 'credit': 10.0, 'amount_currency': 0.0, 'currency_id': self.currency_2.id},
|
||||
])
|
||||
|
||||
def test_zero_amount_journal_curr_2_statement_curr_1(self):
|
||||
self.bank_journal_2.currency_id = self.currency_2
|
||||
|
||||
statement = self.env['account.bank.statement'].with_context(skip_check_amounts_currencies=True).create({
|
||||
'name': 'test_statement',
|
||||
'date': '2019-01-01',
|
||||
'journal_id': self.bank_journal_2.id,
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': '2019-01-01',
|
||||
'payment_ref': 'line_1',
|
||||
'partner_id': self.partner_a.id,
|
||||
'foreign_currency_id': self.currency_1.id,
|
||||
'amount': 0.0,
|
||||
'amount_currency': 10.0,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
self.assertRecordValues(statement.line_ids.move_id.line_ids, [
|
||||
{'debit': 10.0, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': self.currency_2.id},
|
||||
{'debit': 0.0, 'credit': 10.0, 'amount_currency': 0.0, 'currency_id': False},
|
||||
])
|
||||
|
||||
def test_zero_amount_currency_journal_curr_2_statement_curr_1(self):
|
||||
self.bank_journal_2.currency_id = self.currency_2
|
||||
|
||||
statement = self.env['account.bank.statement'].with_context(skip_check_amounts_currencies=True).create({
|
||||
'name': 'test_statement',
|
||||
'date': '2019-01-01',
|
||||
'journal_id': self.bank_journal_2.id,
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': '2019-01-01',
|
||||
'payment_ref': 'line_1',
|
||||
'partner_id': self.partner_a.id,
|
||||
'foreign_currency_id': self.currency_1.id,
|
||||
'amount': 10.0,
|
||||
'amount_currency': 0.0,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
self.assertRecordValues(statement.line_ids.move_id.line_ids, [
|
||||
{'debit': 0.0, 'credit': 0.0, 'amount_currency': 10.0, 'currency_id': self.currency_2.id},
|
||||
{'debit': 0.0, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': False},
|
||||
])
|
||||
|
||||
def test_zero_amount_journal_curr_2_statement_curr_3(self):
|
||||
self.bank_journal_2.currency_id = self.currency_2
|
||||
|
||||
statement = self.env['account.bank.statement'].with_context(skip_check_amounts_currencies=True).create({
|
||||
'name': 'test_statement',
|
||||
'date': '2019-01-01',
|
||||
'journal_id': self.bank_journal_2.id,
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': '2019-01-01',
|
||||
'payment_ref': 'line_1',
|
||||
'partner_id': self.partner_a.id,
|
||||
'foreign_currency_id': self.currency_3.id,
|
||||
'amount': 0.0,
|
||||
'amount_currency': 10.0,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
self.assertRecordValues(statement.line_ids.move_id.line_ids, [
|
||||
{'debit': 0.0, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': self.currency_2.id},
|
||||
{'debit': 0.0, 'credit': 0.0, 'amount_currency': -10.0, 'currency_id': self.currency_3.id},
|
||||
])
|
||||
|
||||
def test_zero_amount_currency_journal_curr_2_statement_curr_3(self):
|
||||
self.bank_journal_2.currency_id = self.currency_2
|
||||
|
||||
statement = self.env['account.bank.statement'].with_context(skip_check_amounts_currencies=True).create({
|
||||
'name': 'test_statement',
|
||||
'date': '2019-01-01',
|
||||
'journal_id': self.bank_journal_2.id,
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': '2019-01-01',
|
||||
'payment_ref': 'line_1',
|
||||
'partner_id': self.partner_a.id,
|
||||
'foreign_currency_id': self.currency_3.id,
|
||||
'amount': 10.0,
|
||||
'amount_currency': 0.0,
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
self.assertRecordValues(statement.line_ids.move_id.line_ids, [
|
||||
{'debit': 5.0, 'credit': 0.0, 'amount_currency': 10.0, 'currency_id': self.currency_2.id},
|
||||
{'debit': 0.0, 'credit': 5.0, 'amount_currency': 0.0, 'currency_id': self.currency_3.id},
|
||||
])
|
||||
|
||||
def test_constraints(self):
|
||||
def assertStatementLineConstraint(statement_vals, statement_line_vals):
|
||||
with self.assertRaises(Exception), self.cr.savepoint():
|
||||
|
||||
Reference in New Issue
Block a user