Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
56.41% |
22 / 39 |
CRAP | |
86.45% |
338 / 391 |
ShoppingService | |
0.00% |
0 / 1 |
|
58.54% |
24 / 41 |
132.46 | |
86.45% |
338 / 391 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
getOrder | |
100.00% |
1 / 1 |
3 | |
100.00% |
8 / 8 |
|||
getNonMember | |
0.00% |
0 / 1 |
2.50 | |
50.00% |
3 / 6 |
|||
createOrder | |
100.00% |
1 / 1 |
2 | |
100.00% |
9 / 9 |
|||
registerPreOrder | |
0.00% |
0 / 1 |
2 | |
96.00% |
24 / 25 |
|||
getNewOrder | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
newOrder | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
copyToOrderFromCustomer | |
0.00% |
0 / 1 |
3 | |
96.15% |
25 / 26 |
|||
getDeliveriesCart | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
getDeliveriesOrder | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
getDeliveries | |
0.00% |
0 / 1 |
4.12 | |
50.00% |
3 / 6 |
|||
getNewShipping | |
100.00% |
1 / 1 |
3 | |
100.00% |
12 / 12 |
|||
copyToShippingFromCustomer | |
0.00% |
0 / 1 |
3 | |
97.56% |
40 / 41 |
|||
getNewDetails | |
100.00% |
1 / 1 |
2 | |
100.00% |
9 / 9 |
|||
getNewOrderDetail | |
0.00% |
0 / 1 |
3.07 | |
80.00% |
16 / 20 |
|||
getNewShipmentItem | |
0.00% |
0 / 1 |
7.19 | |
84.38% |
27 / 32 |
|||
getShippingDeliveryFeeTotal | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
getProductDeliveryFee | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
getAmount | |
100.00% |
1 / 1 |
1 | |
100.00% |
6 / 6 |
|||
setShippingDeliveryFee | |
100.00% |
1 / 1 |
3 | |
100.00% |
11 / 11 |
|||
setDeliveryFreeAmount | |
0.00% |
0 / 1 |
7.91 | |
37.50% |
3 / 8 |
|||
setDeliveryFreeQuantity | |
0.00% |
0 / 1 |
7.91 | |
37.50% |
3 / 8 |
|||
isOrderProduct | |
0.00% |
0 / 1 |
8.02 | |
92.86% |
13 / 14 |
|||
setOrderUpdate | |
100.00% |
1 / 1 |
4 | |
100.00% |
0 / 0 |
|||
setOrderUpdateData | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
setStockUpdate | |
100.00% |
1 / 1 |
3 | |
100.00% |
9 / 9 |
|||
setCustomerUpdate | |
100.00% |
1 / 1 |
2 | |
100.00% |
9 / 9 |
|||
getPayments | |
100.00% |
1 / 1 |
6 | |
100.00% |
8 / 8 |
|||
getFormDeliveryDates | |
0.00% |
0 / 1 |
15.15 | |
45.00% |
9 / 20 |
|||
getFormPayments | |
0.00% |
0 / 1 |
3.02 | |
87.50% |
7 / 8 |
|||
getShippingForm | |
100.00% |
1 / 1 |
1 | |
100.00% |
0 / 0 |
|||
getShippingFormBuilder | |
100.00% |
1 / 1 |
1 | |
100.00% |
11 / 11 |
|||
setFormData | |
100.00% |
1 / 1 |
3 | |
100.00% |
7 / 7 |
|||
calculateDeliveryFee | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
processPurchase | |
0.00% |
0 / 1 |
3.01 | |
90.91% |
10 / 11 |
|||
isDiscount | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
|||
setDiscount | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
calculatePrice | |
0.00% |
0 / 1 |
2.02 | |
83.33% |
5 / 6 |
|||
setOrderStatus | |
100.00% |
1 / 1 |
1 | |
100.00% |
7 / 7 |
|||
sendOrderMail | |
100.00% |
1 / 1 |
1 | |
100.00% |
11 / 11 |
|||
notifyComplete | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
<?php | |
/* | |
* This file is part of EC-CUBE | |
* | |
* Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved. | |
* | |
* http://www.lockon.co.jp/ | |
* | |
* This program is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU General Public License | |
* as published by the Free Software Foundation; either version 2 | |
* of the License, or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
*/ | |
namespace Eccube\Service; | |
use Doctrine\DBAL\LockMode; | |
use Eccube\Application; | |
use Eccube\Common\Constant; | |
use Eccube\Entity\Customer; | |
use Eccube\Entity\Delivery; | |
use Eccube\Entity\MailHistory; | |
use Eccube\Entity\Order; | |
use Eccube\Entity\OrderDetail; | |
use Eccube\Entity\Product; | |
use Eccube\Entity\ProductClass; | |
use Eccube\Entity\ShipmentItem; | |
use Eccube\Entity\Shipping; | |
use Eccube\Event\EccubeEvents; | |
use Eccube\Event\EventArgs; | |
use Eccube\Exception\CartException; | |
use Eccube\Exception\ShoppingException; | |
use Eccube\Util\Str; | |
class ShoppingService | |
{ | |
/** @var \Eccube\Application */ | |
public $app; | |
/** @var \Eccube\Service\CartService */ | |
protected $cartService; | |
/** @var \Eccube\Service\OrderService */ | |
protected $orderService; | |
/** @var \Eccube\Entity\BaseInfo */ | |
protected $BaseInfo; | |
/** @var \Doctrine\ORM\EntityManager */ | |
protected $em; | |
public function __construct(Application $app, $cartService, $orderService) | |
{ | |
$this->app = $app; | |
$this->cartService = $cartService; | |
$this->orderService = $orderService; | |
$this->BaseInfo = $app['eccube.repository.base_info']->get(); | |
} | |
/** | |
* セッションにセットされた受注情報を取得 | |
* | |
* @param null $status | |
* @return null|object | |
*/ | |
public function getOrder($status = null) | |
{ | |
// 受注データを取得 | |
$preOrderId = $this->cartService->getPreOrderId(); | |
if (!$preOrderId) { | |
return null; | |
} | |
$condition = array( | |
'pre_order_id' => $preOrderId, | |
); | |
if (!is_null($status)) { | |
$condition += array( | |
'OrderStatus' => $status, | |
); | |
} | |
$Order = $this->app['eccube.repository.order']->findOneBy($condition); | |
return $Order; | |
} | |
/** | |
* 非会員情報を取得 | |
* | |
* @param $sesisonKey | |
* @return $Customer|null | |
*/ | |
public function getNonMember($sesisonKey) | |
{ | |
// 非会員でも一度会員登録されていればショッピング画面へ遷移 | |
$nonMember = $this->app['session']->get($sesisonKey); | |
if (is_null($nonMember)) { | |
return null; | |
} | |
$Customer = $nonMember['customer']; | |
$Customer->setPref($this->app['eccube.repository.master.pref']->find($nonMember['pref'])); | |
return $Customer; | |
} | |
/** | |
* 受注情報を作成 | |
* | |
* @param $Customer | |
* @return \Eccube\Entity\Order | |
*/ | |
public function createOrder($Customer) | |
{ | |
// ランダムなpre_order_idを作成 | |
do { | |
$preOrderId = sha1(Str::random(32)); | |
$Order = $this->app['eccube.repository.order']->findOneBy(array( | |
'pre_order_id' => $preOrderId, | |
'OrderStatus' => $this->app['config']['order_processing'], | |
)); | |
} while ($Order); | |
// 受注情報、受注明細情報、お届け先情報、配送商品情報を作成 | |
$Order = $this->registerPreOrder( | |
$Customer, | |
$preOrderId); | |
$this->cartService->setPreOrderId($preOrderId); | |
$this->cartService->save(); | |
return $Order; | |
} | |
/** | |
* 仮受注情報作成 | |
* | |
* @param $Customer | |
* @param $preOrderId | |
* @return mixed | |
* @throws \Doctrine\ORM\NoResultException | |
* @throws \Doctrine\ORM\NonUniqueResultException | |
*/ | |
public function registerPreOrder(Customer $Customer, $preOrderId) | |
{ | |
$this->em = $this->app['orm.em']; | |
// 受注情報を作成 | |
$Order = $this->getNewOrder($Customer); | |
$Order->setPreOrderId($preOrderId); | |
$this->em->persist($Order); | |
// 配送業者情報を取得 | |
$deliveries = $this->getDeliveriesCart(); | |
// お届け先情報を作成 | |
$Order = $this->getNewShipping($Order, $Customer, $deliveries); | |
// 受注明細情報、配送商品情報を作成 | |
$Order = $this->getNewDetails($Order); | |
// 小計 | |
$subTotal = $this->orderService->getSubTotal($Order); | |
// 消費税のみの小計 | |
$tax = $this->orderService->getTotalTax($Order); | |
// 配送料合計金額 | |
$Order->setDeliveryFeeTotal($this->getShippingDeliveryFeeTotal($Order->getShippings())); | |
// 小計 | |
$Order->setSubTotal($subTotal); | |
// 配送料無料条件(合計金額) | |
$this->setDeliveryFreeAmount($Order); | |
// 配送料無料条件(合計数量) | |
$this->setDeliveryFreeQuantity($Order); | |
// 初期選択の支払い方法をセット | |
$payments = $this->app['eccube.repository.payment']->findAllowedPayments($deliveries); | |
$payments = $this->getPayments($payments, $subTotal); | |
if (count($payments) > 0) { | |
$payment = $payments[0]; | |
$Order->setPayment($payment); | |
$Order->setPaymentMethod($payment->getMethod()); | |
$Order->setCharge($payment->getCharge()); | |
} else { | |
$Order->setCharge(0); | |
} | |
$Order->setTax($tax); | |
// 合計金額の計算 | |
$this->calculatePrice($Order); | |
$this->em->flush(); | |
return $Order; | |
} | |
/** | |
* 受注情報を作成 | |
* @param $Customer | |
* @return \Eccube\Entity\Order | |
*/ | |
public function getNewOrder(Customer $Customer) | |
{ | |
$Order = $this->newOrder(); | |
$this->copyToOrderFromCustomer($Order, $Customer); | |
return $Order; | |
} | |
/** | |
* 受注情報を作成 | |
* @return \Eccube\Entity\Order | |
*/ | |
public function newOrder() | |
{ | |
$OrderStatus = $this->app['eccube.repository.order_status']->find($this->app['config']['order_processing']); | |
$Order = new \Eccube\Entity\Order($OrderStatus); | |
return $Order; | |
} | |
/** | |
* 受注情報を作成 | |
* | |
* @param \Eccube\Entity\Order $Order | |
* @param \Eccube\Entity\Customer|null $Customer | |
* @return \Eccube\Entity\Order | |
*/ | |
public function copyToOrderFromCustomer(Order $Order, Customer $Customer = null) | |
{ | |
if (is_null($Customer)) { | |
return $Order; | |
} | |
if ($Customer->getId()) { | |
$Order->setCustomer($Customer); | |
} | |
$Order | |
->setName01($Customer->getName01()) | |
->setName02($Customer->getName02()) | |
->setKana01($Customer->getKana01()) | |
->setKana02($Customer->getKana02()) | |
->setCompanyName($Customer->getCompanyName()) | |
->setEmail($Customer->getEmail()) | |
->setTel01($Customer->getTel01()) | |
->setTel02($Customer->getTel02()) | |
->setTel03($Customer->getTel03()) | |
->setFax01($Customer->getFax01()) | |
->setFax02($Customer->getFax02()) | |
->setFax03($Customer->getFax03()) | |
->setZip01($Customer->getZip01()) | |
->setZip02($Customer->getZip02()) | |
->setZipCode($Customer->getZip01().$Customer->getZip02()) | |
->setPref($Customer->getPref()) | |
->setAddr01($Customer->getAddr01()) | |
->setAddr02($Customer->getAddr02()) | |
->setSex($Customer->getSex()) | |
->setBirth($Customer->getBirth()) | |
->setJob($Customer->getJob()); | |
return $Order; | |
} | |
/** | |
* 配送業者情報を取得 | |
* | |
* @return array | |
*/ | |
public function getDeliveriesCart() | |
{ | |
// カートに保持されている商品種別を取得 | |
$productTypes = $this->cartService->getProductTypes(); | |
return $this->getDeliveries($productTypes); | |
} | |
/** | |
* 配送業者情報を取得 | |
* | |
* @param Order $Order | |
* @return array | |
*/ | |
public function getDeliveriesOrder(Order $Order) | |
{ | |
// 受注情報から商品種別を取得 | |
$productTypes = $this->orderService->getProductTypes($Order); | |
return $this->getDeliveries($productTypes); | |
} | |
/** | |
* 配送業者情報を取得 | |
* | |
* @param $productTypes | |
* @return array | |
*/ | |
public function getDeliveries($productTypes) | |
{ | |
// 商品種別に紐づく配送業者を取得 | |
$deliveries = $this->app['eccube.repository.delivery']->getDeliveries($productTypes); | |
if ($this->BaseInfo->getOptionMultipleShipping() == Constant::ENABLED) { | |
// 複数配送対応 | |
// 支払方法を取得 | |
$payments = $this->app['eccube.repository.payment']->findAllowedPayments($deliveries); | |
if (count($productTypes) > 1) { | |
// 商品種別が複数ある場合、配送対象となる配送業者を取得 | |
$deliveries = $this->app['eccube.repository.delivery']->findAllowedDeliveries($productTypes, $payments); | |
} | |
} | |
return $deliveries; | |
} | |
/** | |
* お届け先情報を作成 | |
* | |
* @param Order $Order | |
* @param Customer $Customer | |
* @param $deliveries | |
* @return Order | |
*/ | |
public function getNewShipping(Order $Order, Customer $Customer, $deliveries) | |
{ | |
$productTypes = array(); | |
foreach ($deliveries as $Delivery) { | |
if (!in_array($Delivery->getProductType()->getId(), $productTypes)) { | |
$Shipping = new Shipping(); | |
$this->copyToShippingFromCustomer($Shipping, $Customer) | |
->setOrder($Order) | |
->setDelFlg(Constant::DISABLED); | |
// 配送料金の設定 | |
$this->setShippingDeliveryFee($Shipping, $Delivery); | |
$this->em->persist($Shipping); | |
$Order->addShipping($Shipping); | |
$productTypes[] = $Delivery->getProductType()->getId(); | |
} | |
} | |
return $Order; | |
} | |
/** | |
* お届け先情報を作成 | |
* | |
* @param \Eccube\Entity\Shipping $Shipping | |
* @param \Eccube\Entity\Customer|null $Customer | |
* @return \Eccube\Entity\Shipping | |
*/ | |
public function copyToShippingFromCustomer(Shipping $Shipping, Customer $Customer = null) | |
{ | |
if (is_null($Customer)) { | |
return $Shipping; | |
} | |
$CustomerAddress = $this->app['eccube.repository.customer_address']->findOneBy( | |
array('Customer' => $Customer), | |
array('id' => 'ASC') | |
); | |
if (!is_null($CustomerAddress)) { | |
$Shipping | |
->setName01($CustomerAddress->getName01()) | |
->setName02($CustomerAddress->getName02()) | |
->setKana01($CustomerAddress->getKana01()) | |
->setKana02($CustomerAddress->getKana02()) | |
->setCompanyName($CustomerAddress->getCompanyName()) | |
->setTel01($CustomerAddress->getTel01()) | |
->setTel02($CustomerAddress->getTel02()) | |
->setTel03($CustomerAddress->getTel03()) | |
->setFax01($CustomerAddress->getFax01()) | |
->setFax02($CustomerAddress->getFax02()) | |
->setFax03($CustomerAddress->getFax03()) | |
->setZip01($CustomerAddress->getZip01()) | |
->setZip02($CustomerAddress->getZip02()) | |
->setZipCode($CustomerAddress->getZip01().$CustomerAddress->getZip02()) | |
->setPref($CustomerAddress->getPref()) | |
->setAddr01($CustomerAddress->getAddr01()) | |
->setAddr02($CustomerAddress->getAddr02()); | |
} else { | |
$Shipping | |
->setName01($Customer->getName01()) | |
->setName02($Customer->getName02()) | |
->setKana01($Customer->getKana01()) | |
->setKana02($Customer->getKana02()) | |
->setCompanyName($Customer->getCompanyName()) | |
->setTel01($Customer->getTel01()) | |
->setTel02($Customer->getTel02()) | |
->setTel03($Customer->getTel03()) | |
->setFax01($Customer->getFax01()) | |
->setFax02($Customer->getFax02()) | |
->setFax03($Customer->getFax03()) | |
->setZip01($Customer->getZip01()) | |
->setZip02($Customer->getZip02()) | |
->setZipCode($Customer->getZip01().$Customer->getZip02()) | |
->setPref($Customer->getPref()) | |
->setAddr01($Customer->getAddr01()) | |
->setAddr02($Customer->getAddr02()); | |
} | |
return $Shipping; | |
} | |
/** | |
* 受注明細情報、配送商品情報を作成 | |
* | |
* @param Order $Order | |
* @return Order | |
*/ | |
public function getNewDetails(Order $Order) | |
{ | |
// 受注詳細, 配送商品 | |
foreach ($this->cartService->getCart()->getCartItems() as $item) { | |
/* @var $ProductClass \Eccube\Entity\ProductClass */ | |
$ProductClass = $item->getObject(); | |
/* @var $Product \Eccube\Entity\Product */ | |
$Product = $ProductClass->getProduct(); | |
$quantity = $item->getQuantity(); | |
// 受注明細情報を作成 | |
$OrderDetail = $this->getNewOrderDetail($Product, $ProductClass, $quantity); | |
$OrderDetail->setOrder($Order); | |
$Order->addOrderDetail($OrderDetail); | |
// 配送商品情報を作成 | |
$this->getNewShipmentItem($Order, $Product, $ProductClass, $quantity); | |
} | |
return $Order; | |
} | |
/** | |
* 受注明細情報を作成 | |
* | |
* @param Product $Product | |
* @param ProductClass $ProductClass | |
* @param $quantity | |
* @return \Eccube\Entity\OrderDetail | |
*/ | |
public function getNewOrderDetail(Product $Product, ProductClass $ProductClass, $quantity) | |
{ | |
$OrderDetail = new OrderDetail(); | |
$TaxRule = $this->app['eccube.repository.tax_rule']->getByRule($Product, $ProductClass); | |
$OrderDetail->setProduct($Product) | |
->setProductClass($ProductClass) | |
->setProductName($Product->getName()) | |
->setProductCode($ProductClass->getCode()) | |
->setPrice($ProductClass->getPrice02()) | |
->setQuantity($quantity) | |
->setTaxRule($TaxRule->getId()) | |
->setTaxRate($TaxRule->getTaxRate()); | |
$ClassCategory1 = $ProductClass->getClassCategory1(); | |
if (!is_null($ClassCategory1)) { | |
$OrderDetail->setClasscategoryName1($ClassCategory1->getName()); | |
$OrderDetail->setClassName1($ClassCategory1->getClassName()->getName()); | |
} | |
$ClassCategory2 = $ProductClass->getClassCategory2(); | |
if (!is_null($ClassCategory2)) { | |
$OrderDetail->setClasscategoryName2($ClassCategory2->getName()); | |
$OrderDetail->setClassName2($ClassCategory2->getClassName()->getName()); | |
} | |
$this->em->persist($OrderDetail); | |
return $OrderDetail; | |
} | |
/** | |
* 配送商品情報を作成 | |
* | |
* @param Order $Order | |
* @param Product $Product | |
* @param ProductClass $ProductClass | |
* @param $quantity | |
* @return \Eccube\Entity\ShipmentItem | |
*/ | |
public function getNewShipmentItem(Order $Order, Product $Product, ProductClass $ProductClass, $quantity) | |
{ | |
$ShipmentItem = new ShipmentItem(); | |
$shippings = $Order->getShippings(); | |
// 選択された商品がどのお届け先情報と関連するかチェック | |
$Shipping = null; | |
foreach ($shippings as $s) { | |
if ($s->getDelivery()->getProductType()->getId() == $ProductClass->getProductType()->getId()) { | |
// 商品種別が同一のお届け先情報と関連させる | |
$Shipping = $s; | |
break; | |
} | |
} | |
if (is_null($Shipping)) { | |
// お届け先情報と関連していない場合、エラー | |
throw new CartException('shopping.delivery.not.producttype'); | |
} | |
// 商品ごとの配送料合計 | |
$productDeliveryFeeTotal = 0; | |
if (!is_null($this->BaseInfo->getOptionProductDeliveryFee())) { | |
$productDeliveryFeeTotal = $ProductClass->getDeliveryFee() * $quantity; | |
} | |
$Shipping->setShippingDeliveryFee($Shipping->getShippingDeliveryFee() + $productDeliveryFeeTotal); | |
$ShipmentItem->setShipping($Shipping) | |
->setOrder($Order) | |
->setProductClass($ProductClass) | |
->setProduct($Product) | |
->setProductName($Product->getName()) | |
->setProductCode($ProductClass->getCode()) | |
->setPrice($ProductClass->getPrice02()) | |
->setQuantity($quantity); | |
$ClassCategory1 = $ProductClass->getClassCategory1(); | |
if (!is_null($ClassCategory1)) { | |
$ShipmentItem->setClasscategoryName1($ClassCategory1->getName()); | |
$ShipmentItem->setClassName1($ClassCategory1->getClassName()->getName()); | |
} | |
$ClassCategory2 = $ProductClass->getClassCategory2(); | |
if (!is_null($ClassCategory2)) { | |
$ShipmentItem->setClasscategoryName2($ClassCategory2->getName()); | |
$ShipmentItem->setClassName2($ClassCategory2->getClassName()->getName()); | |
} | |
$Shipping->addShipmentItem($ShipmentItem); | |
$this->em->persist($ShipmentItem); | |
return $ShipmentItem; | |
} | |
/** | |
* お届け先ごとの送料合計を取得 | |
* | |
* @param $shippings | |
* @return int | |
*/ | |
public function getShippingDeliveryFeeTotal($shippings) | |
{ | |
$deliveryFeeTotal = 0; | |
foreach ($shippings as $Shipping) { | |
$deliveryFeeTotal += $Shipping->getShippingDeliveryFee(); | |
} | |
return $deliveryFeeTotal; | |
} | |
/** | |
* 商品ごとの配送料を取得 | |
* | |
* @param Shipping $Shipping | |
* @return int | |
*/ | |
public function getProductDeliveryFee(Shipping $Shipping) | |
{ | |
$productDeliveryFeeTotal = 0; | |
$shipmentItems = $Shipping->getShipmentItems(); | |
foreach ($shipmentItems as $ShipmentItem) { | |
$productDeliveryFeeTotal += $ShipmentItem->getProductClass()->getDeliveryFee() * $ShipmentItem->getQuantity(); | |
} | |
return $productDeliveryFeeTotal; | |
} | |
/** | |
* 住所などの情報が変更された時に金額の再計算を行う | |
* | |
* @param Order $Order | |
* @return Order | |
*/ | |
public function getAmount(Order $Order) | |
{ | |
// 初期選択の配送業者をセット | |
$shippings = $Order->getShippings(); | |
// 配送料合計金額 | |
$Order->setDeliveryFeeTotal($this->getShippingDeliveryFeeTotal($shippings)); | |
// 配送料無料条件(合計金額) | |
$this->setDeliveryFreeAmount($Order); | |
// 配送料無料条件(合計数量) | |
$this->setDeliveryFreeQuantity($Order); | |
// 合計金額の計算 | |
$this->calculatePrice($Order); | |
return $Order; | |
} | |
/** | |
* 配送料金の設定 | |
* | |
* @param Shipping $Shipping | |
* @param Delivery|null $Delivery | |
*/ | |
public function setShippingDeliveryFee(Shipping $Shipping, Delivery $Delivery = null) | |
{ | |
// 配送料金の設定 | |
if (is_null($Delivery)) { | |
$Delivery = $Shipping->getDelivery(); | |
} | |
$deliveryFee = $this->app['eccube.repository.delivery_fee']->findOneBy(array('Delivery' => $Delivery, 'Pref' => $Shipping->getPref())); | |
$Shipping->setDeliveryFee($deliveryFee); | |
$Shipping->setDelivery($Delivery); | |
// 商品ごとの配送料合計 | |
$productDeliveryFeeTotal = 0; | |
if (!is_null($this->BaseInfo->getOptionProductDeliveryFee())) { | |
$productDeliveryFeeTotal += $this->getProductDeliveryFee($Shipping); | |
} | |
$Shipping->setShippingDeliveryFee($deliveryFee->getFee() + $productDeliveryFeeTotal); | |
$Shipping->setShippingDeliveryName($Delivery->getName()); | |
} | |
/** | |
* 配送料無料条件(合計金額)の条件を満たしていれば配送料金を0に設定 | |
* | |
* @param Order $Order | |
*/ | |
public function setDeliveryFreeAmount(Order $Order) | |
{ | |
// 配送料無料条件(合計金額) | |
$deliveryFreeAmount = $this->BaseInfo->getDeliveryFreeAmount(); | |
if (!is_null($deliveryFreeAmount)) { | |
// 合計金額が設定金額以上であれば送料無料 | |
if ($Order->getSubTotal() >= $deliveryFreeAmount) { | |
$Order->setDeliveryFeeTotal(0); | |
// お届け先情報の配送料も0にセット | |
$shippings = $Order->getShippings(); | |
foreach ($shippings as $Shipping) { | |
$Shipping->setShippingDeliveryFee(0); | |
} | |
} | |
} | |
} | |
/** | |
* 配送料無料条件(合計数量)の条件を満たしていれば配送料金を0に設定 | |
* | |
* @param Order $Order | |
*/ | |
public function setDeliveryFreeQuantity(Order $Order) | |
{ | |
// 配送料無料条件(合計数量) | |
$deliveryFreeQuantity = $this->BaseInfo->getDeliveryFreeQuantity(); | |
if (!is_null($deliveryFreeQuantity)) { | |
// 合計数量が設定数量以上であれば送料無料 | |
if ($this->orderService->getTotalQuantity($Order) >= $deliveryFreeQuantity) { | |
$Order->setDeliveryFeeTotal(0); | |
// お届け先情報の配送料も0にセット | |
$shippings = $Order->getShippings(); | |
foreach ($shippings as $Shipping) { | |
$Shipping->setShippingDeliveryFee(0); | |
} | |
} | |
} | |
} | |
/** | |
* 商品公開ステータスチェック、在庫チェック、購入制限数チェックを行い、在庫情報をロックする | |
* | |
* @param $em トランザクション制御されているEntityManager | |
* @param Order $Order 受注情報 | |
* @return bool true : 成功、false : 失敗 | |
*/ | |
public function isOrderProduct($em, \Eccube\Entity\Order $Order) | |
{ | |
// 商品公開ステータスチェック | |
$orderDetails = $Order->getOrderDetails(); | |
foreach ($orderDetails as $orderDetail) { | |
if ($orderDetail->getProduct()->getStatus()->getId() != \Eccube\Entity\Master\Disp::DISPLAY_SHOW) { | |
// 商品が非公開ならエラー | |
return false; | |
} | |
// 購入制限数チェック | |
if (!is_null($orderDetail->getProductClass()->getSaleLimit())) { | |
if ($orderDetail->getQuantity() > $orderDetail->getProductClass()->getSaleLimit()) { | |
return false; | |
} | |
} | |
} | |
// 在庫チェック | |
foreach ($orderDetails as $orderDetail) { | |
// 在庫が無制限かチェックし、制限ありなら在庫数をチェック | |
if ($orderDetail->getProductClass()->getStockUnlimited() == Constant::DISABLED) { | |
// 在庫チェックあり | |
// 在庫に対してロック(select ... for update)を実行 | |
$productStock = $em->getRepository('Eccube\Entity\ProductStock')->find( | |
$orderDetail->getProductClass()->getProductStock()->getId(), LockMode::PESSIMISTIC_WRITE | |
); | |
// 購入数量と在庫数をチェックして在庫がなければエラー | |
if ($orderDetail->getQuantity() > $productStock->getStock()) { | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
/** | |
* 受注情報、お届け先情報の更新 | |
* | |
* @param Order $Order 受注情報 | |
* @param $data フォームデータ | |
* | |
* @deprecated since 3.0.5, to be removed in 3.1 | |
*/ | |
public function setOrderUpdate(Order $Order, $data) | |
{ | |
// 受注情報を更新 | |
$Order->setOrderDate(new \DateTime()); | |
$Order->setOrderStatus($this->app['eccube.repository.order_status']->find($this->app['config']['order_new'])); | |
$Order->setMessage($data['message']); | |
// お届け先情報を更新 | |
$shippings = $data['shippings']; | |
foreach ($shippings as $Shipping) { | |
$Delivery = $Shipping->getDelivery(); | |
$deliveryFee = $this->app['eccube.repository.delivery_fee']->findOneBy(array( | |
'Delivery' => $Delivery, | |
'Pref' => $Shipping->getPref() | |
)); | |
$deliveryTime = $Shipping->getDeliveryTime(); | |
if (!empty($deliveryTime)) { | |
$Shipping->setShippingDeliveryTime($deliveryTime->getDeliveryTime()); | |
} | |
$Shipping->setDeliveryFee($deliveryFee); | |
// 商品ごとの配送料合計 | |
$productDeliveryFeeTotal = 0; | |
if (!is_null($this->BaseInfo->getOptionProductDeliveryFee())) { | |
$productDeliveryFeeTotal += $this->getProductDeliveryFee($Shipping); | |
} | |
$Shipping->setShippingDeliveryFee($deliveryFee->getFee() + $productDeliveryFeeTotal); | |
$Shipping->setShippingDeliveryName($Delivery->getName()); | |
} | |
// 配送料無料条件(合計金額) | |
$this->setDeliveryFreeAmount($Order); | |
// 配送料無料条件(合計数量) | |
$this->setDeliveryFreeQuantity($Order); | |
} | |
/** | |
* 受注情報の更新 | |
* | |
* @param Order $Order 受注情報 | |
*/ | |
public function setOrderUpdateData(Order $Order) | |
{ | |
// 受注情報を更新 | |
$Order->setOrderDate(new \DateTime()); | |
$OrderStatus = $this->app['eccube.repository.order_status']->find($this->app['config']['order_new']); | |
$this->setOrderStatus($Order, $OrderStatus); | |
} | |
/** | |
* 在庫情報の更新 | |
* | |
* @param $em トランザクション制御されているEntityManager | |
* @param Order $Order 受注情報 | |
*/ | |
public function setStockUpdate($em, Order $Order) | |
{ | |
$orderDetails = $Order->getOrderDetails(); | |
// 在庫情報更新 | |
foreach ($orderDetails as $orderDetail) { | |
// 在庫が無制限かチェックし、制限ありなら在庫数を更新 | |
if ($orderDetail->getProductClass()->getStockUnlimited() == Constant::DISABLED) { | |
$productStock = $em->getRepository('Eccube\Entity\ProductStock')->find( | |
$orderDetail->getProductClass()->getProductStock()->getId() | |
); | |
// 在庫情報の在庫数を更新 | |
$stock = $productStock->getStock() - $orderDetail->getQuantity(); | |
$productStock->setStock($stock); | |
// 商品規格情報の在庫数を更新 | |
$orderDetail->getProductClass()->setStock($stock); | |
} | |
} | |
} | |
/** | |
* 会員情報の更新 | |
* | |
* @param Order $Order 受注情報 | |
* @param Customer $user ログインユーザ | |
*/ | |
public function setCustomerUpdate(Order $Order, Customer $user) | |
{ | |
$orderDetails = $Order->getOrderDetails(); | |
// 顧客情報を更新 | |
$now = new \DateTime(); | |
$firstBuyDate = $user->getFirstBuyDate(); | |
if (empty($firstBuyDate)) { | |
$user->setFirstBuyDate($now); | |
} | |
$user->setLastBuyDate($now); | |
$user->setBuyTimes($user->getBuyTimes() + 1); | |
$user->setBuyTotal($user->getBuyTotal() + $Order->getTotal()); | |
} | |
/** | |
* 支払方法選択の表示設定 | |
* | |
* @param $payments 支払選択肢情報 | |
* @param $subTotal 小計 | |
* @return array | |
*/ | |
public function getPayments($payments, $subTotal) | |
{ | |
$pays = array(); | |
foreach ($payments as $payment) { | |
// 支払方法の制限値内であれば表示 | |
if (!is_null($payment)) { | |
$pay = $this->app['eccube.repository.payment']->find($payment['id']); | |
if (intval($pay->getRuleMin()) <= $subTotal) { | |
if (is_null($pay->getRuleMax()) || $pay->getRuleMax() >= $subTotal) { | |
$pays[] = $pay; | |
} | |
} | |
} | |
} | |
return $pays; | |
} | |
/** | |
* お届け日を取得 | |
* | |
* @param Order $Order | |
* @return array | |
*/ | |
public function getFormDeliveryDates(Order $Order) | |
{ | |
// お届け日の設定 | |
$minDate = 0; | |
$deliveryDateFlag = false; | |
// 配送時に最大となる商品日数を取得 | |
foreach ($Order->getOrderDetails() as $detail) { | |
$deliveryDate = $detail->getProductClass()->getDeliveryDate(); | |
if (!is_null($deliveryDate)) { | |
if ($deliveryDate->getValue() < 0) { | |
// 配送日数がマイナスの場合はお取り寄せなのでスキップする | |
$deliveryDateFlag = false; | |
break; | |
} | |
if ($minDate < $deliveryDate->getValue()) { | |
$minDate = $deliveryDate->getValue(); | |
} | |
// 配送日数が設定されている | |
$deliveryDateFlag = true; | |
} | |
} | |
// 配達最大日数期間を設定 | |
$deliveryDates = array(); | |
// 配送日数が設定されている | |
if ($deliveryDateFlag) { | |
$period = new \DatePeriod ( | |
new \DateTime($minDate.' day'), | |
new \DateInterval('P1D'), | |
new \DateTime($minDate + $this->app['config']['deliv_date_end_max'].' day') | |
); | |
foreach ($period as $day) { | |
$deliveryDates[$day->format('Y/m/d')] = $day->format('Y/m/d'); | |
} | |
} | |
return $deliveryDates; | |
} | |
/** | |
* 支払方法を取得 | |
* | |
* @param $deliveries | |
* @param Order $Order | |
* @return array | |
*/ | |
public function getFormPayments($deliveries, Order $Order) | |
{ | |
$productTypes = $this->orderService->getProductTypes($Order); | |
if ($this->BaseInfo->getOptionMultipleShipping() == Constant::ENABLED && count($productTypes) > 1) { | |
// 複数配送時の支払方法 | |
$payments = $this->app['eccube.repository.payment']->findAllowedPayments($deliveries); | |
} else { | |
// 配送業者をセット | |
$shippings = $Order->getShippings(); | |
$Shipping = $shippings[0]; | |
$payments = $this->app['eccube.repository.payment']->findPayments($Shipping->getDelivery(), true); | |
} | |
$payments = $this->getPayments($payments, $Order->getSubTotal()); | |
return $payments; | |
} | |
/** | |
* お届け先ごとにFormを作成 | |
* | |
* @param Order $Order | |
* @return \Symfony\Component\Form\Form | |
* @deprecated since 3.0, to be removed in 3.1 | |
*/ | |
public function getShippingForm(Order $Order) | |
{ | |
$message = $Order->getMessage(); | |
$deliveries = $this->getDeliveriesOrder($Order); | |
// 配送業者の支払方法を取得 | |
$payments = $this->getFormPayments($deliveries, $Order); | |
$builder = $this->app['form.factory']->createBuilder('shopping', null, array( | |
'payments' => $payments, | |
'payment' => $Order->getPayment(), | |
'message' => $message, | |
)); | |
$builder | |
->add('shippings', 'collection', array( | |
'type' => 'shipping_item', | |
'data' => $Order->getShippings(), | |
)); | |
$form = $builder->getForm(); | |
return $form; | |
} | |
/** | |
* お届け先ごとにFormBuilderを作成 | |
* | |
* @param Order $Order | |
* @return \Symfony\Component\Form\FormBuilderInterface | |
*/ | |
public function getShippingFormBuilder(Order $Order) | |
{ | |
$message = $Order->getMessage(); | |
$deliveries = $this->getDeliveriesOrder($Order); | |
// 配送業者の支払方法を取得 | |
$payments = $this->getFormPayments($deliveries, $Order); | |
$builder = $this->app['form.factory']->createBuilder('shopping', null, array( | |
'payments' => $payments, | |
'payment' => $Order->getPayment(), | |
'message' => $message, | |
)); | |
$builder | |
->add('shippings', 'collection', array( | |
'type' => 'shipping_item', | |
'data' => $Order->getShippings(), | |
)); | |
return $builder; | |
} | |
/** | |
* フォームデータを更新 | |
* | |
* @param Order $Order | |
* @param array $data | |
*/ | |
public function setFormData(Order $Order, array $data) | |
{ | |
// お問い合わせ | |
$Order->setMessage($data['message']); | |
// お届け先情報を更新 | |
$shippings = $data['shippings']; | |
foreach ($shippings as $Shipping) { | |
$deliveryTime = $Shipping->getDeliveryTime(); | |
if (!empty($deliveryTime)) { | |
$Shipping->setShippingDeliveryTime($deliveryTime->getDeliveryTime()); | |
} | |
} | |
} | |
/** | |
* 配送料の合計金額を計算 | |
* | |
* @param Order $Order | |
* @return Order | |
*/ | |
public function calculateDeliveryFee(Order $Order) | |
{ | |
// 配送業者を取得 | |
$shippings = $Order->getShippings(); | |
// 配送料合計金額 | |
$Order->setDeliveryFeeTotal($this->getShippingDeliveryFeeTotal($shippings)); | |
// 配送料無料条件(合計金額) | |
$this->setDeliveryFreeAmount($Order); | |
// 配送料無料条件(合計数量) | |
$this->setDeliveryFreeQuantity($Order); | |
return $Order; | |
} | |
/** | |
* 購入処理を行う | |
* | |
* @param Order $Order | |
* @throws ShoppingException | |
*/ | |
public function processPurchase(Order $Order) | |
{ | |
$em = $this->app['orm.em']; | |
// 合計金額の再計算 | |
$this->calculatePrice($Order); | |
// 商品公開ステータスチェック、商品制限数チェック、在庫チェック | |
$check = $this->isOrderProduct($em, $Order); | |
if (!$check) { | |
throw new ShoppingException('front.shopping.stock.error'); | |
} | |
// 受注情報、配送情報を更新 | |
$Order = $this->calculateDeliveryFee($Order); | |
$this->setOrderUpdateData($Order); | |
// 在庫情報を更新 | |
$this->setStockUpdate($em, $Order); | |
if ($this->app->isGranted('ROLE_USER')) { | |
// 会員の場合、購入金額を更新 | |
$this->setCustomerUpdate($Order, $this->app->user()); | |
} | |
} | |
/** | |
* 値引き可能かチェック | |
* | |
* @param Order $Order | |
* @param $discount | |
* @return bool | |
*/ | |
public function isDiscount(Order $Order, $discount) | |
{ | |
if ($Order->getTotal() < $discount) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* 値引き金額をセット | |
* | |
* @param Order $Order | |
* @param $discount | |
*/ | |
public function setDiscount(Order $Order, $discount) | |
{ | |
$Order->setDiscount($Order->getDiscount() + $discount); | |
} | |
/** | |
* 合計金額を計算 | |
* | |
* @param Order $Order | |
* @return Order | |
*/ | |
public function calculatePrice(Order $Order) | |
{ | |
$total = $Order->getTotalPrice(); | |
if ($total < 0) { | |
// 合計金額がマイナスの場合、0を設定し、discountは値引きされた額のみセット | |
$total = 0; | |
} | |
$Order->setTotal($total); | |
$Order->setPaymentTotal($total); | |
return $Order; | |
} | |
/** | |
* 受注ステータスをセット | |
* | |
* @param Order $Order | |
* @param $status | |
* @return Order | |
*/ | |
public function setOrderStatus(Order $Order, $status) | |
{ | |
$Order->setOrderDate(new \DateTime()); | |
$Order->setOrderStatus($this->app['eccube.repository.order_status']->find($status)); | |
$event = new EventArgs( | |
array( | |
'Order' => $Order, | |
), | |
null | |
); | |
$this->app['eccube.event.dispatcher']->dispatch(EccubeEvents::SERVICE_SHOPPING_ORDER_STATUS, $event); | |
return $Order; | |
} | |
/** | |
* 受注メール送信を行う | |
* | |
* @param Order $Order | |
* @return MailHistory | |
*/ | |
public function sendOrderMail(Order $Order) | |
{ | |
// メール送信 | |
$message = $this->app['eccube.service.mail']->sendOrderMail($Order); | |
// 送信履歴を保存. | |
$MailTemplate = $this->app['eccube.repository.mail_template']->find(1); | |
$MailHistory = new MailHistory(); | |
$MailHistory | |
->setSubject($message->getSubject()) | |
->setMailBody($message->getBody()) | |
->setMailTemplate($MailTemplate) | |
->setSendDate(new \DateTime()) | |
->setOrder($Order); | |
$this->app['orm.em']->persist($MailHistory); | |
$this->app['orm.em']->flush($MailHistory); | |
return $MailHistory; | |
} | |
/** | |
* 受注処理完了通知 | |
* | |
* @param Order $Order | |
*/ | |
public function notifyComplete(Order $Order) | |
{ | |
$event = new EventArgs( | |
array( | |
'Order' => $Order, | |
), | |
null | |
); | |
$this->app['eccube.event.dispatcher']->dispatch(EccubeEvents::SERVICE_SHOPPING_NOTIFY_COMPLETE, $event); | |
} | |
} |