Completed
Pull Request — experimental/sf (#3420)
by chihiro
244:13 queued 235:15
created

OrderHelper::createPreOrderId()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 16

Duplication

Lines 10
Ratio 62.5 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 1
nop 0
dl 10
loc 16
rs 9.7333
c 0
b 0
f 0
ccs 6
cts 6
cp 1
crap 2
1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.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;
15
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Doctrine\ORM\EntityManager;
18
use Doctrine\ORM\EntityManagerInterface;
19
use Eccube\Common\EccubeConfig;
20
use Eccube\Entity\Cart;
21
use Eccube\Entity\CartItem;
22
use Eccube\Entity\Customer;
23
use Eccube\Entity\Master\DeviceType;
24
use Eccube\Entity\Master\OrderItemType;
25
use Eccube\Entity\Master\OrderStatus;
26
use Eccube\Entity\Order;
27
use Eccube\Entity\OrderItem;
28
use Eccube\Entity\Shipping;
29
use Eccube\Repository\DeliveryFeeRepository;
30
use Eccube\Repository\DeliveryRepository;
31
use Eccube\Repository\Master\OrderItemTypeRepository;
32
use Eccube\Repository\Master\OrderStatusRepository;
33
use Eccube\Repository\OrderRepository;
34
use Eccube\Repository\PaymentRepository;
35
use Eccube\Repository\TaxRuleRepository;
36
use Eccube\Util\StringUtil;
37
use Eccube\Repository\Master\DeviceTypeRepository;
38
39
/**
40
 * OrderやOrderに関連するエンティティを構築するクラス
41
 * namespaceやクラス名は要検討
42
 */
43
class OrderHelper
44
{
45
    /**
46
     * @var OrderItemTypeRepository
47
     */
48
    protected $orderItemTypeRepository;
49
50
    /**
51
     * @var OrderStatusRepository
52
     */
53
    protected $orderStatusRepository;
54
55
    /**
56
     * @var TaxRuleRepository
57
     */
58
    protected $taxRuleRepository;
59
60
    /**
61
     * @var DeliveryFeeRepository
62
     */
63
    protected $deliveryFeeRepository;
64
65
    /**
66
     * @var DeliveryRepository
67
     */
68
    protected $deliveryRepository;
69
70
    /**
71
     * @var PaymentRepository
72
     */
73
    protected $paymentRepository;
74
75
    /**
76
     * @var OrderRepository
77
     */
78
    protected $orderRepository;
79
80
    /**
81
     * @var EntityManager
82
     */
83
    protected $entityManager;
84
85
    /**
86
     * @var EccubeConfig
87
     */
88
    protected $eccubeConfig;
89
90
    /**
91
     * @var \Mobile_Detect
92
     */
93
    protected $mobileDetect;
94
95
    /**
96
     * @var DeviceTypeRepository
97
     */
98
    protected $deviceTypeRepository;
99
100
    /**
101
     * OrderHelper constructor.
102
     *
103
     * @param OrderItemTypeRepository $orderItemTypeRepository
104
     * @param OrderStatusRepository $orderStatusRepository
0 ignored issues
show
introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
105
     * @param TaxRuleRepository $taxRuleRepository
0 ignored issues
show
introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
106
     * @param DeliveryFeeRepository $deliveryFeeRepository
0 ignored issues
show
introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
107
     * @param DeliveryRepository $deliveryRepository
0 ignored issues
show
introduced by
Expected 6 spaces after parameter type; 1 found
Loading history...
108
     * @param PaymentRepository $paymentRepository
0 ignored issues
show
introduced by
Expected 7 spaces after parameter type; 1 found
Loading history...
109
     * @param OrderRepository $orderRepository
0 ignored issues
show
introduced by
Expected 9 spaces after parameter type; 1 found
Loading history...
110
     * @param EntityManager $entityManager
0 ignored issues
show
introduced by
Expected 11 spaces after parameter type; 1 found
Loading history...
111
     * @param EccubeConfig $eccubeConfig
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
112
     * @param \Mobile_Detect $mobileDetect
0 ignored issues
show
introduced by
Expected 10 spaces after parameter type; 1 found
Loading history...
113
     * @param DeviceTypeRepository $deviceTypeRepository
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
114
     */
115 175
    public function __construct(
116
        OrderItemTypeRepository $orderItemTypeRepository,
117
        OrderStatusRepository $orderStatusRepository,
118
        TaxRuleRepository $taxRuleRepository,
119
        DeliveryFeeRepository $deliveryFeeRepository,
120
        DeliveryRepository $deliveryRepository,
121
        PaymentRepository $paymentRepository,
122
        OrderRepository $orderRepository,
123
        EntityManagerInterface $entityManager,
124
        EccubeConfig $eccubeConfig,
125
        \Mobile_Detect $mobileDetect,
126
        DeviceTypeRepository $deviceTypeRepository
127
    ) {
128 175
        $this->orderItemTypeRepository = $orderItemTypeRepository;
129 175
        $this->orderStatusRepository = $orderStatusRepository;
130 175
        $this->taxRuleRepository = $taxRuleRepository;
131 175
        $this->deliveryFeeRepository = $deliveryFeeRepository;
132 175
        $this->deliveryRepository = $deliveryRepository;
133 175
        $this->paymentRepository = $paymentRepository;
134 175
        $this->orderRepository = $orderRepository;
135 175
        $this->entityManager = $entityManager;
0 ignored issues
show
Documentation Bug introduced by
$entityManager is of type object<Doctrine\ORM\EntityManagerInterface>, but the property $entityManager was declared to be of type object<Doctrine\ORM\EntityManager>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
136 175
        $this->eccubeConfig = $eccubeConfig;
137 175
        $this->mobileDetect = $mobileDetect;
138 175
        $this->deviceTypeRepository = $deviceTypeRepository;
139
    }
140
141
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$preOrderId" missing
Loading history...
142
     * 購入処理中の受注データを生成する.
143
     *
144
     * @param Customer $Customer
145
     * @param array $CartItems
0 ignored issues
show
introduced by
Expected 4 spaces after parameter type; 1 found
Loading history...
146
     *
147
     * @return Order
148
     */
149 51
    public function createProcessingOrder(Customer $Customer, $CartItems, $preOrderId = null)
150
    {
151 51
        $OrderStatus = $this->orderStatusRepository->find(OrderStatus::PROCESSING);
152 51
        $Order = new Order($OrderStatus);
153
154 51
        if (!$preOrderId) {
155
            // pre_order_idを生成
156 51
            $Order->setPreOrderId($this->createPreOrderId());
157
        }
158
159
        // 顧客情報の設定
160 51
        $this->setCustomer($Order, $Customer);
161
162 51
        $DeviceType = $this->deviceTypeRepository->find($this->mobileDetect->isMobile() ? DeviceType::DEVICE_TYPE_SP : DeviceType::DEVICE_TYPE_PC);
163 51
        $Order->setDeviceType($DeviceType);
164
165
        // 明細情報の設定
166 51
        $OrderItems = $this->createOrderItemsFromCartItems($CartItems);
0 ignored issues
show
Documentation introduced by
$CartItems is of type array, but the function expects a object<Doctrine\Common\C...ctions\ArrayCollection>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
167 51
        $OrderItemsGroupBySaleType = array_reduce($OrderItems, function ($result, $item) {
168
            /* @var OrderItem $item */
169 51
            $saleTypeId = $item->getProductClass()->getSaleType()->getId();
170 51
            $result[$saleTypeId][] = $item;
171
172 51
            return $result;
173 51
        }, []);
174
175 51
        foreach ($OrderItemsGroupBySaleType as $OrderItems) {
176 51
            $Shipping = $this->createShippingFromCustomer($Customer);
177 51
            $Shipping->setOrder($Order);
178 51
            $this->addOrderItems($Order, $Shipping, $OrderItems);
179 51
            $this->setDefaultDelivery($Shipping);
180 51
            $this->entityManager->persist($Shipping);
181 51
            $Order->addShipping($Shipping);
182
        }
183
184 51
        $this->setDefaultPayment($Order);
185
186 51
        $this->entityManager->persist($Order);
187
        //$this->entityManager->flush();
188
189 51
        return $Order;
190
    }
191
192
    /**
193
     * OrderをCartに変換します.
194
     *
195
     * @param Order $Order
196
     *
197
     * @return Cart
198
     */
199 2
    public function convertToCart(Order $Order)
200
    {
201 2
        $Cart = new Cart();
202 2
        $Cart->setPreOrderId($Order->getPreOrderId());
203
        /** @var OrderItem $OrderItem */
204 2
        foreach ($Order->getProductOrderItems() as $OrderItem) {
205 1
            $CartItem = new CartItem();
206 1
            $ProductClass = $OrderItem->getProductClass();
207 1
            $this->entityManager->refresh($ProductClass);
208 1
            $CartItem->setProductClass($ProductClass);
209 1
            $CartItem->setPrice($OrderItem->getPriceIncTax());
210 1
            $CartItem->setQuantity($OrderItem->getQuantity());
211 1
            $Cart->addCartItem($CartItem);
212
        }
213
214 2
        return $Cart;
215
    }
216
217 51
    private function createPreOrderId()
218
    {
219
        // ランダムなpre_order_idを作成
220 View Code Duplication
        do {
221 51
            $preOrderId = sha1(StringUtil::random(32));
222
223 51
            $Order = $this->orderRepository->findOneBy(
224
                [
225 51
                    'pre_order_id' => $preOrderId,
226
                    'OrderStatus' => OrderStatus::PROCESSING,
227
                ]
228
            );
229 51
        } while ($Order);
230
231 51
        return $preOrderId;
232
    }
233
234 51
    private function setCustomer(Order $Order, Customer $Customer)
235
    {
236 51
        if ($Customer->getId()) {
237 34
            $Order->setCustomer($Customer);
238
        }
239
240 51
        $Order->copyProperties(
241 51
            $Customer,
242
            [
243 51
                'id',
244
                'create_date',
245
                'update_date',
246
                'del_flg',
247
            ]
248
        );
249
    }
250
251
    /**
252
     * @param ArrayCollection $CartItems
253
     *
254
     * @return OrderItem[]
255
     */
256 51
    private function createOrderItemsFromCartItems($CartItems)
257
    {
258 51
        $ProductItemType = $this->orderItemTypeRepository->find(OrderItemType::PRODUCT);
259
260 51
        return array_map(function ($item) use ($ProductItemType) {
261
            /* @var $item CartItem */
262
            /* @var $ProductClass \Eccube\Entity\ProductClass */
263 51
            $ProductClass = $item->getProductClass();
264
            /* @var $Product \Eccube\Entity\Product */
265 51
            $Product = $ProductClass->getProduct();
266
267 51
            $OrderItem = new OrderItem();
268
            $OrderItem
269 51
                ->setProduct($Product)
270 51
                ->setProductClass($ProductClass)
271 51
                ->setProductName($Product->getName())
272 51
                ->setProductCode($ProductClass->getCode())
273 51
                ->setPrice($ProductClass->getPrice02())
274 51
                ->setQuantity($item->getQuantity())
275 51
                ->setOrderItemType($ProductItemType);
276
277 51
            $ClassCategory1 = $ProductClass->getClassCategory1();
278 51
            if (!is_null($ClassCategory1)) {
279 51
                $OrderItem->setClasscategoryName1($ClassCategory1->getName());
280 51
                $OrderItem->setClassName1($ClassCategory1->getClassName()->getName());
281
            }
282 51
            $ClassCategory2 = $ProductClass->getClassCategory2();
283 51
            if (!is_null($ClassCategory2)) {
284 43
                $OrderItem->setClasscategoryName2($ClassCategory2->getName());
285 43
                $OrderItem->setClassName2($ClassCategory2->getClassName()->getName());
286
            }
287
288 51
            return $OrderItem;
289 51
        }, $CartItems->toArray());
290
    }
291
292 51
    private function createShippingFromCustomer(Customer $Customer)
293
    {
294 51
        $Shipping = new Shipping();
295
        $Shipping
296 51
            ->setName01($Customer->getName01())
297 51
            ->setName02($Customer->getName02())
298 51
            ->setKana01($Customer->getKana01())
299 51
            ->setKana02($Customer->getKana02())
300 51
            ->setCompanyName($Customer->getCompanyName())
301 51
            ->setPhoneNumber($Customer->getPhoneNumber())
302 51
            ->setPostalCode($Customer->getPostalCode())
303 51
            ->setPref($Customer->getPref())
304 51
            ->setAddr01($Customer->getAddr01())
305 51
            ->setAddr02($Customer->getAddr02());
306
307 51
        return $Shipping;
308
    }
309
310 51
    private function setDefaultDelivery(Shipping $Shipping)
311
    {
312
        // 配送商品に含まれる販売種別を抽出.
313 51
        $OrderItems = $Shipping->getOrderItems();
314 51
        $SaleTypes = [];
315
        /** @var OrderItem $OrderItem */
316 51 View Code Duplication
        foreach ($OrderItems as $OrderItem) {
317 51
            $ProductClass = $OrderItem->getProductClass();
318 51
            $SaleType = $ProductClass->getSaleType();
319 51
            $SaleTypes[$SaleType->getId()] = $SaleType;
320
        }
321
322
        // 販売種別に紐づく配送業者を取得.
323 51
        $Deliveries = $this->deliveryRepository->getDeliveries($SaleTypes);
324
325
        // 初期の配送業者を設定
326 51
        $Delivery = current($Deliveries);
327 51
        $Shipping->setDelivery($Delivery);
328 51
        $Shipping->setShippingDeliveryName($Delivery->getName());
329
    }
330
331 51
    private function setDefaultPayment(Order $Order)
332
    {
333 51
        $OrderItems = $Order->getOrderItems();
334
335
        // 受注明細に含まれる販売種別を抽出.
336 51
        $SaleTypes = [];
337
        /** @var OrderItem $OrderItem */
338 51 View Code Duplication
        foreach ($OrderItems as $OrderItem) {
339 51
            $ProductClass = $OrderItem->getProductClass();
340 51
            if (is_null($ProductClass)) {
341
                // 商品明細のみ対象とする. 送料明細等はスキップする.
342
                continue;
343
            }
344 51
            $SaleType = $ProductClass->getSaleType();
345 51
            $SaleTypes[$SaleType->getId()] = $SaleType;
346
        }
347
348
        // 販売種別に紐づく配送業者を抽出
349 51
        $Deliveries = $this->deliveryRepository->getDeliveries($SaleTypes);
350
351
        // 利用可能な支払い方法を抽出.
352 51
        $Payments = $this->paymentRepository->findAllowedPayments($Deliveries, true);
353
354
        // 初期の支払い方法を設定.
355 51
        $Payment = current($Payments);
356 51
        if ($Payment) {
357 51
            $Order->setPayment($Payment);
358 51
            $Order->setPaymentMethod($Payment->getMethod());
359
        }
360
    }
361
362 51
    private function addOrderItems(Order $Order, Shipping $Shipping, array $OrderItems)
363
    {
364 51
        foreach ($OrderItems as $OrderItem) {
365 51
            $Shipping->addOrderItem($OrderItem);
366 51
            $Order->addOrderItem($OrderItem);
367 51
            $OrderItem->setOrder($Order);
368 51
            $OrderItem->setShipping($Shipping);
369
        }
370
    }
371
}
372