<?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 Eccube\Controller;
use Carbon\Carbon;
use Doctrine\Common\Collections\ArrayCollection;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\Category;
use Eccube\Entity\Customer;
use Eccube\Entity\CustomerAddress;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Entity\Master\ProductStatus;
use Eccube\Entity\Order;
use Eccube\Entity\Product;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Form\Type\AddCartType;
use Eccube\Form\Type\Master\ProductListMaxType;
use Eccube\Form\Type\Master\ProductListOrderByType;
use Eccube\Form\Type\SearchProductType;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\CategoryRepository;
use Eccube\Repository\CustomerFavoriteProductRepository;
use Eccube\Repository\Master\ProductListMaxRepository;
use Eccube\Repository\ProductRepository;
use Eccube\Service\CartService;
use Eccube\Repository\DeliveryFeeRepository;
use Eccube\Repository\DeliveryRepository;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\PurchaseFlow;
use Knp\Bundle\PaginatorBundle\Pagination\SlidingPagination;
use Knp\Component\Pager\Paginator;
use Plugin\Coupon4\Form\Type\CouponUseType;
use Plugin\Coupon4\Repository\CouponOrderRepository;
use Plugin\Coupon4\Repository\CouponRepository;
use Plugin\Coupon4\Service\CouponService;
use Plugin\EccubePaymentLite4\Repository\RegularDiscountRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Plugin\StripePaymentGateway\Repository\StripeConfigRepository;
use Eccube\Entity\ProductClass; //20220829 kikuzawa
use Eccube\Entity\Shipping;
use Eccube\Exception\ShoppingException;
use Eccube\Form\Type\AddCartByEmailType;
use Eccube\Form\Type\Front\CustomerAddressType;
use Eccube\Form\Type\Front\MyCardType;
use Eccube\Form\Type\Front\ShoppingShippingType;
use Eccube\Form\Type\Shopping\CustomerAddressOneTouchType;
use Eccube\Repository\CartRepository;
use Eccube\Repository\OrderRepository;
use Plugin\ProductOption\Entity\Option; //20220829 kikuzawa
use Plugin\ProductOption\Service\ProductOptionCartService; //20220829 kikuzawa
use Eccube\Repository\CustomerRepository; //20220812 kikuzawa
use Eccube\Repository\CustomerAddressRepository; //20220812 kikuzawa
use Eccube\Service\MailService;
use Eccube\Service\OneTouchService;
use Eccube\Service\OrderHelper;
use Eccube\Service\Payment\PaymentDispatcher;
use Eccube\Service\Payment\PaymentMethodInterface;
use Eccube\Service\ProductReviewService;
use Exception;
use Plugin\ProductReview4\Entity\ProductReview;
use Plugin\ProductReview4\Repository\ProductReviewRepository;
use Plugin\StripePaymentGateway\Entity\StripeCustomer;
use Plugin\StripePaymentGateway\StripeClient;
use Plugin\StripeRec\Service\Method\StripeRecurringNagMethod;
use Psr\Container\ContainerInterface;
use Stripe\PaymentMethod;
use Stripe\Customer as StripeLibCustomer;
use Symfony\Component\Asset\Packages;
use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy;
use Symfony\Component\Form\Test\FormInterface;
use Symfony\Component\Validator\Constraints\Length;
use function Plugin\get;
class ProductController extends AbstractController
{
/**
* @var PurchaseFlow
*/
protected $purchaseFlow;
/**
* @var PurchaseFlow
*/
protected $shoppingPurchaseFlow;
/**
* @var MailService
*/
protected $mailService;
/**
* @var CustomerFavoriteProductRepository
*/
protected $customerFavoriteProductRepository;
/**
* @var CartService
*/
protected $cartService;
/**
* @var ProductRepository
*/
protected $productRepository;
/**
* @var BaseInfo
*/
protected $BaseInfo;
/**
* @var AuthenticationUtils
*/
protected $helper;
/**
* @var ProductListMaxRepository
*/
protected $productListMaxRepository;
/**
* @var OrderHelper
*/
protected $orderHelper;
/**
* @var DeliveryFeeRepository
*/
protected $deliveryFeeRepository;
/**
* @var DeliveryRepository
*/
protected $deliveryRepository;
/**
* @var CartRepository
*/
protected $cartRepository;
/**
* @var OrderRepository
*/
protected $orderRepository;
private $title = '';
protected $stripeConfigRepository;
//20220812 kikuzawa
protected $customerRepository;
protected $customerAddressRepository;
protected $container;
private $em;
protected $stripeCustomerRepository;
/**
* @var CategoryRepository
*/
protected $categoryRepository;
/**
* @var RegularDiscountRepository
*/
protected $regularDiscountRepository;
/**
* @var CouponService
*/
protected $couponService;
/**
* @var CouponRepository
*/
protected $couponRepository;
/**
* @var CouponOrderRepository
*/
protected $couponOrderRepository;
protected $packages;
protected $productReviewRepository;
protected $productReviewService;
protected $OnetouchService;
/**
* ProductController constructor.
*
* @param PurchaseFlow $cartPurchaseFlow
* @param CustomerFavoriteProductRepository $customerFavoriteProductRepository
* @param CartService $cartService
* @param ProductRepository $productRepository
* @param BaseInfoRepository $baseInfoRepository
* @param AuthenticationUtils $helper
* @param ProductListMaxRepository $productListMaxRepository
*/
public function __construct(
PurchaseFlow $cartPurchaseFlow,
CustomerFavoriteProductRepository $customerFavoriteProductRepository,
// CartService $cartService,
ProductRepository $productRepository,
BaseInfoRepository $baseInfoRepository,
AuthenticationUtils $helper,
CustomerRepository $customerRepository, //20220812 kikuzawa
CustomerAddressRepository $customerAddressRepository,
ProductOptionCartService $cartService, //20220812 kikuzawa
ProductListMaxRepository $productListMaxRepository,
ContainerInterface $container,
OrderHelper $orderHelper,
MailService $mailService,
StripeConfigRepository $stripeConfigRepository,
DeliveryFeeRepository $deliveryFeeRepository,
DeliveryRepository $deliveryRepository,
CartRepository $cartRepository,
OrderRepository $orderRepository,
PurchaseFlow $shoppingPurchaseFlow,
CategoryRepository $categoryRepository,
RegularDiscountRepository $regularDiscountRepository,
CouponService $couponService,
CouponRepository $couponRepository,
CouponOrderRepository $couponOrderRepository,
Packages $packages,
ProductReviewRepository $productReviewRepository,
ProductReviewService $productReviewService,
OneTouchService $OnetouchService
) {
$this->purchaseFlow = $cartPurchaseFlow;
$this->customerFavoriteProductRepository = $customerFavoriteProductRepository;
$this->cartService = $cartService;
$this->mailService = $mailService;
$this->productRepository = $productRepository;
$this->BaseInfo = $baseInfoRepository->get();
$this->helper = $helper;
$this->productListMaxRepository = $productListMaxRepository;
$this->container = $container;
$this->em = $container->get('doctrine.orm.entity_manager');
$this->stripeCustomerRepository = $this->em->getRepository(StripeCustomer::class);
$this->deliveryFeeRepository = $deliveryFeeRepository;
$this->deliveryRepository = $deliveryRepository;
$this->orderHelper = $orderHelper;
$this->cartRepository = $cartRepository;
$this->orderRepository = $orderRepository;
$this->stripeConfigRepository = $stripeConfigRepository;
$this->customerRepository = $customerRepository; //20220812 kikuzawa
$this->customerAddressRepository = $customerAddressRepository; //20220812 kikuzawa
$this->shoppingPurchaseFlow = $shoppingPurchaseFlow;
$this->categoryRepository = $categoryRepository;
$this->regularDiscountRepository = $regularDiscountRepository;
$this->couponService = $couponService;
$this->couponRepository = $couponRepository;
$this->couponOrderRepository = $couponOrderRepository;
$this->packages = $packages;
$this->productReviewRepository = $productReviewRepository;
$this->productReviewService = $productReviewService;
$this->OnetouchService = $OnetouchService;
}
/**
* 商品一覧画面.
*
* @Route("/products/list", name="product_list")
* @Template("Product/list.twig")
*/
public function index(Request $request, Paginator $paginator)
{
$Customer = $this->getUser();
// Doctrine SQLFilter
if ($this->BaseInfo->isOptionNostockHidden()) {
$this->entityManager->getFilters()->enable('option_nostock_hidden');
}
// handleRequestは空のqueryの場合は無視するため
if ($request->getMethod() === 'GET') {
$request->query->set('pageno', $request->query->get('pageno', ''));
}
// searchForm
/* @var $builder \Symfony\Component\Form\FormBuilderInterface */
$builder = $this->formFactory->createNamedBuilder('', SearchProductType::class);
if ($request->getMethod() === 'GET') {
$builder->setMethod('GET');
}
$event = new EventArgs(
[
'builder' => $builder,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_INITIALIZE, $event);
/* @var $searchForm \Symfony\Component\Form\FormInterface */
$searchForm = $builder->getForm();
$searchForm->handleRequest($request);
// paginator
$searchData = $searchForm->getData();
if($Customer){
if ($Customer->getIsSupplier() === true) {
$qb = $this->productRepository->getQueryBuilderBySearchData($searchData, $Customer->getOwnerRank(), true);
} else {
$qb = $this->productRepository->getQueryBuilderBySearchData($searchData, $Customer->getOwnerRank());
}
}else{
$qb = $this->productRepository->getQueryBuilderBySearchData($searchData);
}
$event = new EventArgs(
[
'searchData' => $searchData,
'qb' => $qb,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_SEARCH, $event);
$searchData = $event->getArgument('searchData');
$query = $qb->getQuery()
->useResultCache(true, $this->eccubeConfig['eccube_result_cache_lifetime_short']);
/** @var SlidingPagination $pagination */
$pagination = $paginator->paginate(
$query,
!empty($searchData['pageno']) ? $searchData['pageno'] : 1,
!empty($searchData['disp_number']) ? $searchData['disp_number']->getId() : $this->productListMaxRepository->findOneBy([], ['sort_no' => 'ASC'])->getId()
);
// if (isset($searchData['category_id']) && $searchData['category_id']) {
// // カテゴリ表示時は全て表示
// $pagination = $paginator->paginate($query,1,99);
// } else {
// // BEST OF BEST表示時は4件のみ
// $pagination = $paginator->paginate($query,1,4);
// }
$ids = [];
$ReviewAveList = array();
$ReviewCntList = array();
foreach ($pagination as $Product) {
$ids[] = $Product->getId();
$rate = $this->entityManager->getRepository('Plugin\ProductReview4\Entity\ProductReview')->getAvgAll($Product);
$ReviewAveList[$Product->getId()] = round($rate['recommend_avg']);
$ReviewCntList[$Product->getId()] = intval($rate['review_count']);
}
$ProductsAndClassCategories = $this->productRepository->findProductsWithSortedClassCategories($ids, 'p.id');
// addCart form
$forms = [];
foreach ($pagination as $Product) {
/* @var $builder \Symfony\Component\Form\FormBuilderInterface */
$builder = $this->formFactory->createNamedBuilder(
'',
AddCartType::class,
null,
[
'product' => $ProductsAndClassCategories[$Product->getId()],
'allow_extra_fields' => true,
]
);
$addCartForm = $builder->getForm();
$forms[$Product->getId()] = $addCartForm->createView();
}
// 表示件数
$builder = $this->formFactory->createNamedBuilder(
'disp_number',
ProductListMaxType::class,
null,
[
'required' => false,
'allow_extra_fields' => true,
]
);
if ($request->getMethod() === 'GET') {
$builder->setMethod('GET');
}
$event = new EventArgs(
[
'builder' => $builder,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_DISP, $event);
$dispNumberForm = $builder->getForm();
$dispNumberForm->handleRequest($request);
// ソート順
$builder = $this->formFactory->createNamedBuilder(
'orderby',
ProductListOrderByType::class,
null,
[
'required' => false,
'allow_extra_fields' => true,
]
);
if ($request->getMethod() === 'GET') {
$builder->setMethod('GET');
}
$event = new EventArgs(
[
'builder' => $builder,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_INDEX_ORDER, $event);
$orderByForm = $builder->getForm();
$orderByForm->handleRequest($request);
$Category = $searchForm->get('category_id')->getData();
if (!isset($searchForm->getData()['name'])) {
$items = $pagination->getItems();
$filteredItems = array_filter($items, function ($product) {
return $product['id'] !== 1543;
});
$pagination->setItems($filteredItems);
}
return [
'subtitle' => $this->getPageTitle($searchData),
'pagination' => $pagination,
'search_form' => $searchForm->createView(),
'disp_number_form' => $dispNumberForm->createView(),
'order_by_form' => $orderByForm->createView(),
'forms' => $forms,
'Category' => $Category,
'ReviewAveList' => $ReviewAveList,
'ReviewCntList' => $ReviewCntList,
];
}
/**
* 商品一覧画面.
*
* @Route("/products/category/{id}", name="product_category")
*/
public function listCategory(Request $request, Category $category)
{
$searchData = [
'category_id' => $category
];
$productCategoriesQuery = $this->productRepository->getQueryBuilderBySearchData($searchData);
$productCategories = $productCategoriesQuery->getQuery()->getResult();
if ($productCategories !== null && count($productCategories) > 0) {
foreach ($productCategories as $Product) {
$rate = $this->productReviewService->getReview($Product);
$reg_price = 0;
if($Product->hasProductClass()) {
$reg_price = $Product->getPrice02IncTaxMin();
} else {
$reg_price = $Product->getPrice02IncTaxMin();
}
if ($Product->getProductClasses()[0]->getRegularDiscount() && $Product->getProductClasses()[0]->getRegularDiscount()->getDiscountRate() > 0) {
$price = $reg_price - $reg_price * $Product->getProductClasses()[0]->getRegularDiscount()->getDiscountRate() / 100;
}
$tags = $this->productRepository->getProductTags($Product->getId());
$tagName = !empty($tags) ? $tags[0]['name'] : null;
$product[] = [
'id' => $Product->getId(),
'name' => $Product->getName(),
'product_class' => $Product->getProductClasses()[0]->getId(),
'price_discount' => $price ?? 0,
'price' => $reg_price,
'discount_rate' => $Product->getProductClasses()[0]->getRegularDiscount() ? $Product->getProductClasses()[0]->getRegularDiscount()->getDiscountRate() : 0,
'image' => $Product->getMainListImage() ? $Product->getMainListImage()->getFileName() : null,
'star' => round($rate['RecommendAvg'], 1),
'reviewCount' => intval($rate['ReviewCntList']),
'tagName' => $tagName,
];
}
}
return $this->json($product);
}
/**
* 商品詳細画面.
* @Route("/products/detail/{id}", name="product_detail_old", methods={"GET"})
* @Route("/products/{id}/{slug}", name="product_detail", methods={"GET"})
* @Template("Product/detail.twig")
* @ParamConverter("Product", options={"repository_method" = "findWithSortedClassCategories"})
*
* @param Request $request
* @param Product $Product
*
* @return array
*/
public function detail(Request $request, Product $Product,$slug = null)
{
$ChangeCustomer = $this->session->get('PRODUCT_DETAIL_REGULAR') ?? $this->session->get('PRODUCT_DETAIL') ?? 0;
if ($request->attributes->get('_route') === 'product_detail_old') {
$slug = $Product->getSlug();
return $this->redirectToRoute('product_detail', ['id' => $Product->getId(), 'slug' => $slug]);
}
if(!$Product->getIsVariant() && $slug !== $Product->getSlug()) {
return $this->redirectToRoute('product_detail', ['id' => $Product->getId(), 'slug' => $Product->getSlug()]);
}
$Customer = null;
$LastOrder = [];
if ($this->isGranted('ROLE_USER')) {
$Customer = $this->getUser();
$is_favorite = $this->customerFavoriteProductRepository->isFavorite($Customer, $Product);
$LastOrder = $this->productRepository->getCountProductOrder($Product->getId(),$Customer->getId());
}
$ProductVariant = $this->productRepository->findVariantsByProductId($Product->getId());
if ($ProductVariant) {
$url = '/products/'.$ProductVariant->getId().'?s='.$Product->getId().'/'.$Product->getSlug();
return $this->redirect($url);
}
if ((!$this->getUser() && !$this->session->get("IS_SUPPLIER")) || ($this->getUser() && !$this->getUser()->getIsSupplier())) {
if ($this->handlerSupplierProduct($Product)) {
return $this->redirectToRoute('salon-suppliers');
}
}
if (!$this->checkVisibility($Product)) {
throw new NotFoundHttpException();
}
if ($this->session->get('PRODUCT_DETAIL')) {
$this->session->remove('PRODUCT_DETAIL');
}
$builder = $this->formFactory->createNamedBuilder(
'',
AddCartType::class,
null,
[
'product' => $Product,
'id_add_product_id' => false,
]
);
$event = new EventArgs(
[
'builder' => $builder,
'Product' => $Product,
],
$request
);
$Customer = null;
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE, $event);
$is_favorite = false;
if ($this->isGranted('ROLE_USER')) {
$Customer = $this->getUser();
$is_favorite = $this->customerFavoriteProductRepository->isFavorite($Customer, $Product);
}
//お気に入り数の合計を取得 20211127 kikuzawa
$favorite_total = 0;
$favorite_total = $this->customerFavoriteProductRepository->getFavoriteTotal($Product);
$user_id = "";
$Customer = $this->getUser();
$Customer = null;
$productRegularDiscounts = null;
if ($Product) {
$productRegular = $Product->getRegularProduct();
if ($productRegular){
$productRegularDiscount = $productRegular->getProductClasses()[0]->getRegularDiscount();
if ($productRegularDiscount) {
$productRegularDiscounts = $this->regularDiscountRepository->findBy([
'discount_id' => $productRegularDiscount->getDiscountId()
]);
}
}
}
$saleType = null;
if ($this->isGranted('ROLE_USER')) {
$Customer = $this->getUser();
$StripeCustomerData = $this->OnetouchService->getCustomerStripeOnetouch($Customer, $Product);
$productRegularDiscounts = $StripeCustomerData['productRegularDiscounts'] ?? null;
$saleType = $Product['ProductClasses'][0]->getSaleType()->getId();
}
$ship = null;
$DeliveryFreeAmount = $this->BaseInfo->getDeliveryFreeAmount();
//
if($Product->getOwnerProductId()){
// ダイヤモンド会員向けの商品ページは非表示、通常商品ページにリダイレクト
return $this->redirectToRoute('product_detail', ["id"=>$Product->getOwnerProductId()]);
}
$RankProduct = null;
if($Product->getRankPrice()){
// ダイヤモンド会員向けの商品情報の取得
$RankProduct = $this->productRepository->findOneBy(["owner_product_id"=>$Product->getId()]);
}
$s = $request->get('s');
if ($s) {
$VariantChild = explode('/', $s)[0];
}
$defaultSelect = $VariantChild ?? 0;
$this->session->remove('PRODUCT_DETAIL');
$this->session->remove('PRODUCT_DETAIL_REGULAR');
$Product->setPageViews($Product->getPageViews() + 1);
$this->entityManager->persist($Product);
$this->entityManager->flush();
$faqs = $this->productRepository->parseFAQs($Product->getLlmoFaq());
return [
'title' => $this->title,
'subtitle' => $Product->getName(),
'form' => $builder->getForm()->createView(),
'Product' => $Product,
'is_favorite' => $is_favorite,
'favorite_total' => $favorite_total, //お気に入り数の合計を取得 20211127 kikuzawa
'user_id' => $user_id,
'Customer' => $Customer,
'RankProduct' => $RankProduct,
'productRegularDiscounts' => $productRegularDiscounts,
'LastOrder' =>$LastOrder,
'IsLightVersion' => $this->BaseInfo->getIsLightVersion(),
"defaultSelect"=> $defaultSelect,
'Sale_type' => $saleType,
'ChangeCustomer' => $ChangeCustomer,
'faqs' => $faqs,
];
}
/**
* お気に入り追加.
*
* @Route("/products/add_favorite/{id}", name="product_add_favorite", requirements={"id" = "\d+"})
*/
public function addFavorite(Request $request, Product $Product)
{
$this->checkVisibility($Product);
$event = new EventArgs(
[
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_INITIALIZE, $event);
if ($this->isGranted('ROLE_USER')) {
$Customer = $this->getUser();
$this->customerFavoriteProductRepository->addFavorite($Customer, $Product);
$this->session->getFlashBag()->set('product_detail.just_added_favorite', $Product->getId());
$event = new EventArgs(
[
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE, $event);
if ($request->get("supplier_page")) {
return $this->json(['status' => 'success', 'message' => '商品はお気に入りに保存されました']);
}
return $this->redirectToRoute('product_detail', ['id' => $Product->getId()]);
} else {
// 非会員の場合、ログイン画面を表示
// ログイン後の画面遷移先を設定
$this->setLoginTargetPath($this->generateUrl('product_add_favorite', ['id' => $Product->getId()]));
$this->session->getFlashBag()->set('eccube.add.favorite', true);
$event = new EventArgs(
[
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_FAVORITE_ADD_COMPLETE, $event);
return $this->redirectToRoute('mypage_login');
}
}
/**
* カートに追加.
*
* @Route("/products/add_cart/{id}", name="product_add_cart", methods={"POST","GET"}, requirements={"id" = "\d+"})
*/
//app/Plugin/ProductOption/Controller/AddcartController.phpの内容を移植 20220829 kikuzawa
public function addCart(Request $request, Product $Product)
{
// エラーメッセージの配列
$errorMessages = [];
if (!$this->checkVisibility($Product)) {
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(EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE, $event);
/* @var $form \Symfony\Component\Form\FormInterface */
$form = $builder->getForm();
$form->handleRequest($request);
//送り先のメールアドレス(option1)が会員情報に存在するかチェック 20220812 kikuzawa
if (isset($form->all()['productoption1'])) {
$recipientEmail = $form->get('productoption1')->getData();
if ($recipientEmail) {
$customer = $this->customerRepository->findBy(array('email' => $recipientEmail));
if (!$customer) {
$errorMessages[] = '存在しないメールアドレスです。';
}
}
}
if (!$form->isValid()) {
foreach ($form->all() as $child) {
$config = $child->getConfig();
foreach ($child->getErrors() as $error) {
$errorMessages[] = $config->getOption('label') . ':' . $error->getMessage();
}
}
}
$addCartData = $form->getData();
$ProductClass = $this->entityManager->getRepository(ProductClass::class)->find($addCartData['product_class_id']);
$limit = $ProductClass->getSaleLimit();
if (!$ProductClass->isStockUnlimited()) {
$stock = $ProductClass->getStock();
}
if (!is_null($limit) || isset($stock)) {
$Carts = $this->cartService->getCarts();
$quantity = $addCartData['quantity'];
foreach ($Carts as $Cart) {
foreach ($Cart->getCartItems() as $item) {
if ($item->getProductClass()->getId() == $ProductClass->getId()) $quantity += $item->getQuantity();
}
}
$productName = $ProductClass->getProduct()->getName();
if ($ProductClass->hasClassCategory1()) {
$productName .= ' - ' . $ProductClass->getClassCategory1()->getName();
}
if ($ProductClass->hasClassCategory2()) {
$productName .= ' - ' . $ProductClass->getClassCategory2()->getName();
}
if (!is_null($limit) && $limit < $quantity) {
$errorMessages[] = trans('front.shopping.over_sale_limit', ['%product%' => $productName]);
}
if (isset($stock) && $stock < $quantity) {
$errorMessages[] = trans('front.shopping.out_of_stock', ['%product%' => $productName]);
}
}
if (count($errorMessages) == 0) {
log_info(
'カート追加処理開始',
[
'product_id' => $Product->getId(),
'product_class_id' => $addCartData['product_class_id'],
'quantity' => $addCartData['quantity'],
]
);
// カートへ追加
$ProductOptions = $Product->getProductOptions();
$Options = [];
foreach ($ProductOptions as $ProductOption) {
$Option = $ProductOption->getOption();
$option_key = 'productoption' . $Option->getId();
$value = $form->get($option_key)->getData();
if ($Option) {
$add = true;
if ($Option->getType() == Option::SELECT_TYPE || $Option->getType() == Option::RADIO_TYPE) {
if ($Option->getDisableCategory()) {
if ($Option->getDisableCategory() == $value) {
$add = false;
}
}
$value = $value->getId();
if (strlen($value) == 0) $add = false;
} elseif ($Option->getType() == Option::TEXT_TYPE || $Option->getType() == Option::TEXTAREA_TYPE || $Option->getType() == Option::NUMBER_TYPE) {
if (strlen($value) == 0) $add = false;
} elseif ($Option->getType() == Option::CHECKBOX_TYPE) {
if (count($value) == 0) {
$add = false;
} else {
$buff = $value;
$value = [];
foreach ($buff as $categoryoption) {
$value[] = $categoryoption->getId();
}
}
} elseif ($Option->getType() == Option::DATE_TYPE) {
if (is_null($value)) $add = false;
}
if ($add) {
if (is_array($value)) {
$Options[$Option->getId()] = $value;
} elseif (is_object($value)) {
$Options[$Option->getId()] = $value->format('Y-m-d');
} else {
$Options[$Option->getId()] = (string)$value;
}
}
}
}
$this->cartService->addProductOption($addCartData['product_class_id'], $Options, $addCartData['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($addCartData['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' => $addCartData['product_class_id'],
'quantity' => $addCartData['quantity'],
]
);
$event = new EventArgs(
[
'form' => $form,
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE, $event);
}
if ($event->getResponse() !== null) {
return $event->getResponse();
}
if ($request->isXmlHttpRequest()) {
// ajaxでのリクエストの場合は結果をjson形式で返す。
// 初期化
$done = null;
$messages = [];
if (empty($errorMessages)) {
// エラーが発生していない場合
$done = true;
array_push($messages, trans('front.product.add_cart_complete'));
} else {
// エラーが発生している場合
$done = false;
$messages = $errorMessages;
}
$Customer = $this->getUser();
$Point = $this->getPointCart($Cart, $Customer);
$Cart = $this->cartService->getCart();
$quantity = 0;
$Total = 0;
foreach ($Carts as $Cart) {
foreach ($Cart->getCartItems() as $item) {
if ($item->getProductClass()->getId() == $ProductClass->getId()){
$quantity = $item->getQuantity();
}
}
$Total = $Total + $Cart->getTotalPrice();
}
return $this->json(['done' => $done, 'messages' => $messages, 'total_price' => number_format($Total), 'add_point' => $Point, 'product_class_id' => $ProductClass->getId(), 'quantity' => $quantity]);
} else {
// ajax以外でのリクエストの場合はカート画面へリダイレクト
if (empty($errorMessages)) {
return $this->redirectToRoute('cart');
} else {
foreach ($errorMessages as $errorMessage) {
$this->addRequestError($errorMessage);
}
return $this->redirect($request->headers->get('referer'));
}
}
}
/**
* ページタイトルの設定
*
* @param null|array $searchData
*
* @return str
*/
protected function getPageTitle($searchData)
{
if (isset($searchData['name']) && !empty($searchData['name'])) {
return trans('front.product.search_result');
} elseif (isset($searchData['category_id']) && $searchData['category_id']) {
return $searchData['category_id']->getName();
} else {
return trans('front.product.all_products');
}
}
/**
* 閲覧可能な商品かどうかを判定
*
* @param Product $Product
*
* @return boolean 閲覧可能な場合はtrue
*/
protected function checkVisibility(Product $Product)
{
$is_admin = $this->session->has('_security_admin');
// 管理ユーザの場合はステータスやオプションにかかわらず閲覧可能.
if (!$is_admin) {
// 在庫なし商品の非表示オプションが有効な場合.
// if ($this->BaseInfo->isOptionNostockHidden()) {
// if (!$Product->getStockFind()) {
// return false;
// }
// }
// 公開ステータスでない商品は表示しない.
if ($Product->getStatus()->getId() !== ProductStatus::DISPLAY_SHOW) {
return false;
}
}
return true;
}
/**
* カートに追加.
*
* @Route("/products/one_touch_payment/{id}", name="one_touch_payment", methods={"POST"}, requirements={"id" = "\d+"})
* @Template("Product/detail.twig")
*/
public function oneTouchPayment(Request $request, Product $Product)
{
// エラーメッセージの配列
$errorMessages = [];
if (!$this->checkVisibility($Product)) {
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(EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE, $event);
/* @var $form \Symfony\Component\Form\FormInterface */
$form = $builder->getForm();
$form->handleRequest($request);
//送り先のメールアドレス(option1)が会員情報に存在するかチェック 20220812 kikuzawa
if (isset($form->all()['productoption1'])) {
$recipientEmail = $form->get('productoption1')->getData();
if ($recipientEmail) {
$customer = $this->customerRepository->findBy(array('email' => $recipientEmail));
if (!$customer) {
$errorMessages[] = '存在しないメールアドレスです。';
}
}
}
if (!$form->isValid()) {
foreach ($form->all() as $child) {
$config = $child->getConfig();
foreach ($child->getErrors() as $error) {
$errorMessages[] = $config->getOption('label') . ':' . $error->getMessage();
}
}
}
$addCartData = $form->getData();
$ProductClass = $this->entityManager->getRepository(ProductClass::class)->find($addCartData['product_class_id']);
$limit = $ProductClass->getSaleLimit();
if (!$ProductClass->isStockUnlimited()) {
$stock = $ProductClass->getStock();
}
if (!is_null($limit) || isset($stock)) {
$Carts = $this->cartService->getCarts();
$quantity = $addCartData['quantity'];
foreach ($Carts as $Cart) {
foreach ($Cart->getCartItems() as $item) {
if ($item->getProductClass()->getId() == $ProductClass->getId()) $quantity += $item->getQuantity();
}
}
$productName = $ProductClass->getProduct()->getName();
if ($ProductClass->hasClassCategory1()) {
$productName .= ' - ' . $ProductClass->getClassCategory1()->getName();
}
if ($ProductClass->hasClassCategory2()) {
$productName .= ' - ' . $ProductClass->getClassCategory2()->getName();
}
if (!is_null($limit) && $limit < $quantity) {
$errorMessages[] = trans('front.shopping.over_sale_limit', ['%product%' => $productName]);
}
if (isset($stock) && $stock < $quantity) {
$errorMessages[] = trans('front.shopping.out_of_stock', ['%product%' => $productName]);
}
}
$oneTouchPaymentCart = null;
if (count($errorMessages) == 0) {
log_info(
'カート追加処理開始',
[
'product_id' => $Product->getId(),
'product_class_id' => $addCartData['product_class_id'],
'quantity' => $addCartData['quantity'],
]
);
// カートへ追加
$ProductOptions = $Product->getProductOptions();
$Options = [];
foreach ($ProductOptions as $ProductOption) {
$Option = $ProductOption->getOption();
$option_key = 'productoption' . $Option->getId();
$value = $form->get($option_key)->getData();
if ($Option) {
$add = true;
if ($Option->getType() == Option::SELECT_TYPE || $Option->getType() == Option::RADIO_TYPE) {
if ($Option->getDisableCategory()) {
if ($Option->getDisableCategory() == $value) {
$add = false;
}
}
$value = $value->getId();
if (strlen($value) == 0) $add = false;
} elseif ($Option->getType() == Option::TEXT_TYPE || $Option->getType() == Option::TEXTAREA_TYPE || $Option->getType() == Option::NUMBER_TYPE) {
if (strlen($value) == 0) $add = false;
} elseif ($Option->getType() == Option::CHECKBOX_TYPE) {
if (count($value) == 0) {
$add = false;
} else {
$buff = $value;
$value = [];
foreach ($buff as $categoryoption) {
$value[] = $categoryoption->getId();
}
}
} elseif ($Option->getType() == Option::DATE_TYPE) {
if (is_null($value)) $add = false;
}
if ($add) {
if (is_array($value)) {
$Options[$Option->getId()] = $value;
} elseif (is_object($value)) {
$Options[$Option->getId()] = $value->format('Y-m-d');
} else {
$Options[$Option->getId()] = (string)$value;
}
}
}
}
$this->cartService->addProductOption($addCartData['product_class_id'], $Options, $addCartData['quantity']);
// 明細の正規化
$Carts = $this->cartService->getCarts();
foreach ($Carts as $Cart) {
$cartItems = $Cart->getCartItems();
$isOneTouchPayment = $cartItems[0]->getIsOneTouchPayment();
if ($isOneTouchPayment) {
$oneTouchPaymentCart = $cartItems[0]->getCart();
}
$result = $this->purchaseFlow->validate($Cart, new PurchaseContext($Cart, $this->getUser()));
// 復旧不可のエラーが発生した場合は追加した明細を削除.
if ($result->hasError()) {
$this->cartService->removeProduct($addCartData['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' => $addCartData['product_class_id'],
'quantity' => $addCartData['quantity'],
]
);
$event = new EventArgs(
[
'form' => $form,
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE, $event);
}
if ($event->getResponse() !== null) {
return $event->getResponse();
}
// ajaxでのリクエストの場合は結果をjson形式で返す。
// 初期化
$done = null;
$messages = [];
$Customer = $this->getUser();
if (empty($errorMessages) && $oneTouchPaymentCart && $Customer) {
// エラーが発生していない場合
$done = true;
try {
$Order = $this->orderHelper->initializeOrder($oneTouchPaymentCart, $Customer);
$this->executePurchaseFlow($Order, false);
if ($Customer->getId()) {
$this->orderHelper->updateCustomerInfo($Order, $Customer);
$trial = $Customer->getTrialFamilyDate();
if ($trial) {
$date = Carbon::parse($trial->format('Y-m-d H:i:s'));
$now = Carbon::now();
$diff = $date->diffInMonths($now);
if ($diff < 1) {
$Order->setPaymentTotal($Order->getPaymentTotal() - $Order->getDeliveryFeeTotal());
$Order->setTotal($Order->getTotal() - $Order->getDeliveryFeeTotal());
$Order->setDeliveryFeeTotal(0);
}
}
$this->entityManager->persist($Order);
$this->entityManager->flush($Order);
}
$Shipping = $Order->getShippings()[0];
$ShippingData = [
'id' => $Shipping->getId(),
'name01' => $Shipping->getName01(),
'name02' => $Shipping->getName02(),
'kana01' => $Shipping->getKana01(),
'kana02' => $Shipping->getKana02(),
'postal_code' => $Shipping->getPostalCode(),
'pref' => $Shipping->getPref()->getName(),
'addr01' => $Shipping->getAddr01(),
'addr02' => $Shipping->getAddr02(),
'phone_number' => $Shipping->getPhoneNumber(),
];
$regularDiscount = $Order->getOrderItems()[0]->getProduct()->getProductClasses()[0]->getRegularDiscount();
$discountSecond = array();
if ($regularDiscount) {
$discountFirst = $this->regularDiscountRepository->find($Order->getOrderItems()[0]->getProduct()->getProductClasses()[0]->getRegularDiscount()->getId());
$discountSecond = $this->regularDiscountRepository->findDiscountById($discountFirst->getDiscountId());
}
$OrderData = [
'payment_total' => $Order->getPaymentTotal(),
'delivery_fee_total' => $Order->getDeliveryFeeTotal(),
'order_id' => $Order->getId(),
'discount' => $Order->getDiscount(),
'shipping' => $ShippingData,
'product_name' => $Order->getOrderItems()[0]->getProduct()->getName() ?? null,
'main_image' => $Order->getOrderItems()[0]->getProduct()->getMainFileName() ? $this->packages->getUrl($Order->getOrderItems()[0]->getProduct()->getMainListImage(),'save_image') : $this->packages->getUrl('no_image_product.png','save_image'),
'discount_rate' => $Order->getOrderItems()[0]->getProduct()->getProductClasses()[0]->getRegularDiscount() ? $Order->getOrderItems()[0]->getProduct()->getProductClasses()[0]->getRegularDiscount()->getDiscountRate() : 0,
'price' => $Order->getOrderItems()[0]->getProduct()->getPrice02IncTaxMax() ?? null,
'pt' => $this->get_point($Order->getPaymentTotal(), false) ?? null,
'pt_family_benefits' => $this->get_point($Order->getPaymentTotal(), true) ?? null,
'discount_second' => count($discountSecond) > 1 ? $discountSecond[1]->getDiscountRate() : 0,
'sale_type' => $Order->getOrderItems()[0]->getProduct()->getProductClasses()[0]->getSaletype()->getName() == "定期商品",
'add_point' => number_format($Order->getAddPoint()),
'subtotal' => $Order->getSubtotal(),
'quantity' => $Order->getOrderItems()->first()->getQuantity(),
];
$this->cartService->removeCart($oneTouchPaymentCart);
return $this->json([
'Order' => $OrderData,
'done' => true,
]);
} catch (\Exception $e) {
if ($oneTouchPaymentCart) {
$this->cartService->removeCart($oneTouchPaymentCart);
}
$this->entityManager->rollback();
$this->addError('front.shopping.system_error');
return $this->json(['done' => false, 'messages' => $messages]);;
}
} else {
if ($oneTouchPaymentCart) {
$this->cartService->removeCart($oneTouchPaymentCart);
}
// エラーが発生している場合
$done = false;
$messages = $errorMessages;
foreach ($messages as $message) {
$this->addError($message);
}
}
return $this->json(['done' => $done, 'messages' => $messages]);
}
/**
* カートに追加.
*
* @Route("/products/show_shipping/{id}", name="show_shipping", methods={"POST"}, requirements={"id" = "\d+"})
* @Template("Product/detail.twig")
*/
public function showListShipping(Request $request, Shipping $Shipping)
{
$messages = [];
$Customer = $this->getUser();
try {
/** @var Customer $Customer */
$CustomerAddress = new CustomerAddress();
$CustomerAddress->setFromCustomer($Customer);
$Addresses = array_merge([$CustomerAddress], $Customer->getCustomerAddresses()->toArray());
$ShippingDatas = [];
foreach ($Addresses as $key => $address) {
$default = '';
if ($key == 0) {
$default = 'checked';
}
$ShippingDatas[] = [
'id' => $address->getId(),
'name01' => $address->getName01(),
'name02' => $address->getName02(),
'kana01' => $address->getKana01(),
'kana02' => $address->getKana02(),
'postal_code' => $address->getPostalCode(),
'pref' => $address->getPref()->getName(),
'addr01' => $address->getAddr01(),
'addr02' => $address->getAddr02(),
'phone_number' => $address->getPhoneNumber(),
'default' => $default
];
}
return $this->json(['done' => false, 'messages' => $messages,'Shippings' => $ShippingDatas] );
} catch (\Exception $e) {
$this->entityManager->rollback();
$this->addError('front.shopping.system_error');
return $this->json(['done' => false, 'messages' => $messages]);
}
}
/**
* カートに追加.
*
* @Route("/products/show_card/{id}", name="show_card", methods={"POST"}, requirements={"id" = "\d+"})
* @Template("Product/detail.twig")
*/
public function showListCard(Request $request, Customer $Customer)
{
$messages = [];
$dataCards = [];
$Customer = $this->getUser();
$cards = new ArrayCollection();
$defaultPayment = null;
$StripeCustomer=$this->stripeCustomerRepository->findOneBy(array('Customer'=>$Customer));
try {
if ($StripeCustomer) {
$StripeCustomerId = $StripeCustomer->getStripeCustomerId();
$paymentMethod = StripeLibCustomer::retrieve($StripeCustomerId);
if ($StripeCustomerId) {
$cards = PaymentMethod::all([
'customer' => $StripeCustomerId,
'type' => 'card',
]);
$cards = new ArrayCollection($cards->data);
};
if ($request->get('stripe_payment_method_id')) {
$defaultPayment = $request->get('stripe_payment_method_id');
}
else{
if ($paymentMethod['invoice_settings']['default_payment_method']) {
$defaultPayment = $paymentMethod['invoice_settings']['default_payment_method'];
}else{
$defaultPayment = $cards[0]['id'];
}
}
}
foreach ($cards as $key => $card) {
$default = "";
if ($defaultPayment == $card['id']) {
$default = "checked";
}
$dataCards[] = [
'id' => $card['id'],
'brand' => $card['card']['brand'],
'exp_month' => $card['card']['exp_month'],
'exp_year' => $card['card']['exp_year'],
'last4' => $card['card']['last4'],
'default' => $default
];
}
return $this->json(['done' => true, 'messages' => $messages,'Cards' => $dataCards] );
} catch (\Exception $e) {
$this->entityManager->rollback();
$this->addError('front.shopping.system_error');
return $this->json(['done' => false, 'messages' => $messages]);
}
}
/**
* カートに追加.
*
* @Route("/products/update_card/{id}", name="update_card", methods={"POST"}, requirements={"id" = "\d+"})
* @Template("Product/detail.twig")
*/
public function updateCard(Request $request)
{
$messages = [];
$StripeCardId = $request->get('radio_card');
$paymentMethod = PaymentMethod::retrieve($StripeCardId);
$dataCard = [
'id' => $paymentMethod['id'],
'brand' => $paymentMethod['card']['brand'],
'exp_month' => $paymentMethod['card']['exp_month'],
'exp_year' => $paymentMethod['card']['exp_year'],
'last4' => $paymentMethod['card']['last4'],
];
return $this->json(['done' => true, 'messages' => $messages,'Card' => $dataCard] );
}
/**
* カートに追加.
*
* @Route("/products/create_card_onetouch/{id}", name="create_card_onetouch", methods={"POST"}, requirements={"id" = "\d+"})
* @Template("Product/detail.twig")
*/
public function createCardOnetouch(Request $request, Customer $Customer)
{
$messages = [];
$StripeCustomer = $this->stripeCustomerRepository->findOneBy(array('Customer' => $Customer));
$cards = new ArrayCollection();
if ($StripeCustomer) {
$StripeCustomerId = $StripeCustomer->getStripeCustomerId();
if ($StripeCustomerId) {
$cards = PaymentMethod::all([
'customer' => $StripeCustomerId,
'type' => 'card',
]);
$cards = new ArrayCollection($cards->data);
};
}else{
$customer_id = $Customer['id'];
$customer_email = $Customer['email'];
$data = [
'email'=> $customer_email,
'metadata'=> array('customer_id' => $customer_id),
];
$StripeCustomerApi = StripeLibCustomer::create($data);
$StripeCustomer = new StripeCustomer();
$StripeCustomer->setCustomer($Customer);
$StripeCustomer->setStripeCustomerId($StripeCustomerApi['id']);
$StripeCustomer->setIsSaveCardOn(0);
$StripeCustomer->setCreatedAt(new \DateTime());
$this->entityManager->persist($StripeCustomer);
$this->entityManager->flush($StripeCustomer);
$StripeCustomerId = $StripeCustomer->getStripeCustomerId();
if ($StripeCustomerId) {
$cards = PaymentMethod::all([
'customer' => $StripeCustomerId,
'type' => 'card',
]);
$cards = new ArrayCollection($cards->data);
};
}
$fingerprints = [];
foreach ($cards as $card) {
$fingerprints[] = $card['card']['fingerprint'];
}
try {
$payment_method = PaymentMethod::retrieve($request->get("stripe_payment_method_id"));
if (in_array($payment_method['card']['fingerprint'], $fingerprints)) {
return $this->redirectToRoute('mypage_card');
}
$payment_method->attach([
'customer' => $StripeCustomerId
]);
$dataCard = [
'id' => $payment_method['id'],
'brand' => $payment_method['card']['brand'],
'exp_month' => $payment_method['card']['exp_month'],
'exp_year' => $payment_method['card']['exp_year'],
'last4' => $payment_method['card']['last4'],
];
return $this->json(['done' => true, 'messages' => $messages,'Card' => $dataCard,'StripeCustomerId' => $StripeCustomerId] );
} catch (Exception $e) {
return $this->redirectToRoute('mypage_card_new');
}
}
/**
* カートに追加.
*
* @Route("/products/update_shipping/{id}", name="update_shipping", methods={"POST"}, requirements={"id" = "\d+"})
* @Template("Product/detail.twig")
*/
public function updateShipping(Request $request, Shipping $Shipping)
{
$messages = [];
$Customer = $this->getUser();
$customerId = $Customer->getId();
$preOrderId = $Shipping->getOrder()->getPreOrderId();
$Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
$idAddress = $request->get('radio_address');
try {
if ($idAddress != 0) {
/** @var CustomerAddress $CustomerAddress */
$CustomerAddress = $this->customerAddressRepository->find($idAddress);
$Shipping->setFromCustomerAddress($CustomerAddress);
}
else{
$CustomerAddress = new CustomerAddress();
$CustomerAddress->setFromCustomer($Customer);
$Shipping->setFromCustomerAddress($CustomerAddress);
}
// 合計金額の再計算
$response = $this->executePurchaseFlow($Order);
$this->entityManager->flush();
$Shipping = $Order->getShippings()[0];
$ShippingData = [
'id' => $Shipping->getId(),
'name01' => $Shipping->getName01(),
'name02' => $Shipping->getName02(),
'kana01' => $Shipping->getKana01(),
'kana02' => $Shipping->getKana02(),
'postal_code' => $Shipping->getPostalCode(),
'pref' => $Shipping->getPref()->getName(),
'addr01' => $Shipping->getAddr01(),
'addr02' => $Shipping->getAddr02(),
'phone_number' => $Shipping->getPhoneNumber(),
'default_id' => $CustomerAddress->getId(),
];
$OrderData = [
'payment_total' => $Order->getPaymentTotal(),
'delivery_fee_total' => $Order->getDeliveryFeeTotal(),
'order_id' => $Order->getId(),
'discount' => $Order['discount'],
'shipping' => $ShippingData
];
return $this->json([
'Order' => $OrderData,
'done' => true,
]);
} catch (\Exception $e) {
$this->entityManager->rollback();
$this->addError('front.shopping.system_error');
return $this->json(['done' => false, 'messages' => $messages]);;
}
}
/**
* カートに追加.
*
* @Route("/products/create_shipping/{id}", name="create_shipping", methods={"POST"}, requirements={"id" = "\d+"})
* @Template("Product/detail.twig")
*/
public function createShipping(Request $request, Shipping $Shipping)
{
$messages = [];
$CustomerAddress = new CustomerAddress();
$CustomerAddress->setCustomer($this->getUser());
$builder = $this->formFactory->createBuilder(CustomerAddressType::class, $CustomerAddress);
$form = $builder->getForm();
$form->handleRequest($request);
try {
$this->entityManager->persist($CustomerAddress);
$this->entityManager->flush();
$preOrderId = $Shipping->getOrder()->getPreOrderId();
$Order = $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
$Shipping->setFromCustomerAddress($CustomerAddress);
$response = $this->executePurchaseFlow($Order);
$this->entityManager->flush();
$Shipping = $Order->getShippings()[0];
$ShippingData = [
'id' => $Shipping->getId(),
'name01' => $Shipping->getName01(),
'name02' => $Shipping->getName02(),
'kana01' => $Shipping->getKana01(),
'kana02' => $Shipping->getKana02(),
'postal_code' => $Shipping->getPostalCode(),
'pref' => $Shipping->getPref()->getName(),
'addr01' => $Shipping->getAddr01(),
'addr02' => $Shipping->getAddr02(),
'phone_number' => $Shipping->getPhoneNumber(),
'default_id' => $CustomerAddress->getId(),
];
$OrderData = [
'payment_total' => $Order->getPaymentTotal(),
'delivery_fee_total' => $Order->getDeliveryFeeTotal(),
'order_id' => $Order->getId(),
'discount' => $Order['discount'],
'shipping' => $ShippingData
];
return $this->json([
'Order' => $OrderData,
'done' => true,
]);
} catch (\Exception $e) {
$this->entityManager->rollback();
$this->addError('front.shopping.system_error');
return $this->json(['done' => false, 'messages' => $messages]);;
}
}
/**
* @param ItemHolderInterface $itemHolder
* @param bool $returnResponse レスポンスを返すかどうか. falseの場合はPurchaseFlowResultを返す.
*
* @return PurchaseFlowResult|\Symfony\Component\HttpFoundation\RedirectResponse
*/
protected function executePurchaseFlow(ItemHolderInterface $itemHolder, $returnResponse = true)
{
/** @var PurchaseFlowResult $flowResult */
$flowResult = $this->shoppingPurchaseFlow->validate($itemHolder, new PurchaseContext(clone $itemHolder, $itemHolder->getCustomer()));
foreach ($flowResult->getWarning() as $warning) {
$this->addWarning($warning->getMessage());
}
foreach ($flowResult->getErrors() as $error) {
$this->addError($error->getMessage());
}
if (!$returnResponse) {
return $flowResult;
}
if ($flowResult->hasError()) {
log_info('Errorが発生したため購入エラー画面へ遷移します.', [$flowResult->getErrors()]);
return $flowResult;
}
if ($flowResult->hasWarning()) {
log_info('Warningが発生したため注文手続き画面へ遷移します.', [$flowResult->getWarning()]);
return $flowResult;
}
}
private function get_point($price, $prime=false){
if($prime){
return number_format($price * 3 / 100);
}else{
$pointRate = 1;
if ($this->getUser()) {
$pointRate = $this->getUser()->getOwnerRank() + 1;
}
return number_format($price * $pointRate / 100);
}
}
/**
* 商品一覧画面.
*
* @Route("/products/promotion_code", name="promotion_code", methods={"POST"})
*/
public function applyPromotionCode(Request $request)
{
$Order = $this->orderRepository->find($request->get('order_id'));
$CouponOrder = $this->couponOrderRepository->getCouponOrder($Order->getPreOrderId());
$couponCd = null;
if ($CouponOrder) {
$couponCd = $CouponOrder->getCouponCd();
}
$form_c = $this->formFactory->createBuilder(CouponUseType::class)->getForm();
$service = $this->couponService;
$formCouponCd = $request->get('coupon_cd');
$formCouponCancel = $request->get('coupon_use');
if ($formCouponCancel == 0) {
if (!is_null($formCouponCd)) {
$this->couponService->removeCouponOrder($Order);
$Order->setPaymentTotal($Order->getPaymentTotal() + $Order->getDiscount());
$Order->setTotal($Order->getTotal() + $Order->getDiscount());
$Order->setDiscount(0);
$this->entityManager->persist($Order);
$this->entityManager->flush();
}
return $this->redirectToRoute('shopping');
} else {
$error = false;
$Coupon = $this->couponRepository->findActiveCoupon($formCouponCd);
if (!$Coupon) {
$form_c->get('coupon_cd')->addError(new FormError(trans('plugin_coupon.front.shopping.notexists')));
$error = true;
return $this->json([
'success'=> false,
]);
}
$Customer = $this->getUser();
if (!$error && $Coupon) {
$couponProducts = $service->existsCouponProduct($Coupon, $Order);
$discount = $service->recalcOrder($Coupon, $couponProducts);
$service->saveCouponOrder($Order, $Coupon, $formCouponCd, $Customer, $discount);
if ($discount) {
$Order->setDiscount($discount);
$Order->setPaymentTotal($Order->getPaymentTotal() - $discount);
$Order->setTotal($Order->getTotal() - $discount);
$this->entityManager->persist($Order);
$this->entityManager->flush();
}
return $this->json([
'success'=> true,
'discount' => $discount,
'total' => $Order->getTotal()
]);
}
}
}
private function handlerSupplierProduct($Product)
{
$categorySupplier = $this->productRepository->getSupplierCategories();
$is_supplier = false;
foreach ($Product->getProductCategories() as $category) {
if (in_array($category->getCategoryId(), $categorySupplier)) {
$is_supplier = true;
}
}
return $is_supplier;
}
/**
* 商品一覧画面.
*
* @Route("/products/last_customer/{id}", name="last_customer_order", methods={"GET"}, requirements={"id" = "\d+"})
*/
public function getLastCustomerOrder($id)
{
$lastOrderCustomers = $this->productRepository->getCustomerLastOrder($id);
$Mails = [];
if ($lastOrderCustomers) {
foreach($lastOrderCustomers as $customer) {
$Mails[] = $customer->getEmail();
}
}
return $this->json([
'emails' => $Mails
]);
}
function getPointCart($Cart, $Customer){
$prime = $Customer['prime_member'];
$urank = $Customer['owner_rank'];
$alpha = 0;
if($prime){
$alpha = 3;
}
if($urank == 0){
$alpha = $alpha + 1;
}elseif($urank == 1){
$alpha = $alpha + 2;
}elseif($urank == 2){
$alpha = $alpha + 3;
}elseif($urank == 3){
$alpha = $alpha + 4;
}
return number_format( round(strval($Cart->getTotalPrice() * $alpha / 100)));
}
/**
* カートに追加.
*
* @Route("/products/add_cart_by_email/{id}", name="product_add_cart_by_email", methods={"POST","GET"}, requirements={"id" = "\d+"})
*/
public function addCartByEmail(Request $request, Product $Product)
{
// エラーメッセージの配列
$errorMessages = [];
if (!$this->checkVisibility($Product)) {
throw new NotFoundHttpException();
}
$builder = $this->formFactory->createNamedBuilder(
'',
AddCartByEmailType::class,
null,
[
'product' => $Product,
'id_add_product_id' => false,
]
);
$event = new EventArgs(
[
'builder' => $builder,
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE, $event);
/* @var $form \Symfony\Component\Form\FormInterface */
$form = $builder->getForm();
$form->handleRequest($request);
if (!$form->isValid()) {
foreach ($form->all() as $child) {
$config = $child->getConfig();
foreach ($child->getErrors() as $error) {
$errorMessages[] = $config->getOption('label') . ':' . $error->getMessage();
}
}
}
$recipientEmail = $form->get('email')->getData();
if ($recipientEmail) {
$customer = $this->customerRepository->findBy(array('email' => $recipientEmail));
if (count($customer) > 0) {
$customer = $customer[0];
} else {
$customer = null;
$errorMessages[] = '存在しないメールアドレスです。';
}
}
$addCartData = $form->getData();
$ProductClass = $this->entityManager->getRepository(ProductClass::class)->find($addCartData['product_class_id']);
$limit = $ProductClass->getSaleLimit();
if (!$ProductClass->isStockUnlimited()) {
$stock = $ProductClass->getStock();
}
if (!is_null($limit) || isset($stock)) {
$Carts = $this->cartService->getCarts();
$quantity = $addCartData['quantity'];
foreach ($Carts as $Cart) {
foreach ($Cart->getCartItems() as $item) {
if ($item->getProductClass()->getId() == $ProductClass->getId()) $quantity += $item->getQuantity();
}
}
$productName = $ProductClass->getProduct()->getName();
if ($ProductClass->hasClassCategory1()) {
$productName .= ' - ' . $ProductClass->getClassCategory1()->getName();
}
if ($ProductClass->hasClassCategory2()) {
$productName .= ' - ' . $ProductClass->getClassCategory2()->getName();
}
if (!is_null($limit) && $limit < $quantity) {
$errorMessages[] = trans('front.shopping.over_sale_limit', ['%product%' => $productName]);
}
if (isset($stock) && $stock < $quantity) {
$errorMessages[] = trans('front.shopping.out_of_stock', ['%product%' => $productName]);
}
}
if (count($errorMessages) == 0) {
log_info(
'カート追加処理開始',
[
'product_id' => $Product->getId(),
'product_class_id' => $addCartData['product_class_id'],
'quantity' => $addCartData['quantity'],
]
);
// カートへ追加
$ProductOptions = $Product->getProductOptions();
$Options = [];
foreach ($ProductOptions as $ProductOption) {
$Option = $ProductOption->getOption();
$option_key = 'productoption' . $Option->getId();
$value = $form->get($option_key)->getData();
if ($Option) {
$add = true;
if ($Option->getType() == Option::SELECT_TYPE || $Option->getType() == Option::RADIO_TYPE) {
if ($Option->getDisableCategory()) {
if ($Option->getDisableCategory() == $value) {
$add = false;
}
}
$value = $value->getId();
if (strlen($value) == 0) $add = false;
} elseif ($Option->getType() == Option::TEXT_TYPE || $Option->getType() == Option::TEXTAREA_TYPE || $Option->getType() == Option::NUMBER_TYPE) {
if (strlen($value) == 0) $add = false;
} elseif ($Option->getType() == Option::CHECKBOX_TYPE) {
if (count($value) == 0) {
$add = false;
} else {
$buff = $value;
$value = [];
foreach ($buff as $categoryoption) {
$value[] = $categoryoption->getId();
}
}
} elseif ($Option->getType() == Option::DATE_TYPE) {
if (is_null($value)) $add = false;
}
if ($add) {
if (is_array($value)) {
$Options[$Option->getId()] = $value;
} elseif (is_object($value)) {
$Options[$Option->getId()] = $value->format('Y-m-d');
} else {
$Options[$Option->getId()] = (string)$value;
}
}
}
}
$this->cartService->addProductOption($addCartData['product_class_id'], $Options, $addCartData['quantity']);
// 明細の正規化
$Carts = $this->cartService->getCarts();
foreach ($Carts as $Cart) {
$result = $this->purchaseFlow->validate($Cart, new PurchaseContext($Cart, $customer));
// 復旧不可のエラーが発生した場合は追加した明細を削除.
if ($result->hasError()) {
$this->cartService->removeProduct($addCartData['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' => $addCartData['product_class_id'],
'quantity' => $addCartData['quantity'],
]
);
$event = new EventArgs(
[
'form' => $form,
'Product' => $Product,
],
$request
);
$this->eventDispatcher->dispatch(EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE, $event);
}
if ($event->getResponse() !== null) {
return $event->getResponse();
}
$done = null;
$messages = [];
if (empty($errorMessages)) {
// エラーが発生していない場合
$done = true;
array_push($messages, trans('front.product.add_cart_complete'));
} else {
// エラーが発生している場合
$done = false;
$messages = $errorMessages;
}
return $this->json(['done' => $done, 'messages' => $messages, 'product_class_id' => $ProductClass->getId()]);
}
/**
* @Route("/update_last_seen_product", name="update_last_seen_product", methods={"POST"})
*/
public function updateLastSeenProduct(Request $request)
{
try {
$productId = (int) $request->request->get('productId');
$arr = $this->session->get('plugin.check_product.product');
$arr[] = $productId;
$arr = array_unique($arr);
$max = $this->eccubeConfig['PLG_CHECK_PRODUCT_MAX'];
$arr = array_slice($arr, (- $max), $max);
$this->session->set('plugin.check_product.product', $arr);
return $this->json([
'done' => true,
'child_product_id' => $arr
]);
} catch (\Throwable $th) {
throw $th;
}
}
}