From d3fcc72e0ffb7589404cd9a6a5991f012715731c Mon Sep 17 00:00:00 2001 From: Vitalij Mik Date: Mon, 16 Dec 2024 14:11:19 +0100 Subject: [PATCH] NTR: PISHPS-393: send delivery on cancel item (#916) Co-authored-by: Vitalij Mik --- .../CancelManager/CancelItemFacade.php | 7 +- src/Event/OrderLinesUpdatedEvent.php | 21 ++++++ src/Resources/config/services/api.xml | 1 + src/Resources/config/services/components.xml | 1 + src/Resources/config/services/subscriber.xml | 6 ++ src/Service/MollieApi/Shipment.php | 68 ++++--------------- .../OrderLinesUpdatedSubscriber.php | 57 ++++++++++++++++ .../PHPUnit/Fakes/CancelItemFacadeBuilder.php | 5 +- .../Service/MollieApi/ShipmentTest.php | 5 +- 9 files changed, 113 insertions(+), 58 deletions(-) create mode 100644 src/Event/OrderLinesUpdatedEvent.php create mode 100644 src/Subscriber/OrderLinesUpdatedSubscriber.php diff --git a/src/Components/CancelManager/CancelItemFacade.php b/src/Components/CancelManager/CancelItemFacade.php index 76ab9d1ea..8c7abb0d9 100644 --- a/src/Components/CancelManager/CancelItemFacade.php +++ b/src/Components/CancelManager/CancelItemFacade.php @@ -4,6 +4,7 @@ namespace Kiener\MolliePayments\Components\CancelManager; use Kiener\MolliePayments\Components\RefundManager\Integrators\StockManagerInterface; +use Kiener\MolliePayments\Event\OrderLinesUpdatedEvent; use Kiener\MolliePayments\Factory\MollieApiFactory; use Kiener\MolliePayments\Repository\OrderLineItem\OrderLineItemRepositoryInterface; use Mollie\Api\MollieApiClient; @@ -11,6 +12,7 @@ use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * @final @@ -23,13 +25,15 @@ class CancelItemFacade private LoggerInterface $logger; private OrderLineItemRepositoryInterface $orderLineItemRepository; private StockManagerInterface $stockManager; + private EventDispatcherInterface $eventDispatcher; - public function __construct(MollieApiFactory $clientFactory, OrderLineItemRepositoryInterface $orderLineItemRepository, StockManagerInterface $stockManager, LoggerInterface $logger) + public function __construct(MollieApiFactory $clientFactory, OrderLineItemRepositoryInterface $orderLineItemRepository, StockManagerInterface $stockManager, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger) { $this->client = $clientFactory->getClient(); $this->logger = $logger; $this->orderLineItemRepository = $orderLineItemRepository; $this->stockManager = $stockManager; + $this->eventDispatcher = $eventDispatcher; } public function cancelItem(string $mollieOrderId, string $mollieLineId, string $shopwareLineId, int $quantity, bool $resetStock, Context $context): CancelItemResponse @@ -86,6 +90,7 @@ public function cancelItem(string $mollieOrderId, string $mollieLineId, string $ $mollieOrder->cancelLines(['lines' => [$lines]]); $this->logger->info('Item cancelled successful', ['orderId' => $mollieOrderId, 'mollieLineId' => $mollieLineId, 'quantity' => $quantity]); + $this->eventDispatcher->dispatch(new OrderLinesUpdatedEvent($mollieOrder)); $response = $response->withData($lines); } catch (\Throwable $e) { diff --git a/src/Event/OrderLinesUpdatedEvent.php b/src/Event/OrderLinesUpdatedEvent.php new file mode 100644 index 000000000..000dbf4e5 --- /dev/null +++ b/src/Event/OrderLinesUpdatedEvent.php @@ -0,0 +1,21 @@ +mollieOrder = $mollieOrder; + } + + public function getMollieOrder(): Order + { + return $this->mollieOrder; + } +} diff --git a/src/Resources/config/services/api.xml b/src/Resources/config/services/api.xml index 24a8f2e4e..70d93c2b7 100644 --- a/src/Resources/config/services/api.xml +++ b/src/Resources/config/services/api.xml @@ -31,6 +31,7 @@ + diff --git a/src/Resources/config/services/components.xml b/src/Resources/config/services/components.xml index fc5db6262..8f2e79e7d 100644 --- a/src/Resources/config/services/components.xml +++ b/src/Resources/config/services/components.xml @@ -81,6 +81,7 @@ + diff --git a/src/Resources/config/services/subscriber.xml b/src/Resources/config/services/subscriber.xml index 48604b7af..c23e5b457 100644 --- a/src/Resources/config/services/subscriber.xml +++ b/src/Resources/config/services/subscriber.xml @@ -87,6 +87,12 @@ + + + + + + diff --git a/src/Service/MollieApi/Shipment.php b/src/Service/MollieApi/Shipment.php index 5b89ea282..05e8bf165 100644 --- a/src/Service/MollieApi/Shipment.php +++ b/src/Service/MollieApi/Shipment.php @@ -2,6 +2,7 @@ namespace Kiener\MolliePayments\Service\MollieApi; +use Kiener\MolliePayments\Event\OrderLinesUpdatedEvent; use Kiener\MolliePayments\Exception\CouldNotFetchMollieOrderException; use Kiener\MolliePayments\Exception\MollieOrderCouldNotBeShippedException; use Kiener\MolliePayments\Service\MollieApi\Models\MollieShippingItem; @@ -11,6 +12,7 @@ use Mollie\Api\Resources\Shipment as MollieShipment; use Mollie\Api\Resources\ShipmentCollection; use Mollie\Api\Types\OrderLineType; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class Shipment implements ShipmentInterface { @@ -18,13 +20,15 @@ class Shipment implements ShipmentInterface * @var Order */ private $orderApiService; + private EventDispatcherInterface $eventDispatcher; /** * @param Order $orderApiService */ - public function __construct(Order $orderApiService) + public function __construct(Order $orderApiService, EventDispatcherInterface $eventDispatcher) { $this->orderApiService = $orderApiService; + $this->eventDispatcher = $eventDispatcher; } /** @@ -78,8 +82,12 @@ public function shipOrder(string $mollieOrderId, string $salesChannelId, array $ ]; } - $options = $this->addShippingCosts($mollieOrder, $options); - return $mollieOrder->createShipment($options); + + $shipment = $mollieOrder->createShipment($options); + + $this->eventDispatcher->dispatch(new OrderLinesUpdatedEvent($mollieOrder)); + + return $shipment; } catch (ApiException $e) { throw new MollieOrderCouldNotBeShippedException( $mollieOrderId, @@ -121,9 +129,11 @@ public function shipItem(string $mollieOrderId, string $salesChannelId, string $ } $mollieOrder = $this->orderApiService->getMollieOrder($mollieOrderId, $salesChannelId); - $options = $this->addShippingCosts($mollieOrder, $options); - return $mollieOrder->createShipment($options); + + $shipment = $mollieOrder->createShipment($options); + $this->eventDispatcher->dispatch(new OrderLinesUpdatedEvent($mollieOrder)); + return $shipment; } catch (ApiException $e) { throw new MollieOrderCouldNotBeShippedException( $mollieOrderId, @@ -136,54 +146,6 @@ public function shipItem(string $mollieOrderId, string $salesChannelId, string $ } } - /** - * @param \Mollie\Api\Resources\Order $mollieOrder - * @param array $options - * @return array - */ - private function addShippingCosts(\Mollie\Api\Resources\Order $mollieOrder, array $options): array - { - $shippingOptions = []; - - $mollieLines = $mollieOrder->lines(); - - $shippableLines = []; - - /** - * @var OrderLine $line - */ - foreach ($mollieLines as $line) { - if ($line->type === OrderLineType::TYPE_SHIPPING_FEE) { - $shippingOptions[] = [ - 'id' => $line->id, - 'quantity' => $line->quantity, - ]; - continue; - } - if ($line->shippableQuantity > 0) { - $shippableLines[$line->id] = $line; - } - } - - - foreach ($options['lines'] as $line) { - $shippableLine = $shippableLines[$line['id']]??null; - if ($shippableLine === null) { - continue; - } - $shippableQuantity = $shippableLine->shippableQuantity - $line['quantity']; - if ($shippableQuantity === 0) { - unset($shippableLines[$line['id']]); - } - } - if (count($shippableLines) === 0) { - $options['lines'] = array_merge($options['lines'], $shippingOptions); - } - - - return $options; - } - /** * @param string $mollieOrderId * @param string $salesChannelId diff --git a/src/Subscriber/OrderLinesUpdatedSubscriber.php b/src/Subscriber/OrderLinesUpdatedSubscriber.php new file mode 100644 index 000000000..115d004c2 --- /dev/null +++ b/src/Subscriber/OrderLinesUpdatedSubscriber.php @@ -0,0 +1,57 @@ +logger = $logger; + } + + public static function getSubscribedEvents() + { + return [ + OrderLinesUpdatedEvent::class => 'onOrderLinesUpdated', + ]; + } + + public function onOrderLinesUpdated(OrderLinesUpdatedEvent $event): void + { + $mollieOrder = $event->getMollieOrder(); + + $shippingOptions = []; + + $mollieLines = $mollieOrder->lines(); + + /** + * @var OrderLine $line + */ + foreach ($mollieLines as $line) { + if ($line->type === OrderLineType::TYPE_SHIPPING_FEE && $line->shippableQuantity > 0) { + $shippingOptions[] = [ + 'id' => $line->id, + 'quantity' => $line->quantity, + ]; + } + } + + if (count($shippingOptions) === 0) { + return; + } + try { + $mollieOrder->createShipment(['lines' => $shippingOptions]); + } catch (\Exception $exception) { + $this->logger->error("Failed to update shipping costs", ['message' => $exception->getMessage(), 'options' => $shippingOptions]); + } + } +} diff --git a/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php b/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php index be0eac762..2a4d3497f 100644 --- a/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php +++ b/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php @@ -20,6 +20,7 @@ use Psr\Log\NullLogger; use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection; use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * @final @@ -101,10 +102,10 @@ public function bild(): CancelItemFacade /** @var MollieApiFactory $mollieFactory */ $mollieFactory = $this->testCase->getMockBuilder(MollieApiFactory::class)->disableOriginalConstructor()->getMock(); $mollieFactory->method('getClient')->willReturn($this->mollieClient); - + $dispatcher = $this->testCase->getMockBuilder(EventDispatcherInterface::class)->getMock(); $orderLineRepository = new FakeOrderLineItemRepository($this->itemCollection); - return new CancelItemFacade($mollieFactory, $orderLineRepository, $this->stockManager, new NullLogger()); + return new CancelItemFacade($mollieFactory, $orderLineRepository, $this->stockManager, $dispatcher, new NullLogger()); } } \ No newline at end of file diff --git a/tests/PHPUnit/Service/MollieApi/ShipmentTest.php b/tests/PHPUnit/Service/MollieApi/ShipmentTest.php index acf0818ca..1f12a3a89 100644 --- a/tests/PHPUnit/Service/MollieApi/ShipmentTest.php +++ b/tests/PHPUnit/Service/MollieApi/ShipmentTest.php @@ -13,6 +13,7 @@ use Mollie\Api\Resources\Shipment as MollieShipment; use Mollie\Api\Types\OrderLineType; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class ShipmentTest extends TestCase { @@ -34,11 +35,11 @@ class ShipmentTest extends TestCase protected function setUp(): void { $this->mollieOrder = $this->createMock(MollieOrder::class); - + $dispatcher = $this->createMock(EventDispatcherInterface::class); $this->orderApiService = $this->createMock(Order::class); $this->orderApiService->method('getMollieOrder')->willReturn($this->mollieOrder); - $this->shipmentApiService = new Shipment($this->orderApiService); + $this->shipmentApiService = new Shipment($this->orderApiService,$dispatcher); } protected function setUpOrderLines()