Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECP-9459]Solving the issue of Config "Refund strategy Giftcard" #2789

Merged
merged 15 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion Helper/Webhook/OrderClosedWebhookHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Adyen\Payment\Model\Notification;
use Magento\Sales\Model\Order as MagentoOrder;
use Adyen\Payment\Model\ResourceModel\Order\Payment\CollectionFactory as OrderPaymentCollectionFactory;
use Magento\Framework\Serialize\SerializerInterface;

class OrderClosedWebhookHandler implements WebhookHandlerInterface
{
Expand All @@ -38,6 +39,11 @@ class OrderClosedWebhookHandler implements WebhookHandlerInterface
/** @var OrderPaymentCollectionFactory */
private $adyenOrderPaymentCollectionFactory;

/**
* @var SerializerInterface
*/
private $serializer;
khushboo-singhvi marked this conversation as resolved.
Show resolved Hide resolved

/**
* @param AdyenOrderPayment $adyenOrderPayment
* @param OrderHelper $orderHelper
Expand All @@ -50,13 +56,15 @@ public function __construct(
OrderHelper $orderHelper,
Config $configHelper,
OrderPaymentCollectionFactory $adyenOrderPaymentCollectionFactory,
AdyenLogger $adyenLogger
AdyenLogger $adyenLogger,
SerializerInterface $serializer
) {
$this->adyenOrderPaymentHelper = $adyenOrderPayment;
$this->orderHelper = $orderHelper;
$this->configHelper = $configHelper;
$this->adyenOrderPaymentCollectionFactory = $adyenOrderPaymentCollectionFactory;
$this->adyenLogger = $adyenLogger;
$this->serializer = $serializer;
}

/**
Expand All @@ -71,7 +79,50 @@ public function handleWebhook(
Notification $notification,
string $transitionState
): MagentoOrder {
$additionalData = $notification->getAdditionalData();
if (!empty($additionalData)) {
$additionalData = $this->serializer->unserialize($additionalData);
}

if ($notification->isSuccessful()) {
foreach ($additionalData as $key => $value) {
// Check if the key matches the pattern "order-X-pspReference"
if (preg_match('/^order-(\d+)-pspReference$/', $key, $matches)) {
$orderIndex = (int)$matches[1];
$pspReference = $value;
$sortValue = $orderIndex;

// Retrieve adyen_order_payment for this pspReference
$adyenOrderPayment = $this->adyenOrderPaymentCollectionFactory->create()
->addFieldToFilter('pspreference', $pspReference)
khushboo-singhvi marked this conversation as resolved.
Show resolved Hide resolved
->getFirstItem();

if ($adyenOrderPayment->getId()) {
// Update the status with the order index
$adyenOrderPayment->setSortOrder($sortValue);
$adyenOrderPayment->save();

$this->adyenLogger->addAdyenNotification(
sprintf("Updated adyen_order_payment with order status %d for pspReference %s", $sortValue, $pspReference),
[
'pspReference' => $pspReference,
'status' => $sortValue,
'merchantReference' => $notification->getMerchantReference()
]
);
} else {
// Log if no matching record was found for the given pspReference
$this->adyenLogger->addAdyenNotification(
sprintf("No adyen_order_payment record found for pspReference %s", $pspReference),
[
'pspReference' => $pspReference,
'merchantReference' => $notification->getMerchantReference()
]
);
}
}
}

$order->addCommentToStatusHistory(__('This order has been successfully completed.'));
} else {
/** @var OrderPaymentInterface $orderPayment */
Expand Down
21 changes: 21 additions & 0 deletions Model/Order/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,25 @@ public function getFormattedTotalCapturedWithCurrency(): string
false
);
}

/**
* Set sort order.
*
* @param int $sortOrder
* @return $this
*/
public function setSortOrder($sortOrder)
{
return $this->setData('order_sort', $sortOrder);
}

/**
* Get sort order.
*
* @return int|null
*/
public function getSortOrder()
{
return $this->getData('order_sort');
}
}
4 changes: 2 additions & 2 deletions Model/ResourceModel/Order/Payment/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function getTotalAmount($paymentId, $captured = false)
public function addPaymentFilterAscending($paymentId)
{
$this->addFieldToFilter('payment_id', $paymentId);
$this->getSelect()->order(['created_at ASC']);
$this->getSelect()->order(['order_sort ASC']);
return $this;
}

