src/Eccube/Service/OrderStateMachine.php line 169

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\Service;
  13. use Customize\Repository\OrderRepository;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use Eccube\Entity\Master\OrderStatus;
  16. use Eccube\Entity\Order;
  17. use Eccube\Repository\Master\OrderStatusRepository;
  18. use Eccube\Service\PurchaseFlow\Processor\PointProcessor;
  19. use Eccube\Service\PurchaseFlow\Processor\PointwbikeProcessor;
  20. use Eccube\Service\PurchaseFlow\Processor\StockReduceProcessor;
  21. use Eccube\Service\PurchaseFlow\PurchaseContext;
  22. use Plugin\EccubePaymentLite42\Entity\PaymentStatus;
  23. use Plugin\EccubePaymentLite42\Repository\PaymentStatusRepository;
  24. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  25. use Symfony\Component\Workflow\Event\Event;
  26. use Symfony\Component\Workflow\StateMachine;
  27. class OrderStateMachine implements EventSubscriberInterface
  28. {
  29.     /**
  30.      * @var StateMachine
  31.      */
  32.     private $machine;
  33.     /**
  34.      * @var OrderStatusRepository
  35.      */
  36.     private $orderStatusRepository;
  37.     /**
  38.      * @var PointProcessor
  39.      */
  40.     private $pointProcessor;
  41.     private $pointwbikeProcessor;
  42.     /**
  43.      * @var StockReduceProcessor
  44.      */
  45.     private $stockReduceProcessor;
  46.     private $orderRepository;
  47.     private $entityManager;
  48.     private $paymentStatusRepository;
  49.     
  50.     public function __construct(StateMachine $_orderStateMachineOrderStatusRepository $orderStatusRepositoryPointProcessor $pointProcessorPointwbikeProcessor $pointwbikeProcessorStockReduceProcessor $stockReduceProcessorOrderRepository $orderRepositoryEntityManagerInterface $entityManagerPaymentStatusRepository $paymentStatusRepository)
  51.     {
  52.         $this->machine $_orderStateMachine;
  53.         $this->orderStatusRepository $orderStatusRepository;
  54.         $this->pointProcessor $pointProcessor;
  55.         $this->pointwbikeProcessor $pointwbikeProcessor;
  56.         $this->stockReduceProcessor $stockReduceProcessor;
  57.         $this->orderRepository $orderRepository;
  58.         $this->entityManager $entityManager;
  59.         $this->paymentStatusRepository $paymentStatusRepository;
  60.     }
  61.     /**
  62.      * 指定ステータスに遷移.
  63.      *
  64.      * @param Order $Order 受注
  65.      * @param OrderStatus $OrderStatus 遷移先ステータス
  66.      */
  67.     public function apply(Order $OrderOrderStatus $OrderStatus)
  68.     {
  69.         $context $this->newContext($Order);
  70.         $transition $this->getTransition($context$OrderStatus);
  71.         if ($transition) {
  72.             $this->machine->apply($context$transition->getName());
  73.         } else {
  74.             throw new \InvalidArgumentException();
  75.         }
  76.     }
  77.     /**
  78.      * 指定ステータスに遷移できるかどうかを判定.
  79.      *
  80.      * @param Order $Order 受注
  81.      * @param OrderStatus $OrderStatus 遷移先ステータス
  82.      *
  83.      * @return boolean 指定ステータスに遷移できる場合はtrue
  84.      */
  85.     public function can(Order $OrderOrderStatus $OrderStatus)
  86.     {
  87.         return !is_null($this->getTransition($this->newContext($Order), $OrderStatus));
  88.     }
  89.     private function getTransition(OrderStateMachineContext $contextOrderStatus $OrderStatus)
  90.     {
  91.         $transitions $this->machine->getEnabledTransitions($context);
  92.         foreach ($transitions as $t) {
  93.             if (in_array($OrderStatus->getId(), $t->getTos())) {
  94.                 return $t;
  95.             }
  96.         }
  97.         return null;
  98.     }
  99.     /**
  100.      * {@inheritdoc}
  101.      */
  102.     public static function getSubscribedEvents()
  103.     {
  104.         return [
  105.             'workflow.order.completed' => ['onCompleted'],
  106.             'workflow.order.transition.pay' => ['updatePaymentDate'],
  107.             'workflow.order.transition.cancel' => [['rollbackStock'], ['rollbackUsePoint'], ['rollbackUsePointwbike'], ['cancelChildrenOrders']],
  108.             'workflow.order.transition.back_to_in_progress' => [['commitStock'], ['commitUsePoint']],
  109.             'workflow.order.transition.ship' => [['commitAddPoint']],
  110.             'workflow.order.transition.return' => [['rollbackUsePoint'], ['rollbackUsePointwbike'], ['rollbackAddPoint']],
  111.             'workflow.order.transition.cancel_return' => [['commitUsePoint'], ['commitUsePointwbike'], ['commitAddPoint']],
  112.         ];
  113.     }
  114.     /*
  115.      * Event handlers.
  116.      */
  117.     /**
  118.      * 入金日を更新する.
  119.      *
  120.      * @param Event $event
  121.      */
  122.     public function updatePaymentDate(Event $event)
  123.     {
  124.         /* @var Order $Order */
  125.         $Order $event->getSubject()->getOrder();
  126.         $Order->setPaymentDate(new \DateTime());
  127.     }
  128.     public function cancelChildrenOrders(Event $event)
  129.     {
  130.         // do NOTHING bc OrderStatusChangeNotifier::postUpdate
  131.     }
  132.     /**
  133.      * 会員の保有ポイントを減らす.
  134.      *
  135.      * @param Event $event
  136.      *
  137.      * @throws PurchaseFlow\PurchaseException
  138.      */
  139.     public function commitUsePoint(Event $event)
  140.     {
  141.         /* @var Order $Order */
  142.         $Order $event->getSubject()->getOrder();
  143.         $this->pointProcessor->prepare($Order, new PurchaseContext());
  144.     }
  145.         /**
  146.      * 会員の保有ポイントを減らす.
  147.      *
  148.      * @param Event $event
  149.      *
  150.      * @throws PurchaseFlow\PurchaseException
  151.      */
  152.     public function commitUsePointwbike(Event $event)
  153.     {
  154.         /* @var Order $Order */
  155.         $Order $event->getSubject()->getOrder();
  156.         $this->pointwbikeProcessor->prepare($Order, new PurchaseContext());
  157.     }
  158.     /**
  159.      * 利用ポイントを会員に戻す.
  160.      *
  161.      * @param Event $event
  162.      */
  163.     public function rollbackUsePoint(Event $event)
  164.     {
  165.         /* @var Order $Order */
  166.         $Order $event->getSubject()->getOrder();
  167.         $this->pointProcessor->rollback($Order, new PurchaseContext());
  168.     }
  169.         /**
  170.      * 利用ポイントを会員に戻す.
  171.      *
  172.      * @param Event $event
  173.      */
  174.     public function rollbackUsePointwbike(Event $event)
  175.     {
  176.         /* @var Order $Order */
  177.         $Order $event->getSubject()->getOrder();
  178.         $this->pointwbikeProcessor->rollback($Order, new PurchaseContext());
  179.     }
  180.     /**
  181.      * 在庫を減らす.
  182.      *
  183.      * @param Event $event
  184.      *
  185.      * @throws PurchaseFlow\PurchaseException
  186.      */
  187.     public function commitStock(Event $event)
  188.     {
  189.         /* @var Order $Order */
  190.         $Order $event->getSubject()->getOrder();
  191.         $this->stockReduceProcessor->prepare($Order, new PurchaseContext());
  192.     }
  193.     /**
  194.      * 在庫を戻す.
  195.      *
  196.      * @param Event $event
  197.      */
  198.     public function rollbackStock(Event $event)
  199.     {
  200.         /* @var Order $Order */
  201.         $Order $event->getSubject()->getOrder();
  202.         $this->stockReduceProcessor->rollback($Order, new PurchaseContext());
  203.     }
  204.     /**
  205.      * 会員に加算ポイントを付与する.
  206.      *
  207.      * @param Event $event
  208.      */
  209.     public function commitAddPoint(Event $event)
  210.     {
  211.         /* @var Order $Order */
  212.         $Order $event->getSubject()->getOrder();
  213.         $Customer $Order->getCustomer();
  214.         if ($Customer) {
  215.             $Customer->setPoint(($Customer->getPoint()) + ($Order->getAddPoint()));
  216.         }
  217.     }
  218.     /**
  219.      * 会員に付与した加算ポイントを取り消す.
  220.      *
  221.      * @param Event $event
  222.      */
  223.     public function rollbackAddPoint(Event $event)
  224.     {
  225.         /* @var Order $Order */
  226.         $Order $event->getSubject()->getOrder();
  227.         $Customer $Order->getCustomer();
  228.         if ($Customer) {
  229.             $Customer->setPoint(($Customer->getPoint()) - ($Order->getAddPoint()));
  230.         }
  231.     }
  232.     /**
  233.      * 受注ステータスを再設定.
  234.      * {@link StateMachine}によって遷移が終了したときには{@link Order#OrderStatus}のidが変更されるだけなのでOrderStatusを設定し直す.
  235.      *
  236.      * @param Event $event
  237.      */
  238.     public function onCompleted(Event $event)
  239.     {
  240.         /** @var $context OrderStateMachineContext */
  241.         $context $event->getSubject();
  242.         $Order $context->getOrder();
  243.         $CompletedOrderStatus $this->orderStatusRepository->find($context->getStatus());
  244.         $Order->setOrderStatus($CompletedOrderStatus);
  245.     }
  246.     private function newContext(Order $Order)
  247.     {
  248.         return new OrderStateMachineContext((string) $Order->getOrderStatus()->getId(), $Order);
  249.     }
  250. }
  251. class OrderStateMachineContext
  252. {
  253.     /** @var string */
  254.     private $status;
  255.     /** @var Order */
  256.     private $Order;
  257.     /**
  258.      * OrderStateMachineContext constructor.
  259.      *
  260.      * @param string $status
  261.      * @param Order $Order
  262.      */
  263.     public function __construct($statusOrder $Order)
  264.     {
  265.         $this->status $status;
  266.         $this->Order $Order;
  267.     }
  268.     /**
  269.      * @return string
  270.      */
  271.     public function getStatus()
  272.     {
  273.         return $this->status;
  274.     }
  275.     /**
  276.      * @param string $status
  277.      */
  278.     public function setStatus($status)
  279.     {
  280.         $this->status $status;
  281.     }
  282.     /**
  283.      * @return Order
  284.      */
  285.     public function getOrder()
  286.     {
  287.         return $this->Order;
  288.     }
  289.     // order_state_machine.php の marking_store => property は、デフォルト値である marking を使用するよう強く推奨されている.
  290.     // EC-CUBE4.1 までは status を指定していたが、 Symfony5 よりエラーになるためエイリアスを作成して対応する.
  291.     /**
  292.      * Alias of getStatus()
  293.      */
  294.     public function getMarking(): string
  295.     {
  296.         return $this->getStatus();
  297.     }
  298.     /**
  299.      * Alias of setStatus()
  300.      */
  301.     public function setMarking(string $status): void
  302.     {
  303.         $this->setStatus($status);
  304.     }
  305. }