From 9823d2fcaa35c5737a0afb3a54ba8064bcdfe1b4 Mon Sep 17 00:00:00 2001
From: Laurent Smet <las@odoo.com>
Date: Wed, 17 May 2023 07:27:47 +0000
Subject: [PATCH] [FIX] account: Prevent exchange diff entry with full refund

- create an invoice with a CABA tax
- full refund it using 'add credit note', 'cancel' mode.
=> No CABA entry generated but an exchange difference journal entry
has been created.

This is because the CABA entry is not generated in case of full refund
thanks to the 'move_reverse_cancel' context key. However, this key is not
preventing the generation of the exchange journal entry for CABA.

opw-3321897

closes odoo/odoo#121597

Signed-off-by: Brice Bartoletti (bib) <bib@odoo.com>
---
 addons/account/models/account_move.py         |  4 +-
 .../tests/test_account_move_reconcile.py      | 39 +++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 4ea04af02c9e..1495f97c441c 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -5405,8 +5405,10 @@ class AccountMoveLine(models.Model):
         to_reconcile = _add_lines_to_exchange_difference_vals(self, exchange_diff_move_vals)
 
         # Fix cash basis entries.
+        # If we are fully reversing the entry, no need to fix anything since the journal entry
+        # is exactly the mirror of the source journal entry.
         is_cash_basis_needed = self[0].account_internal_type in ('receivable', 'payable')
-        if is_cash_basis_needed:
+        if is_cash_basis_needed and not self._context.get('move_reverse_cancel'):
             _add_cash_basis_lines_to_exchange_difference_vals(self, exchange_diff_move_vals)
 
         # ==========================================================================
diff --git a/addons/account/tests/test_account_move_reconcile.py b/addons/account/tests/test_account_move_reconcile.py
index 176df30299cd..10dce8653195 100644
--- a/addons/account/tests/test_account_move_reconcile.py
+++ b/addons/account/tests/test_account_move_reconcile.py
@@ -3051,3 +3051,42 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
             }
         ]
         self.assertRecordValues(caba_move.line_ids, expected_values)
+
+    def test_cash_basis_full_refund(self):
+        """ Ensure the caba entry and the exchange difference journal entry for caba are not created in case of full
+        refund.
+        """
+        self.env.company.tax_exigibility = True
+
+        tax = self.env['account.tax'].create({
+            'name': 'cash basis 20%',
+            'type_tax_use': 'purchase',
+            'amount': 20,
+            'tax_exigibility': 'on_payment',
+            'cash_basis_transition_account_id': self.cash_basis_transfer_account.id,
+        })
+
+        invoice = self.init_invoice('out_invoice', post=True, amounts=[1000.0], taxes=tax)
+
+        # Reverse completely the invoice.
+        credit_note_wizard = self.env['account.move.reversal']\
+            .with_context({'active_ids': invoice.ids, 'active_model': 'account.move'})\
+            .create({
+                'refund_method': 'cancel',
+                'reason': 'test_cash_basis_full_refund',
+                'journal_id': invoice.journal_id.id,
+        })
+        action_values = credit_note_wizard.reverse_moves()
+        self.assertRecordValues(invoice, [{'payment_state': 'reversed'}])
+
+        # Check no CABA move has been created.
+        cash_basis_moves = self.env['account.move']\
+            .search([('tax_cash_basis_origin_move_id', 'in', (invoice.id, action_values['res_id']))])
+        self.assertFalse(cash_basis_moves)
+
+        # No exchange journal entry created for CABA.
+        caba_transfer_amls = self.env['account.move.line'].search([
+            ('account_id', '=', self.cash_basis_transfer_account.id),
+            ('move_id', 'not in', (invoice.id, action_values['res_id'])),
+        ])
+        self.assertFalse(caba_transfer_amls.move_id)
-- 
GitLab