custom/plugins/WbfkExtensions/src/Subscriber/AttachDeliveryTimeDataToOrder.php line 41

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace WbfkExtensions\Subscriber;
  4. use Doctrine\DBAL\Connection;
  5. use Doctrine\DBAL\Exception;
  6. use RuntimeException;
  7. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  8. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  9. use Shopware\Core\Checkout\Cart\Order\CartConvertedEvent;
  10. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  11. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
  12. use Shopware\Core\Defaults;
  13. use Shopware\Core\Framework\Uuid\Uuid;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use WbfkExtensions\Core\Checkout\Cart\Delivery\DeliveryMode;
  16. use WbfkExtensions\Core\Checkout\Cart\Delivery\ExpectedProductDeliveryTimeByQuantity\ExpectedProductDeliveryTimeByQuantityCollection;
  17. use WbfkExtensions\Core\Checkout\Cart\Delivery\ExpectedProductDeliveryTimeByQuantity\ExpectedProductDeliveryTimeByQuantityEntity;
  18. use WbfkExtensions\Core\Checkout\Cart\Delivery\ExpectedProductDeliveryTimeByQuantity\ExpectedProductDeliveryTimeByQuantityService;
  19. class AttachDeliveryTimeDataToOrder implements EventSubscriberInterface
  20. {
  21.     public function __construct(
  22.         private readonly ExpectedProductDeliveryTimeByQuantityService $expectedProductDeliveryTimeByQuantityService,
  23.         private readonly Connection $connection
  24.     ) {
  25.     }
  26.     public static function getSubscribedEvents(): array
  27.     {
  28.         return [
  29.             CartConvertedEvent::class => 'onCartConvertedEvent',
  30.             CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlacedEvent',
  31.         ];
  32.     }
  33.     public function onCartConvertedEvent(CartConvertedEvent $event)
  34.     {
  35.         $this->setDeliveryModeCustomField($event);
  36.         $this->addDeliveryTimeDataToConvertedCart($event);
  37.     }
  38.     private function setDeliveryModeCustomField(CartConvertedEvent $event): void
  39.     {
  40.         $cart $event->getCart();
  41.         $convertedCart $event->getConvertedCart();
  42.         $customFields $convertedCart['customFields'] ?? [];
  43.         $customFields[DeliveryMode::CART_EXTENSION_KEY] = $cart->getExtension(
  44.             DeliveryMode::CART_EXTENSION_KEY
  45.         );
  46.         $convertedCart['customFields'] = $customFields;
  47.         $event->setConvertedCart($convertedCart);
  48.     }
  49.     public function addDeliveryTimeDataToConvertedCart(CartConvertedEvent $event): void
  50.     {
  51.         $cart $event->getCart();
  52.         $convertedCart $event->getConvertedCart();
  53.         $lineItems $cart->getLineItems()->filterFlatByType(LineItem::PRODUCT_LINE_ITEM_TYPE);
  54.         $extensionKey ExpectedProductDeliveryTimeByQuantityCollection::LINE_ITEM_EXTENSION_KEY;
  55.         foreach ($lineItems as $lineItem) {
  56.             $lineItemDataKey $this->findLineItemDataKey($event->getConvertedCart(), $lineItem);
  57.             if ($lineItemDataKey === null) {
  58.                 throw new RuntimeException('Could not find line item data key');
  59.             }
  60.             // Store products expected delivery time by quantity in converted cart if available
  61.             $convertedCart['lineItems'][$lineItemDataKey]['payload'][$extensionKey] = $lineItem->getExtension($extensionKey);
  62.         }
  63.         $event->setConvertedCart($convertedCart);
  64.     }
  65.     private function findLineItemDataKey(array $convertedCartLineItem $lineItem): int|string|null
  66.     {
  67.         foreach ($convertedCart['lineItems'] as $key => $lineItemData) {
  68.             if ($lineItemData['referencedId'] === $lineItem->getReferencedId()) {
  69.                 return $key;
  70.             }
  71.         }
  72.         return null;
  73.     }
  74.     /**
  75.      * @throws Exception
  76.      */
  77.     public function onCheckoutOrderPlacedEvent(CheckoutOrderPlacedEvent $event)
  78.     {
  79.         $order $event->getOrder();
  80.         $extensionKey ExpectedProductDeliveryTimeByQuantityCollection::LINE_ITEM_EXTENSION_KEY;
  81.         $orderLineItems $order->getLineItems()->filter(fn(OrderLineItemEntity $orderLineItem) => $orderLineItem->getType() === LineItem::PRODUCT_LINE_ITEM_TYPE);
  82.         /** @var OrderLineItemEntity $orderLineItem */
  83.         foreach ($orderLineItems as $orderLineItem) {
  84.             $lineItemPayload $orderLineItem->getPayload();
  85.             /** @var ?ExpectedProductDeliveryTimeByQuantityCollection $expectedProductDeliveryTimesByQuantity */
  86.             $expectedProductDeliveryTimesByQuantity $lineItemPayload[$extensionKey] ?? null;
  87.             if (!$expectedProductDeliveryTimesByQuantity || empty($expectedProductDeliveryTimesByQuantity)) {
  88.                 continue;
  89.             }
  90.             $expectedProductDeliveryTimesByQuantity $this->restoreExpectedDeliveryByQuantityFromArray($expectedProductDeliveryTimesByQuantity);
  91.             if ($expectedProductDeliveryTimesByQuantity->count() === 0) {
  92.                 continue;
  93.             }
  94.             // In case the payment method is "Invoice", activate the expected delivery reminder mail right away (no need to wait for the payment)
  95.             /** @var ?OrderTransactionEntity $transaction */
  96.             $transaction $order->getTransactions()->last();
  97.             if (!!$transaction && in_array($transaction->getPaymentMethod()->getName(), ['Invoice''Rechnungskauf'])) {
  98.                 /** @var ExpectedProductDeliveryTimeByQuantityEntity $expectedDeliveryTime */
  99.                 foreach ($expectedProductDeliveryTimesByQuantity as $expectedDeliveryTime) {
  100.                     $expectedDeliveryTime->setIsReminderMailScheduled(true);
  101.                 }
  102.             }
  103.             // Save expectedProductDeliveryTimesByQuantity as entities
  104.             /** @var ExpectedProductDeliveryTimeByQuantityEntity $expectedDeliveryTime */
  105.             foreach ($expectedProductDeliveryTimesByQuantity as $expectedDeliveryTime) {
  106.                 $expectedDeliveryTime->setOrderLineItemId($orderLineItem->getId());
  107.                 $expectedDeliveryTime->setOrderId($orderLineItem->getOrderId());
  108.             }
  109.             $this->expectedProductDeliveryTimeByQuantityService->saveCollection($expectedProductDeliveryTimesByQuantity$event->getContext());
  110.             $orderLineItem->addExtension($extensionKey$expectedProductDeliveryTimesByQuantity);
  111.             // Remove expectedProductDeliveryTimesByQuantity from the line item payload
  112.             unset($lineItemPayload[$extensionKey]);
  113.             $orderLineItem->setPayload($lineItemPayload);
  114.             $updateLineItemPayloadSql = <<<SQL
  115.                 UPDATE order_line_item SET payload = :payload WHERE id = :id AND version_id = :version_id
  116.             SQL;
  117.             $this->connection->executeStatement($updateLineItemPayloadSql, [
  118.                 'payload' => json_encode($lineItemPayload),
  119.                 'id' => Uuid::fromHexToBytes($orderLineItem->getId()),
  120.                 'version_id' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION),
  121.             ]);
  122.         }
  123.     }
  124.     /**
  125.      * @throws \Exception
  126.      */
  127.     private function restoreExpectedDeliveryByQuantityFromArray(array $items): ExpectedProductDeliveryTimeByQuantityCollection
  128.     {
  129.         $expectedDeliveryTimeByQuantityCollection = new ExpectedProductDeliveryTimeByQuantityCollection();
  130.         foreach ($items as $item) {
  131.             $expectedDeliveryTimeByQuantityCollection->add(
  132.                 ExpectedProductDeliveryTimeByQuantityEntity::create(
  133.                     $item['orderLineItemId'] ?? null,
  134.                     $item['orderId'] ?? null,
  135.                     $item['productId'] ?? null,
  136.                     $item['productVersionId'] ?? null,
  137.                     $item['isChild'] ?? false,
  138.                     $item['quantity'] ?? null,
  139.                     $item['availableStock'] ?? null,
  140.                     $item['supplierId'] ?? null,
  141.                     $item['supplierPriority'] ?? null,
  142.                     $item['supplierDisplayName'] ?? null,
  143.                     $item['expectedMinimumReadyToShipDate'] ?? null,
  144.                     $item['expectedMaximumReadyToShipDate'] ?? null,
  145.                     $item['expectedMinimumDeliveryDate'] ?? null,
  146.                     $item['expectedMaximumDeliveryDate'] ?? null,
  147.                     $item['reminderMailScheduled'] ?? false,
  148.                     $item['reminderMailSentAt'] ?? null
  149.                 )
  150.             );
  151.         }
  152.         return $expectedDeliveryTimeByQuantityCollection;
  153.     }
  154. }