vendor/shopware/core/Checkout/Order/SalesChannel/OrderService.php line 77

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Order\SalesChannel;
  3. use Shopware\Core\Checkout\Cart\Cart;
  4. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  5. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
  6. use Shopware\Core\Checkout\Order\Exception\PaymentMethodNotAvailableException;
  7. use Shopware\Core\Checkout\Order\OrderEntity;
  8. use Shopware\Core\Framework\Context;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\Validation\BuildValidationEvent;
  13. use Shopware\Core\Framework\Validation\DataBag\DataBag;
  14. use Shopware\Core\Framework\Validation\DataValidationDefinition;
  15. use Shopware\Core\Framework\Validation\DataValidationFactoryInterface;
  16. use Shopware\Core\Framework\Validation\DataValidator;
  17. use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
  18. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  19. use Shopware\Core\System\StateMachine\Aggregation\StateMachineState\StateMachineStateEntity;
  20. use Shopware\Core\System\StateMachine\Exception\StateMachineStateNotFoundException;
  21. use Shopware\Core\System\StateMachine\StateMachineRegistry;
  22. use Shopware\Core\System\StateMachine\Transition;
  23. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  24. use Symfony\Component\HttpFoundation\ParameterBag;
  25. class OrderService
  26. {
  27.     public const CUSTOMER_COMMENT_KEY 'customerComment';
  28.     public const AFFILIATE_CODE_KEY 'affiliateCode';
  29.     public const CAMPAIGN_CODE_KEY 'campaignCode';
  30.     public const ALLOWED_TRANSACTION_STATES = [
  31.         OrderTransactionStates::STATE_OPEN,
  32.         OrderTransactionStates::STATE_CANCELLED,
  33.         OrderTransactionStates::STATE_REMINDED,
  34.         OrderTransactionStates::STATE_FAILED,
  35.         OrderTransactionStates::STATE_CHARGEBACK,
  36.         OrderTransactionStates::STATE_UNCONFIRMED,
  37.     ];
  38.     private DataValidator $dataValidator;
  39.     private DataValidationFactoryInterface $orderValidationFactory;
  40.     private EventDispatcherInterface $eventDispatcher;
  41.     private CartService $cartService;
  42.     private EntityRepositoryInterface $paymentMethodRepository;
  43.     private StateMachineRegistry $stateMachineRegistry;
  44.     /**
  45.      * @internal
  46.      */
  47.     public function __construct(
  48.         DataValidator $dataValidator,
  49.         DataValidationFactoryInterface $orderValidationFactory,
  50.         EventDispatcherInterface $eventDispatcher,
  51.         CartService $cartService,
  52.         EntityRepositoryInterface $paymentMethodRepository,
  53.         StateMachineRegistry $stateMachineRegistry
  54.     ) {
  55.         $this->dataValidator $dataValidator;
  56.         $this->orderValidationFactory $orderValidationFactory;
  57.         $this->eventDispatcher $eventDispatcher;
  58.         $this->cartService $cartService;
  59.         $this->paymentMethodRepository $paymentMethodRepository;
  60.         $this->stateMachineRegistry $stateMachineRegistry;
  61.     }
  62.     /**
  63.      * @throws ConstraintViolationException
  64.      */
  65.     public function createOrder(DataBag $dataSalesChannelContext $context): string
  66.     {
  67.         $this->validateOrderData($data$context);
  68.         $cart $this->cartService->getCart($context->getToken(), $context);
  69.         $this->validateCart($cart$context->getContext());
  70.         return $this->cartService->order($cart$context$data->toRequestDataBag());
  71.     }
  72.     /**
  73.      * @internal Should not be called from outside the core
  74.      */
  75.     public function orderStateTransition(
  76.         string $orderId,
  77.         string $transition,
  78.         ParameterBag $data,
  79.         Context $context
  80.     ): StateMachineStateEntity {
  81.         $stateFieldName $data->get('stateFieldName''stateId');
  82.         $stateMachineStates $this->stateMachineRegistry->transition(
  83.             new Transition(
  84.                 'order',
  85.                 $orderId,
  86.                 $transition,
  87.                 $stateFieldName
  88.             ),
  89.             $context
  90.         );
  91.         $toPlace $stateMachineStates->get('toPlace');
  92.         if (!$toPlace) {
  93.             throw new StateMachineStateNotFoundException('order_transaction'$transition);
  94.         }
  95.         return $toPlace;
  96.     }
  97.     /**
  98.      * @internal Should not be called from outside the core
  99.      */
  100.     public function orderTransactionStateTransition(
  101.         string $orderTransactionId,
  102.         string $transition,
  103.         ParameterBag $data,
  104.         Context $context
  105.     ): StateMachineStateEntity {
  106.         $stateFieldName $data->get('stateFieldName''stateId');
  107.         $stateMachineStates $this->stateMachineRegistry->transition(
  108.             new Transition(
  109.                 'order_transaction',
  110.                 $orderTransactionId,
  111.                 $transition,
  112.                 $stateFieldName
  113.             ),
  114.             $context
  115.         );
  116.         $toPlace $stateMachineStates->get('toPlace');
  117.         if (!$toPlace) {
  118.             throw new StateMachineStateNotFoundException('order_transaction'$transition);
  119.         }
  120.         return $toPlace;
  121.     }
  122.     /**
  123.      * @internal Should not be called from outside the core
  124.      */
  125.     public function orderDeliveryStateTransition(
  126.         string $orderDeliveryId,
  127.         string $transition,
  128.         ParameterBag $data,
  129.         Context $context
  130.     ): StateMachineStateEntity {
  131.         $stateFieldName $data->get('stateFieldName''stateId');
  132.         $stateMachineStates $this->stateMachineRegistry->transition(
  133.             new Transition(
  134.                 'order_delivery',
  135.                 $orderDeliveryId,
  136.                 $transition,
  137.                 $stateFieldName
  138.             ),
  139.             $context
  140.         );
  141.         $toPlace $stateMachineStates->get('toPlace');
  142.         if (!$toPlace) {
  143.             throw new StateMachineStateNotFoundException('order_transaction'$transition);
  144.         }
  145.         return $toPlace;
  146.     }
  147.     public function isPaymentChangeableByTransactionState(OrderEntity $order): bool
  148.     {
  149.         if ($order->getTransactions() === null) {
  150.             return true;
  151.         }
  152.         $transaction $order->getTransactions()->last();
  153.         if ($transaction === null || $transaction->getStateMachineState() === null) {
  154.             return true;
  155.         }
  156.         $state $transaction->getStateMachineState()->getTechnicalName();
  157.         if (\in_array($stateself::ALLOWED_TRANSACTION_STATEStrue)) {
  158.             return true;
  159.         }
  160.         return false;
  161.     }
  162.     private function validateCart(Cart $cartContext $context): void
  163.     {
  164.         $idsOfPaymentMethods = [];
  165.         foreach ($cart->getTransactions() as $paymentMethod) {
  166.             $idsOfPaymentMethods[] = $paymentMethod->getPaymentMethodId();
  167.         }
  168.         $criteria = new Criteria();
  169.         $criteria->addFilter(
  170.             new EqualsFilter('active'true)
  171.         );
  172.         $paymentMethods $this->paymentMethodRepository->searchIds($criteria$context);
  173.         if ($paymentMethods->getTotal() !== \count(array_unique($idsOfPaymentMethods))) {
  174.             foreach ($cart->getTransactions() as $paymentMethod) {
  175.                 if (!\in_array($paymentMethod->getPaymentMethodId(), $paymentMethods->getIds(), true)) {
  176.                     throw new PaymentMethodNotAvailableException($paymentMethod->getPaymentMethodId());
  177.                 }
  178.             }
  179.         }
  180.     }
  181.     /**
  182.      * @throws ConstraintViolationException
  183.      */
  184.     private function validateOrderData(ParameterBag $dataSalesChannelContext $context): void
  185.     {
  186.         $definition $this->getOrderCreateValidationDefinition(new DataBag($data->all()), $context);
  187.         $violations $this->dataValidator->getViolations($data->all(), $definition);
  188.         if ($violations->count() > 0) {
  189.             throw new ConstraintViolationException($violations$data->all());
  190.         }
  191.     }
  192.     private function getOrderCreateValidationDefinition(DataBag $dataSalesChannelContext $context): DataValidationDefinition
  193.     {
  194.         $validation $this->orderValidationFactory->create($context);
  195.         $validationEvent = new BuildValidationEvent($validation$data$context->getContext());
  196.         $this->eventDispatcher->dispatch($validationEvent$validationEvent->getName());
  197.         return $validation;
  198.     }
  199. }