Expand All @@ -83,7 +83,7 @@ public function addPaymentFilterAscending($paymentId)
public function addPaymentFilterDescending($paymentId)
{
$this->addFieldToFilter('payment_id', $paymentId);
$this->getSelect()->order(['created_at DESC', 'entity_id DESC']);
$this->getSelect()->order(['order_sort DESC']);
return $this;
}
}
168 changes: 168 additions & 0 deletions Test/Unit/Helper/Webhook/OrderClosedWebhookHandlerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?php
namespace Adyen\Payment\Test\Unit\Helper;

use Adyen\Payment\Test\Unit\AbstractAdyenTestCase;
use Magento\Framework\Serialize\SerializerInterface;
use PHPUnit\Framework\TestCase;
use Adyen\Payment\Helper\Webhook\OrderClosedWebhookHandler;
use Adyen\Payment\Helper\AdyenOrderPayment;
use Adyen\Payment\Helper\Config;
use Adyen\Payment\Helper\Order as OrderHelper;
use Adyen\Payment\Logger\AdyenLogger;
use Adyen\Payment\Model\Notification;
use Magento\Sales\Model\Order as MagentoOrder;
use Adyen\Payment\Model\ResourceModel\Order\Payment\CollectionFactory as OrderPaymentCollectionFactory;
use Adyen\Payment\Api\Data\OrderPaymentInterface;
use Magento\Sales\Api\Data\OrderPaymentInterface as MagentoOrderPaymentInterface;
use Magento\Sales\Model\Order;

