custom/plugins/UnzerPayment6/src/EventListeners/StateMachine/TransitionEventListener.php line 77

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace UnzerPayment6\EventListeners\StateMachine;
  4. use Psr\Log\LoggerInterface;
  5. use Shopware\Core\Checkout\Document\DocumentCollection;
  6. use Shopware\Core\Checkout\Document\DocumentEntity;
  7. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryDefinition;
  8. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
  9. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
  10. use Shopware\Core\Checkout\Order\OrderEntity;
  11. use Shopware\Core\Framework\Context;
  12. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  14. use Shopware\Core\System\StateMachine\Event\StateMachineTransitionEvent;
  15. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Throwable;
  18. use UnzerPayment6\Components\Event\AutomaticShippingNotificationEvent;
  19. use UnzerPayment6\Components\ShipService\ShipServiceInterface;
  20. use UnzerPayment6\Components\Validator\AutomaticShippingValidatorInterface;
  21. use UnzerPayment6\Installer\CustomFieldInstaller;
  22. class TransitionEventListener implements EventSubscriberInterface
  23. {
  24.     /** @var EntityRepositoryInterface */
  25.     private $orderRepository;
  26.     /** @var EntityRepositoryInterface */
  27.     private $orderDeliveryRepository;
  28.     /** @var EntityRepositoryInterface */
  29.     private $transactionRepository;
  30.     /** @var LoggerInterface */
  31.     private $logger;
  32.     /** @var AutomaticShippingValidatorInterface */
  33.     private $automaticShippingValidator;
  34.     /** @var EventDispatcherInterface */
  35.     private $eventDispatcher;
  36.     /** @var ShipServiceInterface */
  37.     private $shipService;
  38.     public function __construct(
  39.         EntityRepositoryInterface $orderRepository,
  40.         EntityRepositoryInterface $orderDeliveryRepository,
  41.         EntityRepositoryInterface $transactionRepository,
  42.         AutomaticShippingValidatorInterface $automaticShippingValidator,
  43.         LoggerInterface $logger,
  44.         EventDispatcherInterface $eventDispatcher,
  45.         ShipServiceInterface $shipService
  46.     ) {
  47.         $this->orderRepository            $orderRepository;
  48.         $this->orderDeliveryRepository    $orderDeliveryRepository;
  49.         $this->transactionRepository      $transactionRepository;
  50.         $this->logger                     $logger;
  51.         $this->automaticShippingValidator $automaticShippingValidator;
  52.         $this->eventDispatcher            $eventDispatcher;
  53.         $this->shipService                $shipService;
  54.     }
  55.     /**
  56.      * {@inheritdoc}
  57.      */
  58.     public static function getSubscribedEvents(): array
  59.     {
  60.         return [
  61.             StateMachineTransitionEvent::class => 'onStateMachineTransition',
  62.         ];
  63.     }
  64.     public function onStateMachineTransition(StateMachineTransitionEvent $event): void
  65.     {
  66.         $order $this->getOrderFromEvent($event);
  67.         if (!$order || !$this->automaticShippingValidator->shouldSendAutomaticShipping($order$event->getToPlace())) {
  68.             return;
  69.         }
  70.         if (!$this->automaticShippingValidator->hasInvoiceDocument($order)) {
  71.             $this->logger->error(sprintf('Error during automatic shipping validation for order [%s]: No invoice could be found'$order->getOrderNumber()));
  72.             return;
  73.         }
  74.         $orderTransactions $order->getTransactions();
  75.         if ($order->getDocuments() !== null) {
  76.             $invoiceNumber $this->getInvoiceDocumentNumber($order->getDocuments());
  77.         }
  78.         if ($orderTransactions !== null) {
  79.             $firstTransaction $orderTransactions->first();
  80.         }
  81.         if (empty($firstTransaction)) {
  82.             $this->logger->error(sprintf('Error while executing automatic shipping notification for order [%s]: orderTransaction could not be found'$order->getOrderNumber()));
  83.             return;
  84.         }
  85.         if (empty($invoiceNumber)) {
  86.             $this->logger->error(sprintf('Error while executing automatic shipping notification for order [%s]: Either invoice could not be found'$order->getOrderNumber()));
  87.             return;
  88.         }
  89.         try {
  90.             $this->shipService->shipTransaction($firstTransaction->getId(), $event->getContext());
  91.             $this->setCustomFields($event->getContext(), $firstTransaction);
  92.             $this->eventDispatcher->dispatch(new AutomaticShippingNotificationEvent($order$invoiceNumber$event->getContext()));
  93.             $this->logger->info(sprintf('The automatic shipping notification for order [%s] was executed with invoice [%s]'$order->getOrderNumber(), $invoiceNumber));
  94.         } catch (Throwable $exception) {
  95.             $this->logger->error(sprintf('Error while executing automatic shipping notification for order [%s]: %s'$order->getOrderNumber(), $exception->getMessage()), [
  96.                 'trace' => $exception->getTraceAsString(),
  97.             ]);
  98.         }
  99.     }
  100.     protected function setCustomFields(
  101.         Context $context,
  102.         OrderTransactionEntity $transaction
  103.     ): void {
  104.         $customFields $transaction->getCustomFields() ?? [];
  105.         $customFields array_merge($customFields, [
  106.             CustomFieldInstaller::UNZER_PAYMENT_IS_SHIPPED => true,
  107.         ]);
  108.         $update = [
  109.             'id'           => $transaction->getId(),
  110.             'customFields' => $customFields,
  111.         ];
  112.         $this->transactionRepository->update([$update], $context);
  113.     }
  114.     private function getOrderFromEvent(StateMachineTransitionEvent $transitionEvent): ?OrderEntity
  115.     {
  116.         if ($transitionEvent->getEntityName() === OrderDeliveryDefinition::ENTITY_NAME) {
  117.             $criteria = new Criteria([$transitionEvent->getEntityId()]);
  118.             $criteria->addAssociations([
  119.                 'order',
  120.                 'order.transactions',
  121.                 'order.documents',
  122.                 'order.documents.documentType',
  123.             ]);
  124.             /** @var null|OrderDeliveryEntity $orderDeliveryEntity */
  125.             $orderDeliveryEntity $this->orderDeliveryRepository->search($criteria$transitionEvent->getContext())->first();
  126.             if ($orderDeliveryEntity === null) {
  127.                 return null;
  128.             }
  129.             return $orderDeliveryEntity->getOrder();
  130.         }
  131.         $criteria = new Criteria([$transitionEvent->getEntityId()]);
  132.         $criteria->addAssociations([
  133.             'transactions',
  134.             'documents',
  135.             'documents.documentType',
  136.         ]);
  137.         return $this->orderRepository->search($criteria$transitionEvent->getContext())->first();
  138.     }
  139.     private function getInvoiceDocumentNumber(DocumentCollection $documents): string
  140.     {
  141.         $firstDocument $documents->filter(static function (DocumentEntity $entity) {
  142.             if ($entity->getDocumentType() !== null && $entity->getDocumentType()->getTechnicalName() === 'invoice') {
  143.                 return $entity;
  144.             }
  145.             return null;
  146.         })->first();
  147.         if (!empty($firstDocument)) {
  148.             return $firstDocument->getConfig()['documentNumber'];
  149.         }
  150.         return '';
  151.     }
  152. }