<?php
namespace Customize\Controller;
use Carbon\Carbon;
use Customize\Service\EcconnectfmService;
use Customize\Repository\OrderRepository;
use Customize\Repository\OrderItemRepository;
use Eccube\Entity\Customer;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Form\Type\AddCartType;
use Eccube\Controller\AbstractController;
use Eccube\Repository\ProductClassRepository;
use Eccube\Repository\ProductRepository;
use Eccube\Service\CartService;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\PurchaseFlow;
use Knp\Component\Pager\PaginatorInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
class MyPageController extends AbstractController
{
/**
* @var PurchaseFlow
*/
protected $purchaseFlow;
/**
* @var OrderRepository
*/
protected $orderRepository;
/**
* @var OrderItemRepository
*/
protected $orderItemRepository;
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var ProductClassRepository
*/
protected $productClassRepository;
/**
* @var CartService
*/
protected $cartService;
/**
* @var EcconnectfmService
*/
private EcconnectfmService $ecconnectfmService;
/**
* MypageController constructor.
*/
public function __construct(
PurchaseFlow $cartPurchaseFlow,
OrderRepository $orderRepository,
OrderItemRepository $orderItemRepository,
ProductRepository $productRepository,
ProductClassRepository $productClassRepository,
CartService $cartService,
EcconnectfmService $ecconnectfmService
) {
$this->purchaseFlow = $cartPurchaseFlow;
$this->orderRepository = $orderRepository;
$this->orderItemRepository = $orderItemRepository;
$this->productRepository = $productRepository;
$this->productClassRepository = $productClassRepository;
$this->cartService = $cartService;
$this->ecconnectfmService = $ecconnectfmService;
}
/**
* @Route("/mypage/detail", name="mypage_detail", methods={"GET"})
* @Template("Mypage/detail.twig")
*/
public function detail()
{
/** @var Customer $Customer */
$Customer = $this->getUser();
$Customer->setPlainPassword($this->eccubeConfig['eccube_default_password']);
return [
'Customer' => $Customer,
];
}
/**
* @Route("/mypage/history", name="mypage_history", methods={"GET"})
* @Template("Mypage/history_index.twig")
*/
public function history(Request $request, PaginatorInterface $paginator)
{
$Customer = $this->getUser();
// 購入処理中/決済処理中ステータスの受注を非表示にする.
$this->entityManager
->getFilters()
->enable('incomplete_order_status_hidden');
// paginator
$qb = $this->orderRepository->getQueryBuilderByCustomer($Customer);
$pagination = $paginator->paginate(
$qb,
$request->get('pageno', 1),
$this->eccubeConfig['eccube_search_pmax']
);
return [
'pagination' => $pagination,
];
}
/**
* @Route("/mypage/history/{id}", name="mypage_history_detail", methods={"GET"}, requirements={"id" = "\d+"})
* @Template("Mypage/history_detail.twig")
*/
public function historyDetail(Request $request, $id)
{
if (empty($id)) {
return $this->redirectToRoute('mypage_history');
}
$Customer = $this->getUser();
$Order = $this->orderRepository->getOrderByCustomer($Customer, $id);
return [
'Customer' => $Customer,
'Order' => $Order,
];
}
/**
* @Route("/mypage/reserve", name="mypage_reserve", methods={"GET"})
* @Template("Mypage/reserve.twig")
*/
public function reserve(Request $request, PaginatorInterface $paginator)
{
/** @var Customer $Customer */
$Customer = $this->getUser();
$Customer->setPlainPassword($this->eccubeConfig['eccube_default_password']);
$qb = $this->orderRepository->getReserveQueryBuilderByCustomer($Customer);
$pagination = $paginator->paginate(
$qb,
$request->get('pageno', 1),
$this->eccubeConfig['eccube_search_pmax'],
['wrap-queries' => true]
);
$Reserves = $qb->getQuery()->getResult();
return [
'pagination' => $pagination,
'totalQuantity' => empty($Reserves) ? 0 : count($Reserves[0]->getOrderItems())
];
}
/**
* 予約明細の加算/減算/削除を行う.
*
* - 加算
* - 明細の個数を1増やす
* - 減算
* - 明細の個数を1減らす
* - 個数が0になる場合は、明細を削除する
* - 削除
* - 明細を削除する
*
* @Route(
* path="/reserve/{operation}/{productId}/{productClassId}",
* name="reserve_handle_item",
* methods={"PUT"},
* requirements={
* "operation": "extend|remove",
* "productId": "\d+",
* "productClassId": "\d+"
* }
* )
*/
public function handleReserveItem($operation, $productId, $productClassId)
{
log_info('予約明細操作開始', ['operation' => $operation, 'product_class_id' => $productClassId]);
$this->isTokenValid();
$Product = $this->productRepository->find($productId);
$ProductClass = $this->productClassRepository->find($productClassId);
if (is_null($Product) || is_null($ProductClass)) {
log_info('予約商品が存在しないため、予約画面へredirect', ['operation' => $operation, 'product_id' => $productId, 'product_class_id' => $productClassId]);
return $this->redirectToRoute('mypage_reserve');
}
$ReserveItems = $this->orderItemRepository->getReserveItems($this->getUser(), $Product, $ProductClass);
if (is_null($ReserveItems)) {
log_info('予約商品が存在しないため、予約画面へredirect', ['operation' => $operation, 'product_id' => $productId, 'product_class_id' => $productClassId]);
return $this->redirectToRoute('mypage_reserve');
}
// 明細の増減・削除
switch ($operation) {
case 'extend':
foreach ($ReserveItems as $ReserveItem) {
$ReserveItem->setExpirationContactFlg(false);
$ReserveItem->setExpirationDate(Carbon::now()->addDays(90));
$this->entityManager->persist($ReserveItem);
$this->entityManager->flush();
}
break;
case 'remove':
$updateItems = [];
foreach ($ReserveItems as $ReserveItem) {
$updateItem['serial_no'] = $ReserveItem->getProductClass()->getSerialNo();
$updateItem['quantity'] = $ReserveItem->getQuantity();
$updateItem['note'] = '予約注文キャンセルによる引き落とし';
$updateItems[] = $updateItem;
$this->entityManager->remove($ReserveItem);
$this->entityManager->flush();
}
$this->ecconnectfmService->updateFmProductStock($updateItems);
break;
}
log_info('予約演算処理終了', ['operation' => $operation, 'product_id' => $productId, 'product_class_id' => $productClassId]);
return $this->redirectToRoute('mypage_reserve');
}
/**
* カートに追加.
*
* @Route("/reserve/add_cart", name="reserve_add_cart", methods={"POST"})
*/
public function addCart(Request $request)
{
$requestData = $request->request->all();
if (
empty($requestData['product_id']) ||
empty($requestData['product_class_id']) ||
empty($requestData['quantity'])
) {
throw new NotFoundHttpException();
}
$Product = $this->productRepository->findWithSortedClassCategories($requestData['product_id']);
$targetProductClass = null;
foreach ($Product->getProductClasses() as $ProductClass) {
if ($ProductClass->getId() == $requestData['product_class_id']) {
$targetProductClass = $ProductClass;
}
}
if (empty($targetProductClass)) {
throw new NotFoundHttpException();
}
$builder = $this->formFactory->createNamedBuilder(
'',
AddCartType::class,
null,
[
'product' => $Product,
'id_add_product_id' => false,
],
);
$event = new EventArgs(
[
'builder' => $builder,
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE);
/* @var $form \Symfony\Component\Form\FormInterface */
$form = $builder->getForm();
log_info(
'カート追加処理開始',
[
'product_id' => $Product->getId(),
'product_class_id' => $requestData['product_class_id'],
'quantity' => $requestData['quantity'],
]
);
// カートへ追加
$this->cartService->addProduct($requestData['product_class_id'], $requestData['quantity']);
// 明細の正規化
$Carts = $this->cartService->getCarts();
foreach ($Carts as $Cart) {
$result = $this->purchaseFlow->validate($Cart, new PurchaseContext($Cart, $this->getUser()));
// 復旧不可のエラーが発生した場合は追加した明細を削除.
if ($result->hasError()) {
$this->cartService->removeProduct($requestData['product_class_id']);
foreach ($result->getErrors() as $error) {
$errorMessages[] = $error->getMessage();
}
}
foreach ($result->getWarning() as $warning) {
$errorMessages[] = $warning->getMessage();
}
}
$this->cartService->save();
log_info(
'カート追加処理完了',
[
'product_id' => $Product->getId(),
'product_class_id' => $requestData['product_class_id'],
'quantity' => $requestData['quantity'],
]
);
$event = new EventArgs(
[
'form' => $form,
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE);
if ($event->getResponse() !== null) {
return $event->getResponse();
}
// 不要になった予約商品を削除
$ReserveItems = $this->orderItemRepository->getReserveItems($this->getUser(), $Product, $targetProductClass);
foreach ($ReserveItems as $ReserveItem) {
$this->entityManager->remove($ReserveItem);
$this->entityManager->flush();
}
return $this->json(['done' => true]);
}
}