magento / magento2

Prior to making any Submission(s), you must sign an Adobe Contributor License Agreement, available here at: https://opensource.adobe.com/cla.html. All Submissions you make to Adobe Inc. and its affiliates, assigns and subsidiaries (collectively “Adobe”) are subject to the terms of the Adobe Contributor License Agreement.
http://www.magento.com
Open Software License 3.0
11.45k stars 9.29k forks source link

Double store credit refunds when a error is received before redirecting to external psp. #38815

Closed leonhelmus closed 1 month ago

leonhelmus commented 2 months ago

Preconditions and environment

Adobe Commerce: 2.4.6-p4 php 8.1

Steps to reproduce

Expected result

I get my store credit back, but not doubled.

Actual result

I get two times as much store credit back.

Additional information

Additional info If this function (\Magento\Quote\Model\QuoteManagement::submitQuote) receives an error of an external psp after the order has been created Magento will rollbackAddresses using this function: \Magento\Quote\Model\QuoteManagement::rollbackAddresses.

This than triggers the dispatch the event sales_model_service_quote_submit_failure which in turn invokes this observer: \Magento\CustomerBalance\Observer\RevertStoreCreditObserver::execute

Afterwards on the same event the external psp has this event:

    <event name="sales_model_service_quote_submit_failure">
        <observer name="external_psp_failed_quote_order" instance="Example\Magento2\Observer\HandleFailedQuoteOrder"/>
    </event>

Which triggers a cancellation of the order which triggers this function (\Magento\Sales\Model\Order::cancel) Which adds the following event order_cancel_after which triggers the same observer again: \Magento\CustomerBalance\Observer\RevertStoreCreditObserver::execute

In my opinion \Magento\CustomerBalance\Observer\RevertStoreCreditForOrder should check if the customer has already received a refund of store balance and if this has already been triggered it should skip saving an additional time. This is prone to add issues since it does not check if it has already refunded the store credit on quote level or order level.

Workaround fix/ patch

# Prevent double refund of store credit.
#
# Github link: https://github.com/magento/magento2/issues/38815
# Github link: https://github.com/buckaroo-it/Magento2/issues/989

diff --git a/Observer/RevertStoreCreditForOrder.php b/Observer/RevertStoreCreditForOrder.php
--- a/Observer/RevertStoreCreditForOrder.php
+++ b/Observer/RevertStoreCreditForOrder.php
@@ -5,6 +5,11 @@
  */
 namespace Magento\CustomerBalance\Observer;

+use Magento\CustomerBalance\Model\Balance\History;
+use Magento\CustomerBalance\Model\Balance\History as BalanceHistory;
+use Magento\CustomerBalance\Model\ResourceModel\Balance\History\Collection as HistoryCol;
+use Magento\CustomerBalance\Model\ResourceModel\Balance\History\CollectionFactory as HistoryColFactory;
+
 /**
  * Customer balance observer
  */
@@ -28,7 +33,8 @@
      */
     public function __construct(
         \Magento\CustomerBalance\Model\BalanceFactory $balanceFactory,
-        \Magento\Store\Model\StoreManagerInterface $storeManager
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        private readonly HistoryColFactory $historyColFactory,
     ) {
         $this->_balanceFactory = $balanceFactory;
         $this->_storeManager = $storeManager;
@@ -45,6 +51,32 @@
         if (!$order->getCustomerId() || !$order->getBaseCustomerBalanceAmount()) {
             return $this;
         }
+
+        if (!$order->getBaseCustomerBalanceInvoiced()) {
+            /** @var HistoryCol $historyCol */
+            $historyCol = $this->historyColFactory->create();
+            /** @var BalanceHistory $history */
+            $history = $historyCol->addFieldToFilter(
+                'customer_id',
+                ['eq' => $order->getCustomerId()]
+            )->addFieldToFilter(
+                'website_id',
+                ['eq' => $this->_storeManager->getStore($order->getStoreId())->getWebsiteId()]
+            )->addFieldToFilter(
+                'balance_delta',
+                ['eq' => $order->getBaseCustomerBalanceAmount()]
+            )->addFieldToFilter(
+                'action',
+                ['eq' => History::ACTION_REVERTED]
+            )->addFieldToFilter(
+                'additional_info',
+                ['like' => '%' . $order->getIncrementId() . '%']
+            )->getFirstItem();
+
+            if ($history->getId()) {
+                return $this;
+            }
+        }

         $customerAmountDelta = $order->getBaseCustomerBalanceAmount() - $order->getBaseCustomerBalanceInvoiced();

Release note

No response

Triage and priority

m2-assistant[bot] commented 2 months ago

Hi @leonhelmus. Thank you for your report. To speed up processing of this issue, make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, Add a comment to the issue:

m2-assistant[bot] commented 2 months ago

Hi @engcom-Dash. Thank you for working on this issue. In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:


engcom-Dash commented 1 month ago

Hi @leonhelmus

Thanks for reporting and collaboration.

Verified the issue on Magento 2.4.7-p1 but the issue is not reproducible.

Steps to reproduce First create a customer where you add store credit (magento_customerbalance). Than add a product which you can pay of partially or full with store credit. Than it could trigger a error from an external psp. In magento the order has been processed even though this error was given back. I get twice as much store credit back.

I am getting the store credit back, but not doubled.

Please refer the attached screenshots.

Customer store credit in admin

Screenshot 2024-07-17 at 3 39 56 PM

Placing the order with partial store credit and partially with Paypal and the error is triggered

Screenshot 2024-07-17 at 3 38 59 PM Screenshot 2024-07-17 at 3 40 43 PM

Refund received

Screenshot 2024-07-17 at 3 41 29 PM
engcom-Dash commented 1 month ago

Hi @leonhelmus

We have noticed that this issue has not been updated for a long time.
Hence we assume this issue is fixed, so we are closing it. Please feel free to raise a fresh ticket or reopen this ticket if you need more assistance.

Thanks.