Completed
Pull Request — 4.0 (#4379)
by
unknown
04:37
created

StockReduceProcessor::commit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.ec-cube.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Service\PurchaseFlow\Processor;
15
16
use Doctrine\DBAL\LockMode;
17
use Doctrine\ORM\EntityManagerInterface;
18
use Eccube\Entity\ItemHolderInterface;
19
use Eccube\Entity\Order;
20
use Eccube\Entity\ProductStock;
21
use Eccube\Repository\ProductStockRepository;
22
use Eccube\Service\PurchaseFlow\ItemHolderValidator;
23
use Eccube\Service\PurchaseFlow\PurchaseContext;
24
use Eccube\Service\PurchaseFlow\PurchaseProcessor;
25
26
/**
27
 * 在庫制御.
28
 */
29
class StockReduceProcessor extends ItemHolderValidator implements PurchaseProcessor
30
{
31
    /**
32
     * @var ProductStockRepository
33
     */
34
    protected $productStockRepository;
35
36
    /**
37
     * @var EntityManagerInterface
38 196
     */
39
    protected $entityManager;
40 196
41
    /**
42
     * StockReduceProcessor constructor.
43
     *
44
     * @param ProductStockRepository $productStockRepository
45
     * @param EntityManagerInterface $entityManager
46
     */
47
    public function __construct(ProductStockRepository $productStockRepository, EntityManagerInterface $entityManager)
48
    {
49 8
        $this->productStockRepository = $productStockRepository;
50 4
        $this->entityManager = $entityManager;
51 8
    }
52
53
    /*
54
     * ItemHolderValidator
55
     */
56
57
    /**
58
     * {@inheritdoc}
59
     */
60 2
    protected function validate(ItemHolderInterface $itemHolder, PurchaseContext $context)
61 2
    {
62 2
        // 何もしない
63
    }
64
65 10
    /*
66
     * PurchaseProcessor
67
     */
68 10
69
    /**
70
     * {@inheritdoc}
71
     */
72 10
    public function prepare(ItemHolderInterface $itemHolder, PurchaseContext $context)
73
    {
74 10
        // 在庫を減らす
75
        $this->eachProductOrderItems($itemHolder, function ($currentStock, $itemQuantity) {
76
            return $currentStock - $itemQuantity;
77
        });
78 6
    }
79 6
80
    /**
81
     * {@inheritdoc}
82 6
     */
83 6
    public function commit(ItemHolderInterface $target, PurchaseContext $context)
84 10
    {
85
        // 何もしない
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function rollback(ItemHolderInterface $itemHolder, PurchaseContext $context)
92
    {
93
        // 在庫を戻す
94
        $this->eachProductOrderItems($itemHolder, function ($currentStock, $itemQuantity) {
95
            return $currentStock + $itemQuantity;
96
        });
97
    }
98
99
    private function eachProductOrderItems(ItemHolderInterface $itemHolder, callable $callback)
100
    {
101
        // Order以外の場合は何もしない
102
        if (!$itemHolder instanceof Order) {
103
            return;
104
        }
105
106
        foreach ($itemHolder->getProductOrderItems() as $item) {
107
            // 在庫が無制限かチェックし、制限ありなら在庫数をチェック
108
            if (!$item->getProductClass()->isStockUnlimited()) {
109
                // 在庫チェックあり
110
                /* @var ProductStock $productStock */
111
                $productStock = $item->getProductClass()->getProductStock();
112
                // 在庫に対してロックを実行
113
                $this->entityManager->lock($productStock, LockMode::PESSIMISTIC_WRITE);
114
                $this->entityManager->refresh($productStock);
115
                $ProductClass = $item->getProductClass();
116
                $stock = $callback($productStock->getStock(), $item->getQuantity());
117
                if ($stock < 0) {
118
                    $this->throwInvalidItemException(trans('purchase_flow.over_stock', ['%name%' => $ProductClass->formattedProductName()]));
119
                }
120
                $productStock->setStock($stock);
121
                $ProductClass->setStock($stock);
122
            }
123
        }
124
    }
125
}
126