This is needed in order to support use cases where we have several account.move.line on an account_id of internal_type 'bank' inside a single account.move. Indeed, each journal item should be linked to a bank statement line in order to disappear from the bank reconciliation widget and, previously, setting the reference to the second bank statement line was removing the first as both info had to be filled in a single m2o. OPW: 696842
182 lines
10 KiB
Python
182 lines
10 KiB
Python
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
|
|
import time
|
|
|
|
class TestPayment(AccountingTestCase):
|
|
|
|
def setUp(self):
|
|
super(TestPayment, self).setUp()
|
|
self.register_payments_model = self.env['account.register.payments']
|
|
self.payment_model = self.env['account.payment']
|
|
self.invoice_model = self.env['account.invoice']
|
|
self.invoice_line_model = self.env['account.invoice.line']
|
|
self.acc_bank_stmt_model = self.env['account.bank.statement']
|
|
self.acc_bank_stmt_line_model = self.env['account.bank.statement.line']
|
|
|
|
self.partner_agrolait = self.env.ref("base.res_partner_2")
|
|
self.partner_axelor = self.env.ref("base.res_partner_2")
|
|
self.currency_chf_id = self.env.ref("base.CHF").id
|
|
self.currency_usd_id = self.env.ref("base.USD").id
|
|
self.currency_eur_id = self.env.ref("base.EUR").id
|
|
self.env.ref('base.main_company').write({'currency_id': self.currency_eur_id})
|
|
self.product = self.env.ref("product.product_product_4")
|
|
self.payment_method_manual_in = self.env.ref("account.account_payment_method_manual_in")
|
|
self.payment_method_manual_out = self.env.ref("account.account_payment_method_manual_out")
|
|
|
|
self.account_receivable = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_receivable').id)], limit=1)
|
|
self.account_payable = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_payable').id)], limit=1)
|
|
self.account_revenue = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1)
|
|
|
|
self.bank_journal_euro = self.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'BNK67'})
|
|
self.account_eur = self.bank_journal_euro.default_debit_account_id
|
|
|
|
self.bank_journal_usd = self.env['account.journal'].create({'name': 'Bank US', 'type': 'bank', 'code': 'BNK68', 'currency_id': self.currency_usd_id})
|
|
self.account_usd = self.bank_journal_usd.default_debit_account_id
|
|
|
|
self.transfer_account = self.env['res.users'].browse(self.env.uid).company_id.transfer_account_id
|
|
self.diff_income_account = self.env['res.users'].browse(self.env.uid).company_id.income_currency_exchange_account_id
|
|
self.diff_expense_account = self.env['res.users'].browse(self.env.uid).company_id.expense_currency_exchange_account_id
|
|
|
|
def create_invoice(self, amount=100, type='out_invoice', currency_id=None):
|
|
""" Returns an open invoice """
|
|
invoice = self.invoice_model.create({
|
|
'partner_id': self.partner_agrolait.id,
|
|
'reference_type': 'none',
|
|
'currency_id': currency_id,
|
|
'name': type == 'out_invoice' and 'invoice to client' or 'invoice to supplier',
|
|
'account_id': self.account_receivable.id,
|
|
'type': type,
|
|
'date_invoice': time.strftime('%Y') + '-06-26',
|
|
})
|
|
self.invoice_line_model.create({
|
|
'product_id': self.product.id,
|
|
'quantity': 1,
|
|
'price_unit': amount,
|
|
'invoice_id': invoice.id,
|
|
'name': 'something',
|
|
'account_id': self.account_revenue.id,
|
|
})
|
|
invoice.action_invoice_open()
|
|
return invoice
|
|
|
|
def reconcile(self, liquidity_aml, amount=0.0, amount_currency=0.0, currency_id=None):
|
|
""" Reconcile a journal entry corresponding to a payment with its bank statement line """
|
|
bank_stmt = self.acc_bank_stmt_model.create({
|
|
'journal_id': liquidity_aml.journal_id.id,
|
|
'date': time.strftime('%Y') + '-07-15',
|
|
})
|
|
bank_stmt_line = self.acc_bank_stmt_line_model.create({
|
|
'name': 'payment',
|
|
'statement_id': bank_stmt.id,
|
|
'partner_id': self.partner_agrolait.id,
|
|
'amount': amount,
|
|
'amount_currency': amount_currency,
|
|
'currency_id': currency_id,
|
|
'date': time.strftime('%Y') + '-07-15'
|
|
})
|
|
|
|
amount_in_widget = currency_id and amount_currency or amount
|
|
bank_stmt_line.process_reconciliation(payment_aml_rec=liquidity_aml)
|
|
return bank_stmt
|
|
|
|
def check_journal_items(self, aml_recs, aml_dicts):
|
|
def compare_rec_dict(aml_rec, aml_dict):
|
|
return aml_rec.account_id.id == aml_dict['account_id'] \
|
|
and round(aml_rec.debit, 2) == aml_dict['debit'] \
|
|
and round(aml_rec.credit, 2) == aml_dict['credit'] \
|
|
and round(aml_rec.amount_currency, 2) == aml_dict['amount_currency'] \
|
|
and aml_rec.currency_id.id == aml_dict['currency_id']
|
|
|
|
for aml_dict in aml_dicts:
|
|
# There is no unique key to identify journal items (an account_payment may create several lines
|
|
# in the same account), so to check the expected entries are created, we check there is a line
|
|
# matching for each dict of expected values
|
|
aml_rec = aml_recs.filtered(lambda r: compare_rec_dict(r, aml_dict))
|
|
self.assertEqual(len(aml_rec), 1, "Expected a move line with values : %s" % str(aml_dict))
|
|
if aml_dict.get('currency_diff'):
|
|
if aml_rec.credit:
|
|
currency_diff_move = aml_rec.matched_debit_ids.full_reconcile_id.exchange_move_id
|
|
else:
|
|
currency_diff_move = aml_rec.matched_credit_ids.full_reconcile_id.exchange_move_id
|
|
for currency_diff_line in currency_diff_move.line_ids:
|
|
if aml_dict.get('currency_diff') > 0:
|
|
if currency_diff_line.account_id.id == aml_rec.account_id.id:
|
|
self.assertAlmostEquals(currency_diff_line.debit, aml_dict.get('currency_diff'))
|
|
else:
|
|
self.assertAlmostEquals(currency_diff_line.credit, aml_dict.get('currency_diff'))
|
|
self.assertIn(currency_diff_line.account_id.id, [self.diff_expense_account.id, self.diff_income_account.id])
|
|
else:
|
|
if currency_diff_line.account_id.id == aml_rec.account_id.id:
|
|
self.assertAlmostEquals(currency_diff_line.credit, abs(aml_dict.get('currency_diff')))
|
|
else:
|
|
self.assertAlmostEquals(currency_diff_line.debit, abs(aml_dict.get('currency_diff')))
|
|
self.assertIn(currency_diff_line.account_id.id, [self.diff_expense_account.id, self.diff_income_account.id])
|
|
|
|
def test_full_payment_process(self):
|
|
""" Create a payment for two invoices, post it and reconcile it with a bank statement """
|
|
inv_1 = self.create_invoice(amount=100, currency_id=self.currency_eur_id)
|
|
inv_2 = self.create_invoice(amount=200, currency_id=self.currency_eur_id)
|
|
|
|
ctx = { 'active_model': 'account.invoice', 'active_ids': [inv_1.id, inv_2.id] }
|
|
register_payments = self.register_payments_model.with_context(ctx).create({
|
|
'payment_date': time.strftime('%Y') + '-07-15',
|
|
'journal_id': self.bank_journal_euro.id,
|
|
'payment_method_id': self.payment_method_manual_in.id,
|
|
})
|
|
register_payments.create_payment()
|
|
payment = self.payment_model.search([], order="id desc", limit=1)
|
|
|
|
self.assertAlmostEquals(payment.amount, 300)
|
|
self.assertEqual(payment.state, 'posted')
|
|
self.assertEqual(inv_1.state, 'paid')
|
|
self.assertEqual(inv_2.state, 'paid')
|
|
|
|
self.check_journal_items(payment.move_line_ids, [
|
|
{'account_id': self.account_eur.id, 'debit': 300.0, 'credit': 0.0, 'amount_currency': 0, 'currency_id': False},
|
|
{'account_id': inv_1.account_id.id, 'debit': 0.0, 'credit': 300.0, 'amount_currency': 00, 'currency_id': False},
|
|
])
|
|
|
|
liquidity_aml = payment.move_line_ids.filtered(lambda r: r.account_id == self.account_eur)
|
|
bank_statement = self.reconcile(liquidity_aml, 200, 0, False)
|
|
|
|
self.assertEqual(liquidity_aml.statement_id, bank_statement)
|
|
self.assertEqual(liquidity_aml.statement_line_id, bank_statement.line_ids[0])
|
|
|
|
self.assertEqual(payment.state, 'reconciled')
|
|
|
|
def test_internal_transfer_journal_usd_journal_eur(self):
|
|
""" Create a transfer from a EUR journal to a USD journal """
|
|
payment = self.payment_model.create({
|
|
'payment_date': time.strftime('%Y') + '-07-15',
|
|
'payment_type': 'transfer',
|
|
'amount': 50,
|
|
'currency_id': self.currency_usd_id,
|
|
'journal_id': self.bank_journal_usd.id,
|
|
'destination_journal_id': self.bank_journal_euro.id,
|
|
'payment_method_id': self.payment_method_manual_out.id,
|
|
})
|
|
payment.post()
|
|
self.check_journal_items(payment.move_line_ids, [
|
|
{'account_id': self.transfer_account.id, 'debit': 32.70, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_usd_id},
|
|
{'account_id': self.transfer_account.id, 'debit': 0.0, 'credit': 32.70, 'amount_currency': -50, 'currency_id': self.currency_usd_id},
|
|
{'account_id': self.account_eur.id, 'debit': 32.70, 'credit': 0.0, 'amount_currency': 0, 'currency_id': False},
|
|
{'account_id': self.account_usd.id, 'debit': 0.0, 'credit': 32.70, 'amount_currency': -50, 'currency_id': self.currency_usd_id},
|
|
])
|
|
|
|
def test_payment_chf_journal_usd(self):
|
|
payment = self.payment_model.create({
|
|
'payment_date': time.strftime('%Y') + '-07-15',
|
|
'payment_type': 'outbound',
|
|
'amount': 50,
|
|
'currency_id': self.currency_chf_id,
|
|
'journal_id': self.bank_journal_usd.id,
|
|
'partner_type': 'supplier',
|
|
'partner_id': self.partner_axelor.id,
|
|
'payment_method_id': self.payment_method_manual_out.id,
|
|
})
|
|
payment.post()
|
|
|
|
self.check_journal_items(payment.move_line_ids, [
|
|
{'account_id': self.account_usd.id, 'debit': 0.0, 'credit': 38.21, 'amount_currency': -58.42, 'currency_id': self.currency_usd_id},
|
|
{'account_id': self.partner_axelor.property_account_payable_id.id, 'debit': 38.21, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_chf_id},
|
|
])
|