custom/plugins/WbfkExtensions/src/Subscriber/ExpectedLineItemDeliverySubscriber.php line 148

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace WbfkExtensions\Subscriber;
  4. use Shopware\Core\Checkout\Cart\Delivery\Struct\ShippingLocation;
  5. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
  6. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  7. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionDefinition;
  8. use Shopware\Core\Checkout\Order\Event\OrderStateChangeCriteriaEvent;
  9. use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
  10. use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
  11. use Shopware\Core\Content\Product\SalesChannel\ProductAvailableFilter;
  12. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  13. use Shopware\Core\Defaults;
  14. use Shopware\Core\Framework\Context;
  15. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  20. use Shopware\Core\Framework\Util\Random;
  21. use Shopware\Core\Framework\Uuid\Uuid;
  22. use Shopware\Core\PlatformRequest;
  23. use Shopware\Core\System\Country\CountryEntity;
  24. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceParameters;
  25. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  26. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  27. use Shopware\Core\System\StateMachine\Aggregation\StateMachineTransition\StateMachineTransitionActions;
  28. use Shopware\Core\System\StateMachine\Event\StateMachineTransitionEvent;
  29. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  30. use WbfkExtensions\Core\Checkout\Cart\Delivery\ExpectedProductDeliveryTimeByQuantity\ExpectedProductDeliveryTimeByQuantityCollection;
  31. use WbfkExtensions\Core\Checkout\Cart\Delivery\ExpectedProductDeliveryTimeByQuantity\ExpectedProductDeliveryTimeByQuantityEntity;
  32. use WbfkExtensions\Core\Checkout\Cart\Delivery\ExpectedProductDeliveryTimeByQuantity\ExpectedProductDeliveryTimeByQuantityService;
  33. use WbfkExtensions\Core\Checkout\Cart\Delivery\ShippingAndDeliveryInformationService;
  34. class ExpectedLineItemDeliverySubscriber implements EventSubscriberInterface
  35. {
  36.     public function __construct(
  37.         private readonly EntityRepository                             $orderLineItemRepository,
  38.         private readonly ExpectedProductDeliveryTimeByQuantityService $expectedProductDeliveryTimeByQuantityService,
  39.         private readonly SalesChannelRepositoryInterface              $salesChannelProductRepository,
  40.         private readonly ShippingAndDeliveryInformationService        $shippingAndDeliveryInformationService
  41.     )
  42.     {
  43.     }
  44.     public static function getSubscribedEvents(): array
  45.     {
  46.         return [
  47.             StateMachineTransitionEvent::class => 'onOrderPaidCreateExpectedLineItemDeliveries',
  48.             OrderStateChangeCriteriaEvent::class => 'onOrderStateChangeCriteriaEvent'
  49.         ];
  50.     }
  51.     /**
  52.      * When an order is paid, update existing order item expected delivery times
  53.      * If payment method is ...
  54.      * - Invoice: Delivery happens before payment. This is why we don't need to update the expected delivery time,
  55.      *            because the delivery time, which was calculated during the checkout, is still correct.
  56.      * - NOT invoice: Delivery happens after payment. The shipping process starts now (not earlier).
  57.      *            This is why we have to recalculate the expected delivery time for the line items.
  58.      *
  59.      * @throws \Exception
  60.      */
  61.     public function onOrderPaidCreateExpectedLineItemDeliveries(StateMachineTransitionEvent $event): void
  62.     {
  63.         if ($event->getEntityName() === OrderTransactionDefinition::ENTITY_NAME
  64.             && $event->getToPlace()->getTechnicalName() === StateMachineTransitionActions::ACTION_PAID
  65.         ) {
  66.             $orderTransactionId $event->getEntityId();
  67.             $orderLineItemCriteria = new Criteria();
  68.             $orderLineItemCriteria->addAssociation('expectedProductDeliveryTimeByQuantityCollection');
  69.             $expectedDeliveryTimeAssociation $orderLineItemCriteria->getAssociation('expectedProductDeliveryTimeByQuantityCollection');
  70.             $expectedDeliveryTimeAssociation->addFilter(new EqualsFilter('isChild'false));
  71.             $orderLineItemCriteria->addAssociation('order.deliveries.shippingOrderAddress.country');
  72.             $deliveriesAssociation $orderLineItemCriteria->getAssociation('order.deliveries');
  73.             $deliveriesAssociation->addSorting(new FieldSorting('createdAt'FieldSorting::ASCENDING));
  74.             $orderLineItemCriteria->addAssociation('order.transactions.paymentMethod');
  75.             $transactionsAssociation $orderLineItemCriteria->getAssociation('order.transactions');
  76.             $transactionsAssociation->addSorting(new FieldSorting('createdAt'FieldSorting::ASCENDING));
  77.             $orderLineItemCriteria->addFilter(
  78.                 new EqualsFilter('order.transactions.id'$orderTransactionId),
  79.                 new NotFilter(NotFilter::CONNECTION_AND, [new EqualsFilter('productId'null)])
  80.             );
  81.             $updatedExpectedDeliveryTimes = new ExpectedProductDeliveryTimeByQuantityCollection();
  82.             $orderLineItems $this->orderLineItemRepository->search($orderLineItemCriteria$event->getContext());
  83.             /** @var OrderLineItemEntity $orderLineItem */
  84.             foreach ($orderLineItems as $orderLineItem) {
  85.                 // Skip this line item, if it has no expected delivery times
  86.                 $expectedDeliveryTimes $orderLineItem->getExtension(ExpectedProductDeliveryTimeByQuantityCollection::LINE_ITEM_EXTENSION_KEY);
  87.                 if (!$expectedDeliveryTimes || $expectedDeliveryTimes->count() === 0) continue;
  88.                 // Recalculate expected delivery times only, when the payment method is not "Invoice" and a delivery country is available
  89.                 /** @var PaymentMethodEntity $paymentMethod */
  90.                 $paymentMethod $orderLineItem->getOrder()->getTransactions()->last()?->getPaymentMethod();
  91.                 /** @var CountryEntity $country */
  92.                 $country $orderLineItem->getOrder()->getDeliveries()->last()?->getShippingOrderAddress()?->getCountry();
  93.                 if (!in_array($paymentMethod->getName(), ['Rechnungskauf''Invoice']) && !!$country) {
  94.                     /** @var ExpectedProductDeliveryTimeByQuantityEntity $expectedDeliveryTime */
  95.                     foreach ($expectedDeliveryTimes as $expectedDeliveryTime) {
  96.                         $this->shippingAndDeliveryInformationService->recalculateExpectedDeliveryDates($expectedDeliveryTime$country$event->getContext());
  97.                     }
  98.                 }
  99.                 /** @var ExpectedProductDeliveryTimeByQuantityEntity $expectedDeliveryTime */
  100.                 foreach ($expectedDeliveryTimes as $expectedDeliveryTime) {
  101.                     $expectedDeliveryTime->setIsReminderMailScheduled(true);
  102.                     $updatedExpectedDeliveryTimes->add($expectedDeliveryTime);
  103.                 }
  104.             }
  105.             $this->expectedProductDeliveryTimeByQuantityService->updateExpectedDeliveryTimes($updatedExpectedDeliveryTimes$event->getContext());
  106.         }
  107.     }
  108.     /**
  109.      * @param string $productId
  110.      * @param SalesChannelContext $salesChannelContext
  111.      * @return SalesChannelProductEntity|null
  112.      */
  113.     private function fetchSalesChannelProduct(string $productIdSalesChannelContext $salesChannelContext): ?SalesChannelProductEntity
  114.     {
  115.         $criteria = new Criteria([$productId]);
  116.         $criteria->addAssociation('shippingAndDeliveryInformations');
  117.         $criteria->addAssociation('productSuppliers.wbfkSupplier');
  118.         $results $this->salesChannelProductRepository->search($criteria$salesChannelContext);
  119.         if ($results->count() > 0) return $results->first();
  120.         return null;
  121.     }
  122.     /**
  123.      * @param OrderStateChangeCriteriaEvent $event
  124.      * @return void
  125.      */
  126.     public function onOrderStateChangeCriteriaEvent(OrderStateChangeCriteriaEvent $event)
  127.     {
  128.         $criteria $event->getCriteria();
  129.         $criteria->addAssociation('lineItems.' ExpectedProductDeliveryTimeByQuantityCollection::LINE_ITEM_EXTENSION_KEY);
  130.     }
  131. }