app/Customize/Service/OrderStateMachine.php line 165

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