From da27836f454ab65fbd268e6d19fbf4f2d4977a6c Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Tue, 24 Apr 2018 10:59:18 +0200 Subject: [PATCH] [FIX] account: unreconcile payment - Company currency in EUR - Create 2 rates for USD: 1.0 on 2018-01-01 0.5 on 2018-02-01 - Create an invoice on 2018-01-02 of 111 USD - Register a payment on 2018-02-02 of 111 USD - Unreconcile the payment An error occurs: 'You are trying to reconcile some entries that are already reconciled!' In this specific case where the rate decreases, the exchange rate entry is reconciled with the payment, so we need to keep the payment entries. --- addons/account/models/account_move.py | 3 +- addons/account/tests/test_reconciliation.py | 48 +++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 5df5f1c93c7..1c0bec65626 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -1064,8 +1064,9 @@ class AccountMoveLine(models.Model): rec_move_ids += account_move_line.matched_credit_ids if self.env.context.get('invoice_id'): current_invoice = self.env['account.invoice'].browse(self.env.context['invoice_id']) + aml_to_keep = current_invoice.move_id.line_ids | current_invoice.move_id.line_ids.mapped('full_reconcile_id.exchange_move_id.line_ids') rec_move_ids = rec_move_ids.filtered( - lambda r: (r.debit_move_id + r.credit_move_id) & current_invoice.move_id.line_ids + lambda r: (r.debit_move_id + r.credit_move_id) & aml_to_keep ) return rec_move_ids.unlink() diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index 8616fbb746f..af7abc9409b 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -656,3 +656,51 @@ class TestReconciliation(AccountingTestCase): credit_aml.with_context(invoice_id=inv2.id).remove_move_reconcile() self.assertAlmostEquals(inv1.residual, 10) self.assertAlmostEquals(inv2.residual, 20) + + def test_unreconcile_exchange(self): + # Use case: + # - Company currency in EUR + # - Create 2 rates for USD: + # 1.0 on 2018-01-01 + # 0.5 on 2018-02-01 + # - Create an invoice on 2018-01-02 of 111 USD + # - Register a payment on 2018-02-02 of 111 USD + # - Unreconcile the payment + + self.env['res.currency.rate'].create({ + 'name': time.strftime('%Y') + '-07-01', + 'rate': 1.0, + 'currency_id': self.currency_usd_id, + 'company_id': self.env.ref('base.main_company').id + }) + self.env['res.currency.rate'].create({ + 'name': time.strftime('%Y') + '-08-01', + 'rate': 0.5, + 'currency_id': self.currency_usd_id, + 'company_id': self.env.ref('base.main_company').id + }) + inv = self.create_invoice(invoice_amount=111, currency_id=self.currency_usd_id) + payment = self.env['account.payment'].create({ + 'payment_type': 'inbound', + 'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id, + 'partner_type': 'customer', + 'partner_id': self.partner_agrolait_id, + 'amount': 111, + 'currency_id': self.currency_usd_id, + 'journal_id': self.bank_journal_usd.id, + 'payment_date': time.strftime('%Y') + '-08-01', + }) + payment.post() + credit_aml = payment.move_line_ids.filtered('credit') + + # Check residual before assignation + self.assertAlmostEquals(inv.residual, 111) + + # Assign credit, check exchange move and residual + inv.assign_outstanding_credit(credit_aml.id) + self.assertEqual(len(payment.move_line_ids.mapped('full_reconcile_id').exchange_move_id), 1) + self.assertAlmostEquals(inv.residual, 0) + + # Unreconcile invoice and check residual + credit_aml.with_context(invoice_id=inv.id).remove_move_reconcile() + self.assertAlmostEquals(inv.residual, 111)