class OrderClosedWebhookHandlerTest extends AbstractAdyenTestCase
{
private $orderClosedWebhookHandler;
private $adyenOrderPaymentHelperMock;
private $orderHelperMock;
private $configHelperMock;
private $adyenLoggerMock;
private $adyenOrderPaymentCollectionFactoryMock;
private $serializerMock;

protected function setUp(): void
{
$this->orderMock = $this->createMock(MagentoOrder::class);
$this->notificationMock = $this->createMock(Notification::class);
$this->adyenOrderPaymentCollectionMock = $this->createMock(\Magento\Framework\Data\Collection\AbstractDb::class);
$this->adyenOrderPaymentHelperMock = $this->createMock(AdyenOrderPayment::class);
$this->orderHelperMock = $this->createMock(OrderHelper::class);
$this->configHelperMock = $this->createMock(Config::class);
$this->adyenLoggerMock = $this->createMock(AdyenLogger::class);
$this->adyenOrderPaymentCollectionFactoryMock = $this->createGeneratedMock(OrderPaymentCollectionFactory::class, ['create']);
$this->adyenOrderPaymentMock = $this->createConfiguredMock(Order\Payment::class, [
'getId' => 123
]);
$this->serializerMock = $this->createMock(SerializerInterface::class);
$this->adyenOrderPaymentInterfaceMock = $this->createMock(OrderPaymentInterface::class);
$this->orderClosedWebhookHandler = new OrderClosedWebhookHandler(
$this->adyenOrderPaymentHelperMock,
$this->orderHelperMock,
$this->configHelperMock,
$this->adyenOrderPaymentCollectionFactoryMock,
$this->adyenLoggerMock,
$this->serializerMock
);
}

public function testHandleWebhookSuccessfulNotificationWithMatchingAdyenOrderPayment()
{
$additionalDataString = 'a:1:{s:20:"order-1-pspReference";s:16:"testPspReference";}';
$additionalData = array (
'order-1-pspReference' => 'testPspReference',
);
$this->notificationMock->expects($this->once())->method('isSuccessful')->willReturn(true);
$this->notificationMock->expects($this->once())->method('getAdditionalData')->willReturn($additionalDataString);
$this->serializerMock
->method('unserialize')
->with($additionalDataString)
->willReturn($additionalData);

$this->adyenOrderPaymentCollectionMock->method('addFieldToFilter')->willReturnSelf();
$this->adyenOrderPaymentCollectionMock->method('getFirstItem')->willReturn($this->adyenOrderPaymentMock);

$this->adyenOrderPaymentCollectionFactoryMock->method('create')->willReturn($this->adyenOrderPaymentCollectionMock);

$this->adyenLoggerMock->method('addAdyenNotification')
->with('Updated adyen_order_payment with order status 1 for pspReference testPspReference', [
'pspReference' => 'testPspReference',
'status' => 1,
'merchantReference' => $this->notificationMock->getMerchantReference()
]);

$this->orderMock->expects($this->once())->method('addCommentToStatusHistory')
->with(__('This order has been successfully completed.'));

$result = $this->orderClosedWebhookHandler->handleWebhook($this->orderMock, $this->notificationMock, 'completed');
$this->assertSame($this->orderMock, $result);
}

public function testHandleWebhookUnsuccessfulNotificationWithRefund()
{
$this->notificationMock->expects($this->once())->method('isSuccessful')->willReturn(false);

$this->orderMock->expects($this->once())->method('getPayment')->willReturn(
$this->createConfiguredMock(MagentoOrderPaymentInterface::class, ['getEntityId' => 123])
);

$this->adyenOrderPaymentCollectionMock->method('addFieldToFilter')
->willReturnSelf();

$this->adyenOrderPaymentCollectionMock->expects($this->once())->method('getItems')->willReturn([$this->adyenOrderPaymentInterfaceMock]);

$this->adyenOrderPaymentCollectionFactoryMock->expects($this->once())->method('create')->willReturn($this->adyenOrderPaymentCollectionMock);

$this->adyenOrderPaymentHelperMock->expects($this->once())->method('refundFullyAdyenOrderPayment')->with($this->adyenOrderPaymentInterfaceMock);

$this->orderMock->expects($this->once())->method('addCommentToStatusHistory')
->with(__('All the funds captured/settled will be refunded by Adyen.'));

$this->adyenLoggerMock->expects($this->once())->method('addAdyenNotification')
->with('All the funds captured/settled will be refunded by Adyen.', [
'pspReference' => $this->notificationMock->getPspreference(),
'merchantReference' => $this->notificationMock->getMerchantReference()
]);

$this->orderHelperMock->method('holdCancelOrder')->with($this->orderMock, true);

$this->configHelperMock->method('getNotificationsCanCancel')->with($this->orderMock->getStoreId())->willReturn(true);

$result = $this->orderClosedWebhookHandler->handleWebhook($this->orderMock, $this->notificationMock, 'completed');
$this->assertSame($this->orderMock, $result);
}

public function testHandleWebhookLogsMessageWhenNoMatchingRecordFound(): void
{
$pspReference = 'testPspReference';
$merchantReference = 'testMerchantReference';
$additionalData = [
'order-1-pspReference' => $pspReference,
];
$adyenOrderPaymentMock = $this->createConfiguredMock(Order\Payment::class, [
'getId' => null
]);

$this->notificationMock->expects($this->once())
->method('getAdditionalData')
->willReturn(json_encode($additionalData));
$this->notificationMock->expects($this->once())
->method('isSuccessful')
->willReturn(true);
$this->notificationMock->expects($this->once())
->method('getMerchantReference')
->willReturn($merchantReference);

$this->serializerMock->expects($this->once())
->method('unserialize')
->with(json_encode($additionalData))
->willReturn($additionalData);

$this->adyenOrderPaymentCollectionFactoryMock->expects($this->once())->method('create')->willReturn($this->adyenOrderPaymentCollectionMock);

$this->adyenOrderPaymentCollectionMock
->method('addFieldToFilter')
->willReturnSelf();
$this->adyenOrderPaymentCollectionMock->expects($this->once())
->method('getFirstItem')
->willReturn($adyenOrderPaymentMock);

// Log message assertion
$this->adyenLoggerMock->expects($this->once())
->method('addAdyenNotification')
->with(
sprintf("No adyen_order_payment record found for pspReference %s", $pspReference),
[
'pspReference' => $pspReference,
'merchantReference' => $merchantReference
]
);

$this->orderClosedWebhookHandler->handleWebhook($this->orderMock, $this->notificationMock, 'someTransitionState');
}
}
Loading
Loading