<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
*
* http://www.ec-cube.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Customize\Service;
use Customize\Entity\Estimate;
use Customize\Entity\Master\EstimateStatus;
use Customize\Repository\Master\EstimateStatusRepository;
use Eccube\Service\PurchaseFlow\Processor\PointProcessor;
use Eccube\Service\PurchaseFlow\Processor\StockReduceProcessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\Event;
use Symfony\Component\Workflow\StateMachine;
class EstimateStateMachine implements EventSubscriberInterface
{
/**
* @var StateMachine
*/
private $machine;
/**
* @var EstimateStatusRepository
*/
private $estimateStatusRepository;
/**
* @var PointProcessor
*/
private $pointProcessor;
/**
* @var StockReduceProcessor
*/
private $stockReduceProcessor;
public function __construct(StateMachine $_estimateStateMachine, EstimateStatusRepository $estimateStatusRepository, PointProcessor $pointProcessor, StockReduceProcessor $stockReduceProcessor)
{
$this->machine = $_estimateStateMachine;
$this->estimateStatusRepository = $estimateStatusRepository;
$this->pointProcessor = $pointProcessor;
$this->stockReduceProcessor = $stockReduceProcessor;
}
/**
* 指定ステータスに遷移.
*
* @param Estimate $Estimate 受注
* @param EstimateStatus $EstimateStatus 遷移先ステータス
*/
public function apply(Estimate $Estimate, EstimateStatus $EstimateStatus)
{
$context = $this->newContext($Estimate);
$transition = $this->getTransition($context, $EstimateStatus);
if ($transition) {
$this->machine->apply($context, $transition->getName());
} else {
throw new \InvalidArgumentException();
}
}
/**
* 指定ステータスに遷移できるかどうかを判定.
*
* @param Estimate $Estimate 受注
* @param EstimateStatus $EstimateStatus 遷移先ステータス
*
* @return boolean 指定ステータスに遷移できる場合はtrue
*/
public function can(Estimate $Estimate, EstimateStatus $EstimateStatus)
{
return !is_null($this->getTransition($this->newContext($Estimate), $EstimateStatus));
}
private function getTransition(EstimateStateMachineContext $context, EstimateStatus $EstimateStatus)
{
$transitions = $this->machine->getEnabledTransitions($context);
foreach ($transitions as $t) {
if (in_array($EstimateStatus->getId(), $t->getTos())) {
return $t;
}
}
return null;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
'workflow.estimate.completed' => ['onCompleted'],
'workflow.estimate.transition.return_fixed' => ['returnFixed'],
'workflow.estimate.transition.return_new' => ['returnNewAndInProgress'],
'workflow.estimate.transition.return_in_progress' => ['returnNewAndInProgress'],
// 'workflow.estimate.transition.in_progress' => [],
// 'workflow.estimate.transition.approval_pending' => [],
// 'workflow.estimate.transition.fixed' => [],
// 'workflow.estimate.transition.ordered' => [],
// 'workflow.estimate.transition.cancel' => [],
];
}
/*
* Event handlers.
*/
// @TODO ここにイベント処理を記述する。このファイルを参照 `app/Customize/Service/OrderStateMachine.php`
/**
* 見積ステータスを再設定.
* {@link StateMachine}によって遷移が終了したときには{@link Estimate#EstimateStatus}のidが変更されるだけなのでEstimateStatusを設定し直す.
*
* @param Event $event
*/
public function onCompleted(Event $event)
{
/** @var $context EstimateStateMachineContext */
$context = $event->getSubject();
$Estimate = $context->getEstimate();
$CompletedEstimateStatus = $this->estimateStatusRepository->find($context->getStatus());
$Estimate->setEstimateStatus($CompletedEstimateStatus);
}
/**
* 見積確定から見積対応中へステータスの変更があった場合、Estimateのデータを更新する
*
* @param Event $event
*/
public function returnFixed(Event $event)
{
/** @var $context EstimateStateMachineContext */
$context = $event->getSubject();
$Estimate = $context->getEstimate();
$Estimate->setDesignConfirmFlg(0);
$Estimate->setEstimateFix(0);
$this->returnNewAndInProgress($event);
}
/**
* 見積対応中以前のステップへステータスが戻った場合、
* EstimateShipping.shipping_method_select_conditions(配送方法の選択条件)を更新する
*
* @param Event $event
*/
public function returnNewAndInProgress(Event $event)
{
/** @var $context EstimateStateMachineContext */
$context = $event->getSubject();
$Estimate = $context->getEstimate();
$EstimateShipping = $Estimate->getShippings()[0];
if ( $EstimateShipping ) {
$EstimateShipping->setShippingMethodSelectConditions(null);
}
}
private function newContext(Estimate $Estimate)
{
return new EstimateStateMachineContext((string) $Estimate->getEstimateStatus()->getId(), $Estimate);
}
}
class EstimateStateMachineContext
{
/** @var string */
private $status;
/** @var Estimate */
private $Estimate;
/**
* OrderStateMachineContext constructor.
*
* @param string $status
* @param Estimate $Estimate
*/
public function __construct($status, Estimate $Estimate)
{
$this->status = $status;
$this->Estimate = $Estimate;
}
/**
* @return string
*/
public function getStatus()
{
return $this->status;
}
/**
* @param string $status
*/
public function setStatus($status)
{
$this->status = $status;
}
/**
* @return Estimate
*/
public function getEstimate()
{
return $this->Estimate;
}
// estimate_state_machine.php の marking_store => property は、デフォルト値である marking を使用するよう強く推奨されている.
// EC-CUBE4.1 までは status を指定していたが、 Symfony5 よりエラーになるためエイリアスを作成して対応する.
/**
* Alias of getStatus()
*/
public function getMarking(): string
{
return $this->getStatus();
}
/**
* Alias of setStatus()
*/
public function setMarking(string $status): void
{
$this->setStatus($status);
}
}