<?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\Controller;
use Customize\Repository\Master\MtbPrintRepository;
use Customize\Service\TaxRuleServiceCustom as TaxRuleService;
use Eccube\Controller\AbstractController;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\ProductClass;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\ClassCategoryRepository;
use Eccube\Repository\ClassNameRepository;
use Eccube\Repository\ProductClassRepository;
use Customize\Service\CartService;
use Eccube\Repository\TaxRuleRepository;
use Eccube\Service\OrderHelper;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\PurchaseFlow;
use Eccube\Service\PurchaseFlow\PurchaseFlowResult;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Eccube\Repository\ProductRepository;
class CartController extends AbstractController
{
/**
* @var ProductClassRepository
*/
protected $productClassRepository;
/**
* @var CartService
*/
protected $cartService;
/**
* @var PurchaseFlow
*/
protected $purchaseFlow;
/**
* @var BaseInfo
*/
protected $baseInfo;
protected $mtbPrintRepository;
protected $taxRuleService;
protected $taxRuleRepository;
protected $productRepository;
protected $classNameRepository;
protected $classCategoryRepository;
/**
* CartController constructor.
*
* @param ProductClassRepository $productClassRepository
* @param CartService $cartService
* @param PurchaseFlow $cartPurchaseFlow
* @param BaseInfoRepository $baseInfoRepository
*/
public function __construct(
ProductClassRepository $productClassRepository,
CartService $cartService,
PurchaseFlow $cartPurchaseFlow,
BaseInfoRepository $baseInfoRepository,
MtbPrintRepository $mtbPrintRepository,
TaxRuleService $taxRuleService,
TaxRuleRepository $taxRuleRepository,
ProductRepository $productRepository,
ClassNameRepository $classNameRepository,
ClassCategoryRepository $classCategoryRepository
) {
$this->productClassRepository = $productClassRepository;
$this->cartService = $cartService;
$this->purchaseFlow = $cartPurchaseFlow;
$this->baseInfo = $baseInfoRepository->get();
$this->mtbPrintRepository = $mtbPrintRepository;
$this->taxRuleService = $taxRuleService;
$this->taxRuleRepository = $taxRuleRepository;
$this->productRepository = $productRepository;
$this->classNameRepository = $classNameRepository;
$this->classCategoryRepository = $classCategoryRepository;
}
/**
* カート画面.
*
* @Route("/cart", name="cart", methods={"GET"})
* @Template("Cart/index.twig")
*/
public function index(Request $request)
{
// カートを取得して明細の正規化を実行
$userRate = 0;
if($this->getUser()) {
$userRate = $this->baseInfo->getOptionUserRate();
}
$Carts = $this->cartService->getCarts();
$this->execPurchaseFlow($Carts);
// TODO itemHolderから取得できるように
$least = [];
$quantity = [];
$isDeliveryFree = [];
$totalPrice = 0;
$totalQuantity = 0;
$data_fee_print_all_price = $this->mtbPrintRepository->findOneBy(['product_print_fee_type' => 4, 'discriminator_type' => 'fee_print_all']);
$fee_print_all_price = 0;
$platePrint = [];
$taxRate = $this->taxRuleService->getTaxRate();
foreach ($Carts as $Cart) {
$totalProductPrice = 0;
$quantity[$Cart->getCartKey()] = 0;
$isDeliveryFree[$Cart->getCartKey()] = false;
if ($this->baseInfo->getDeliveryFreeQuantity()) {
if ($this->baseInfo->getDeliveryFreeQuantity() > $Cart->getQuantity()) {
$quantity[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeQuantity() - $Cart->getQuantity();
} else {
$isDeliveryFree[$Cart->getCartKey()] = true;
}
}
$classNameSize = $this->classNameRepository->findBy([
"name" => "サイズ"
]);
$arrIgnoreMerge = [];
foreach($classNameSize as $value) {
$ClassCategories = $this->classCategoryRepository->getList($value);
foreach ($ClassCategories as $ClassCategory) {
$arrIgnoreMerge[] = $ClassCategory->getId();
}
}
$newArrId = [];
foreach($Cart->GetCartItems() as $cartItem) {
if ($cartItem->getIsPrint() == 1) {
$idProduct = $cartItem->getProductClass()->getProduct()->getId();
$product = $this->productRepository->find($idProduct);
if(!isset($newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()])) {
$newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()] = [];
}
if(isset($newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()]['qty'])) {
$newArrId[$idProduct . '_' . $cartItem->getIsRepurchase() . '_' . $cartItem->getProductPrintColor()]['qty'] += $cartItem->getQuantity();
$qty = $newArrId[$idProduct . '_' . $cartItem->getIsRepurchase() . '_' . $cartItem->getProductPrintColor()]['qty'];
}else {
$qty = $cartItem->getQuantity();
}
$newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()]['qty'] = $qty;
$newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()]['idProduct'] = $idProduct;
$newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()]['isRepurchase'] = $cartItem->getIsRepurchase();
$newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()]['color'] = $cartItem->getProductPrintColor();
$newArrId[$idProduct.'_'.$cartItem->getIsRepurchase().'_'.$cartItem->getProductPrintColor()]['id'][] = $cartItem->getId();
}
}
$newArrUpdate = [];
foreach($newArrId as $k => $v) {
foreach ($v['id'] as $vv) {
$newArrUpdate[$vv] = [
'idProduct' => $v['idProduct'],
'qty' => $v['qty']
];
}
}
foreach($Cart->GetCartItems() as $cartItem) {
if ($cartItem->getIsPrint() == 1) {
$qty = $newArrUpdate[$cartItem->getId()]['qty'];
$idProduct = $cartItem->getProductClass()->getProduct()->getId();
$product_print_fee_price = 0;
if ($cartItem->getProductPrintFeeType() == 1) {
$dataMtbPrint = $this->mtbPrintRepository->findBy(
[
'product_print_fee_type' => $cartItem->getProductPrintFeeType(),
'discriminator_type' => 'fee_print_name'
]
);
foreach ($dataMtbPrint as $value) {
if ($value['product_print_fee_type_max'] > 0) {
if ($qty >= $value['product_print_fee_type_min'] && $qty <= $value['product_print_fee_type_max']) {
$product_print_fee_price = $value['price'];
break;
}
} else {
$product_print_fee_price = $value['price'];
}
}
} elseif ($cartItem->getProductPrintFeeType() == 3) {
$dataMtbPrint = $this->mtbPrintRepository->findBy(
[
'product_print_fee_type' => $cartItem->getProductPrintFeeType(),
'discriminator_type' => 'fee_print_name'
]
);
foreach ($dataMtbPrint as $value) {
if ($value['product_print_fee_type_max'] > 0) {
$product_print_fee_price = 50;
} else {
if ($qty >= $value['product_print_fee_type_min']) {
$product_print_fee_price = $value['price'];
break;
}
}
}
} else {
if($cartItem->getProductClass()) {
$idProduct = $cartItem->getProductClass()->getProduct()->getId();
$product = $this->productRepository->find($idProduct);
$product_print_fee_price = $product->getProductPrintFeePrice();
}
}
$cartItem->setProductPrintFeePrice($product_print_fee_price);
}
}
foreach($Cart->GetCartItems() as $cartItem) {
$pricePrint = 0;
if($cartItem->isProduct()) {
$totalProductPrice += $cartItem->getPrice() * $cartItem->getQuantity();
}
if ($cartItem->getIsPrint() == 1) {
if ($cartItem->getIsRepurchase() == 0) {
$platePrint[] = 1;
}
$pricePrint = $cartItem->getProductPrintFeePrice() * $cartItem->getQuantity();
}
$totalPrice = $totalPrice + ($cartItem->getTotalPrice()+$pricePrint);
}
$priceUserRate = $totalProductPrice * ($userRate/100);
if (count($platePrint) > 0) {
$fee_print_all_price = (int)$data_fee_print_all_price->getPrice()*count($platePrint);
if ($data_fee_print_all_price ) {
$fee_print_all_price = (int)$data_fee_print_all_price->getPrice()*count($platePrint);
}
}
$totalPriceProductFee = ($totalPrice - $priceUserRate) + $fee_print_all_price;
// $totalPriceTaxRate = $totalPriceProductFee * ($taxRate/100);
$totalPrice = $totalPriceProductFee;
if ($this->baseInfo->getDeliveryFreeAmount()) {
if (!$isDeliveryFree[$Cart->getCartKey()] && $this->baseInfo->getDeliveryFreeAmount() <= $totalPrice) {
$isDeliveryFree[$Cart->getCartKey()] = true;
} else {
$least[$Cart->getCartKey()] = $this->baseInfo->getDeliveryFreeAmount() - $totalPrice;
}
}
// $totalPrice += $Cart->getTotalPrice();
$totalQuantity += $Cart->getQuantity();
}
// カートが分割された時のセッション情報を削除
$request->getSession()->remove(OrderHelper::SESSION_CART_DIVIDE_FLAG);
$TaxRule = $this->taxRuleRepository->getByRule();
$roundType = 'common';
if($TaxRule->getRoundingType()->getId() == \Eccube\Entity\Master\RoundingType::ROUND) {
$roundType = 'common';
} else if($TaxRule->getRoundingType()->getId() == \Eccube\Entity\Master\RoundingType::FLOOR) {
$roundType = 'floor';
} else if($TaxRule->getRoundingType()->getId() == \Eccube\Entity\Master\RoundingType::CEIL) {
$roundType = 'ceil';
} else {
$roundType = 'ceil';
}
return [
'totalPrice' => $totalPrice,
'fee_print_all_price' => $fee_print_all_price,
'totalPlatePrint' => count($platePrint),
'totalQuantity' => $totalQuantity,
// 空のカートを削除し取得し直す
'Carts' => $this->cartService->getCarts(true),
'least' => $least,
'quantity' => $quantity,
'is_delivery_free' => $isDeliveryFree,
'userRate' => $userRate,
'taxRate' => $taxRate,
'roundType' => $roundType,
];
}
/**
* @param $Carts
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
*/
protected function execPurchaseFlow($Carts)
{
/** @var PurchaseFlowResult[] $flowResults */
$flowResults = array_map(function ($Cart) {
$purchaseContext = new PurchaseContext($Cart, $this->getUser());
return $this->purchaseFlow->validate($Cart, $purchaseContext);
}, $Carts);
// 復旧不可のエラーが発生した場合はカートをクリアして再描画
$hasError = false;
foreach ($flowResults as $result) {
if ($result->hasError()) {
$hasError = true;
foreach ($result->getErrors() as $error) {
$this->addRequestError($error->getMessage());
}
}
}
if ($hasError) {
$this->cartService->clear();
return $this->redirectToRoute('cart');
}
$this->cartService->save();
foreach ($flowResults as $index => $result) {
foreach ($result->getWarning() as $warning) {
if ($Carts[$index]->getItems()->count() > 0) {
$cart_key = $Carts[$index]->getCartKey();
$this->addRequestError($warning->getMessage(), "front.cart.${cart_key}");
} else {
// キーが存在しない場合はグローバルにエラーを表示する
$this->addRequestError($warning->getMessage());
}
}
}
return null;
}
/**
* カート明細の加算/減算/削除を行う.
*
* - 加算
* - 明細の個数を1増やす
* - 減算
* - 明細の個数を1減らす
* - 個数が0になる場合は、明細を削除する
* - 削除
* - 明細を削除する
*
* @Route(
* path="/cart/{operation}/{productClassId}",
* name="cart_handle_item",
* methods={"PUT"},
* requirements={
* "operation": "up|down|remove",
* "productClassId": "\d+"
* }
* )
*/
public function handleCartItem($operation, $productClassId, $cartItemId = 0)
{
log_info('カート明細操作開始', ['operation' => $operation, 'product_class_id' => $productClassId]);
$this->isTokenValid();
/** @var ProductClass $ProductClass */
$ProductClass = $this->productClassRepository->find($productClassId);
if (is_null($ProductClass)) {
log_info('商品が存在しないため、カート画面へredirect', ['operation' => $operation, 'product_class_id' => $productClassId]);
return $this->redirectToRoute('cart');
}
$cartItemId = 0;
if(isset($_GET['cartItemId'])) {
$cartItemId = (int)$_GET['cartItemId'];
}
$isPrint = false;
foreach($this->cartService->getCart()->getItems() as $value) {
if($value->getId() == $cartItemId) {
if($value->getIsPrint() == 1) {
$isPrint = true;
}
break;
}
}
$qty = 1;
if($isPrint == true) {
$printUnit = (int)$ProductClass->getProduct()->getPrinterUnit();
$orderUnit = (int)$ProductClass->getProduct()->getOrderUnit();
if($printUnit > 0) {
$qty = $printUnit;
} else {
if($orderUnit > 0) {
$qty = $orderUnit;
} else {
$qty = 1;
}
}
} else {
$orderUnit = (int)$ProductClass->getProduct()->getOrderUnit();
$qty = ($orderUnit > 0) ? $ProductClass->getProduct()->getOrderUnit() : 1;
}
// 明細の増減・削除
switch ($operation) {
case 'up':
$this->cartService->addProduct($ProductClass, $qty, ['update_quantity' => true, 'productClassId' => $productClassId, 'cartItemId' => $cartItemId]);
break;
case 'down':
$this->cartService->addProduct($ProductClass, -$qty, ['update_quantity' => true, 'cartItemId' => $cartItemId]);
break;
case 'remove':
$this->cartService->removeProduct($ProductClass, $cartItemId);
break;
}
// カートを取得して明細の正規化を実行
$Carts = $this->cartService->getCarts();
$this->execPurchaseFlow($Carts);
log_info('カート演算処理終了', ['operation' => $operation, 'product_class_id' => $productClassId]);
return $this->redirectToRoute('cart');
}
/**
* カートをロック状態に設定し、購入確認画面へ遷移する.
*
* @Route("/cart/buystep/{cart_key}", name="cart_buystep", requirements={"cart_key" = "[a-zA-Z0-9]+[_][\x20-\x7E]+"}, methods={"GET"})
*/
public function buystep(Request $request, $cart_key)
{
$Carts = $this->cartService->getCart();
if (!is_object($Carts)) {
return $this->redirectToRoute('cart');
}
// FRONT_CART_BUYSTEP_INITIALIZE
$event = new EventArgs(
[],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_CART_BUYSTEP_INITIALIZE);
$this->cartService->setPrimary($cart_key);
$this->cartService->save();
// FRONT_CART_BUYSTEP_COMPLETE
$event = new EventArgs(
[],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_CART_BUYSTEP_COMPLETE);
if ($event->hasResponse()) {
return $event->getResponse();
}
return $this->redirectToRoute('shopping');
}
}