Skip to content

Commit

Permalink
Merge pull request #3402 from kiy0taka/sf/fix-order-state-machine
Browse files Browse the repository at this point in the history
OrderStatusMachineでOrderStatusのidが変更される問題の対応
  • Loading branch information
Chihiro Adachi committed Jul 26, 2018
2 parents 2931dcc + 38ceb65 commit 048f3e7
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 37 deletions.
6 changes: 3 additions & 3 deletions app/config/eccube/packages/order_state_machine.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@
* file that was distributed with this source code.
*/

use Eccube\Entity\Order;
use Eccube\Entity\Master\OrderStatus as Status;
use Eccube\Service\OrderStateMachineContext;

$container->loadFromExtension('framework', [
'workflows' => [
'order' => [
'type' => 'state_machine',
'marking_store' => [
'type' => 'single_state',
'arguments' => 'OrderStatus.id',
'arguments' => 'status',
],
'supports' => [
Order::class,
OrderStateMachineContext::class,
],
'initial_place' => (string) Status::NEW,
'places' => [
Expand Down
2 changes: 0 additions & 2 deletions src/Eccube/Controller/Admin/Order/CsvImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@ protected function loadCsv(CsvImportService $csv, &$errors)
}
$OrderStatus = $this->entityManager->find(OrderStatus::class, OrderStatus::DELIVERED);
if ($allShipped) {
// XXX 先行の行で OrderStateMachine が OrderStatus::id を変更している場合があるので refresh する
$this->entityManager->refresh($Order);
if ($this->orderStateMachine->can($Order, $OrderStatus)) {
$this->orderStateMachine->apply($Order, $OrderStatus);
} else {
Expand Down
3 changes: 0 additions & 3 deletions src/Eccube/Controller/Admin/Order/EditController.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,6 @@ public function index(Request $request, $id = null)
$TargetOrder->setOrderStatus($OldStatus);
// FormTypeでステータスの遷移チェックは行っているのでapplyのみ実行.
$this->orderStateMachine->apply($TargetOrder, $NewStatus);
// FIXME ステートマシンがmtb_order_statusを更新しようとするので, refreshしておく.
$this->entityManager->refresh($OldStatus);
$this->entityManager->refresh($NewStatus);
}

$this->entityManager->persist($TargetOrder);
Expand Down
97 changes: 68 additions & 29 deletions src/Eccube/Service/OrderStateMachine.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

namespace Eccube\Service;

use Doctrine\ORM\EntityManagerInterface;
use Eccube\Entity\Master\OrderStatus;
use Eccube\Entity\Order;
use Eccube\Repository\Master\OrderStatusRepository;
Expand Down Expand Up @@ -45,18 +44,12 @@ class OrderStateMachine implements EventSubscriberInterface
*/
private $stockReduceProcessor;

/**
* @var EntityManagerInterface
*/
private $entityManager;

public function __construct(StateMachine $_orderStateMachine, OrderStatusRepository $orderStatusRepository, PointProcessor $pointProcessor, StockReduceProcessor $stockReduceProcessor, EntityManagerInterface $entityManager)
public function __construct(StateMachine $_orderStateMachine, OrderStatusRepository $orderStatusRepository, PointProcessor $pointProcessor, StockReduceProcessor $stockReduceProcessor)
{
$this->machine = $_orderStateMachine;
$this->orderStatusRepository = $orderStatusRepository;
$this->pointProcessor = $pointProcessor;
$this->stockReduceProcessor = $stockReduceProcessor;
$this->entityManager = $entityManager;
}

/**
Expand All @@ -67,9 +60,10 @@ public function __construct(StateMachine $_orderStateMachine, OrderStatusReposit
*/
public function apply(Order $Order, OrderStatus $OrderStatus)
{
$transition = $this->getTransition($Order, $OrderStatus);
$context = $this->newContext($Order);
$transition = $this->getTransition($context, $OrderStatus);
if ($transition) {
$this->machine->apply($Order, $transition->getName());
$this->machine->apply($context, $transition->getName());
} else {
throw new \InvalidArgumentException();
}
Expand All @@ -85,12 +79,12 @@ public function apply(Order $Order, OrderStatus $OrderStatus)
*/
public function can(Order $Order, OrderStatus $OrderStatus)
{
return !is_null($this->getTransition($Order, $OrderStatus));
return !is_null($this->getTransition($this->newContext($Order), $OrderStatus));
}

private function getTransition(Order $Order, OrderStatus $OrderStatus)
private function getTransition(OrderStateMachineContext $context, OrderStatus $OrderStatus)
{
$transitions = $this->machine->getEnabledTransitions($Order);
$transitions = $this->machine->getEnabledTransitions($context);
foreach ($transitions as $t) {
if (in_array($OrderStatus->getId(), $t->getTos())) {
return $t;
Expand Down Expand Up @@ -128,7 +122,7 @@ public static function getSubscribedEvents()
public function updatePaymentDate(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
$Order->setPaymentDate(new \DateTime());
}

Expand All @@ -141,7 +135,7 @@ public function updateShippingDate(Event $event)
{
// TODO: 出荷に出荷日を入れる処理は出荷ごとに実行される可能性があるのでステートマシン外で処理する必要がある
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
foreach ($Order->getShippings() as $Shipping) {
if (!$Shipping->getShippingDate()) {
$Shipping->setShippingDate(new \DateTime());
Expand All @@ -159,7 +153,7 @@ public function updateShippingDate(Event $event)
public function commitUsePoint(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
$this->pointProcessor->prepare($Order, new PurchaseContext());
}

Expand All @@ -171,7 +165,7 @@ public function commitUsePoint(Event $event)
public function rollbackUsePoint(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
$this->pointProcessor->rollback($Order, new PurchaseContext());
}

Expand All @@ -185,7 +179,7 @@ public function rollbackUsePoint(Event $event)
public function commitStock(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
$this->stockReduceProcessor->prepare($Order, new PurchaseContext());
}

Expand All @@ -197,7 +191,7 @@ public function commitStock(Event $event)
public function rollbackStock(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
$this->stockReduceProcessor->rollback($Order, new PurchaseContext());
}

Expand All @@ -209,7 +203,7 @@ public function rollbackStock(Event $event)
public function commitAddPoint(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
$Customer = $Order->getCustomer();
if ($Customer) {
$Customer->setPoint(intval($Customer->getPoint()) + intval($Order->getAddPoint()));
Expand All @@ -224,7 +218,7 @@ public function commitAddPoint(Event $event)
public function rollbackAddPoint(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject();
$Order = $event->getSubject()->getOrder();
$Customer = $Order->getCustomer();
if ($Customer) {
$Customer->setPoint(intval($Customer->getPoint()) - intval($Order->getAddPoint()));
Expand All @@ -239,15 +233,60 @@ public function rollbackAddPoint(Event $event)
*/
public function onCompleted(Event $event)
{
/** @var Order $Order */
$Order = $event->getSubject();
$OrderStatusId = $Order->getOrderStatus()->getId();
/** @var $context OrderStateMachineContext */
$context = $event->getSubject();
$Order = $context->getOrder();
$CompletedOrderStatus = $this->orderStatusRepository->find($context->getStatus());
$Order->setOrderStatus($CompletedOrderStatus);
}

private function newContext(Order $Order)
{
return new OrderStateMachineContext((string) $Order->getOrderStatus()->getId(), $Order);
}
}

class OrderStateMachineContext
{
/** @var string */
private $status;

// XXX このまま EntityManager::flush() をコールすると、 OrderStatus::id が更新されてしまうため元に戻す
$TransitionlStatus = $Order->getOrderStatus();
$this->entityManager->refresh($TransitionlStatus);
/** @var Order */
private $Order;

$CompletedOrderStatus = $this->orderStatusRepository->find($OrderStatusId);
$Order->setOrderStatus($CompletedOrderStatus);
/**
* OrderStateMachineContext constructor.
*
* @param string $status
* @param Order $Order
*/
public function __construct($status, Order $Order)
{
$this->status = $status;
$this->Order = $Order;
}

/**
* @return string
*/
public function getStatus()
{
return $this->status;
}

/**
* @param string $status
*/
public function setStatus($status)
{
$this->status = $status;
}

/**
* @return Order
*/
public function getOrder()
{
return $this->Order;
}
}

0 comments on commit 048f3e7

Please sign in to comment.