src/Eccube/Controller/ShippingMultipleController.php line 117

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\Controller;
  13. use Eccube\Entity\Customer;
  14. use Eccube\Entity\CustomerAddress;
  15. use Eccube\Entity\Master\OrderItemType;
  16. use Eccube\Entity\OrderItem;
  17. use Eccube\Entity\Shipping;
  18. use Eccube\Event\EccubeEvents;
  19. use Eccube\Event\EventArgs;
  20. use Eccube\Form\Type\Front\ShoppingShippingType;
  21. use Eccube\Form\Type\ShippingMultipleType;
  22. use Eccube\Repository\BaseInfoRepository;
  23. use Eccube\Repository\Master\OrderItemTypeRepository;
  24. use Eccube\Repository\Master\PrefRepository;
  25. use Eccube\Repository\OrderRepository;
  26. use Eccube\Service\CartService;
  27. use Eccube\Service\MailService;
  28. use Eccube\Service\OrderHelper;
  29. use Eccube\Service\PurchaseFlow\PurchaseContext;
  30. use Eccube\Service\PurchaseFlow\PurchaseFlow;
  31. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  32. use Symfony\Component\Form\Extension\Core\Type\CollectionType;
  33. use Symfony\Component\HttpFoundation\Request;
  34. use Symfony\Component\Routing\Annotation\Route;
  35. class ShippingMultipleController extends AbstractShoppingController
  36. {
  37.     /**
  38.      * @var PrefRepository
  39.      */
  40.     protected $prefRepository;
  41.     /**
  42.      * @var OrderItemTypeRepository
  43.      */
  44.     protected $orderItemTypeRepository;
  45.     /**
  46.      * @var OrderHelper
  47.      */
  48.     protected $orderHelper;
  49.     /**
  50.      * @var CartService
  51.      */
  52.     protected $cartService;
  53.     /**
  54.      * @var PurchaseFlow
  55.      */
  56.     protected $cartPurchaseFlow;
  57.     /**
  58.      * @var OrderRepository
  59.      */
  60.     protected $orderRepository;
  61.     /**
  62.      * @var MailService
  63.      */
  64.     protected $mailService;
  65.     /**
  66.      * @var baseInfoRepository
  67.      */
  68.     protected $baseInfoRepository;
  69.     /**
  70.      * ShippingMultipleController constructor.
  71.      *
  72.      * @param PrefRepository $prefRepository
  73.      * @param OrderRepository $orderRepository
  74.      * @param OrderItemTypeRepository $orderItemTypeRepository
  75.      * @param OrderHelper $orderHelper
  76.      * @param CartService $cartService
  77.      * @param PurchaseFlow $cartPurchaseFlow
  78.      */
  79.     public function __construct(
  80.         PrefRepository $prefRepository,
  81.         OrderRepository $orderRepository,
  82.         OrderItemTypeRepository $orderItemTypeRepository,
  83.         OrderHelper $orderHelper,
  84.         CartService $cartService,
  85.         PurchaseFlow $cartPurchaseFlow,
  86.         BaseInfoRepository $baseInfoRepository,
  87.         MailService $mailService
  88.     ) {
  89.         $this->prefRepository $prefRepository;
  90.         $this->orderRepository $orderRepository;
  91.         $this->orderItemTypeRepository $orderItemTypeRepository;
  92.         $this->orderHelper $orderHelper;
  93.         $this->cartService $cartService;
  94.         $this->cartPurchaseFlow $cartPurchaseFlow;
  95.         $this->baseInfoRepository $baseInfoRepository;
  96.         $this->mailService $mailService;
  97.     }
  98.     /**
  99.      * 複数配送処理
  100.      *
  101.      * @Route("/shopping/shipping_multiple", name="shopping_shipping_multiple", methods={"GET", "POST"})
  102.      * @Template("Shopping/shipping_multiple.twig")
  103.      */
  104.     public function index(Request $request)
  105.     {
  106.         // ログイン状態のチェック.
  107.         if ($this->orderHelper->isLoginRequired()) {
  108.             return $this->redirectToRoute('shopping_login');
  109.         }
  110.         // 受注の存在チェック
  111.         $preOrderId $this->cartService->getPreOrderId();
  112.         $Order $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
  113.         if (!$Order) {
  114.             return $this->redirectToRoute('shopping_error');
  115.         }
  116.         // 処理しやすいようにすべてのShippingItemをまとめる
  117.         $OrderItems $Order->getProductOrderItems();
  118.         // Orderに含まれる商品ごとの数量を求める
  119.         $ItemQuantitiesByClassId = [];
  120.         foreach ($OrderItems as $item) {
  121.             $itemId $item->getProductClass()->getId();
  122.             $quantity $item->getQuantity();
  123.             if (array_key_exists($itemId$ItemQuantitiesByClassId)) {
  124.                 $ItemQuantitiesByClassId[$itemId] += $quantity;
  125.             } else {
  126.                 $ItemQuantitiesByClassId[$itemId] = $quantity;
  127.             }
  128.         }
  129.         // FormBuilder用に商品ごとにShippingItemをまとめる
  130.         $OrderItemsForFormBuilder = [];
  131.         $tmpAddedClassIds = [];
  132.         foreach ($OrderItems as $item) {
  133.             $itemId $item->getProductClass()->getId();
  134.             if (!in_array($itemId$tmpAddedClassIds)) {
  135.                 $OrderItemsForFormBuilder[] = $item;
  136.                 $tmpAddedClassIds[] = $itemId;
  137.             }
  138.         }
  139.         // Form生成
  140.         $builder $this->formFactory->createBuilder();
  141.         $builder
  142.             ->add('shipping_multiple'CollectionType::class, [
  143.                 'entry_type' => ShippingMultipleType::class,
  144.                 'data' => $OrderItemsForFormBuilder,
  145.                 'allow_add' => true,
  146.                 'allow_delete' => true,
  147.             ]);
  148.         // Event
  149.         $event = new EventArgs(
  150.             [
  151.                 'builder' => $builder,
  152.                 'Order' => $Order,
  153.             ],
  154.             $request
  155.         );
  156.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_SHOPPING_SHIPPING_MULTIPLE_INITIALIZE);
  157.         $form $builder->getForm();
  158.         $form->handleRequest($request);
  159.         $errors = [];
  160.         if ($form->isSubmitted() && $form->isValid()) {
  161.             log_info('複数配送設定処理開始', [$Order->getId()]);
  162.             $data $form['shipping_multiple'];
  163.             // フォームの入力から、送り先ごとに商品の数量を集計する
  164.             $arrOrderItemTemp = [];
  165.             foreach ($data as $multiples) {
  166.                 $OrderItem $multiples->getData();
  167.                 foreach ($multiples as $items) {
  168.                     foreach ($items as $item) {
  169.                         $CustomerAddress $item['customer_address']->getData();
  170.                         $customerAddressName $CustomerAddress->getShippingMultipleDefaultName();
  171.                         $itemId $OrderItem->getProductClass()->getId();
  172.                         $quantity $item['quantity']->getData();
  173.                         if (isset($arrOrderItemTemp[$customerAddressName]) && array_key_exists($itemId$arrOrderItemTemp[$customerAddressName])) {
  174.                             $arrOrderItemTemp[$customerAddressName][$itemId] = $arrOrderItemTemp[$customerAddressName][$itemId] + $quantity;
  175.                         } else {
  176.                             $arrOrderItemTemp[$customerAddressName][$itemId] = $quantity;
  177.                         }
  178.                     }
  179.                 }
  180.             }
  181.             // フォームの入力から、商品ごとの数量を集計する
  182.             $itemQuantities = [];
  183.             foreach ($arrOrderItemTemp as $FormItemByAddress) {
  184.                 foreach ($FormItemByAddress as $itemId => $quantity) {
  185.                     if (array_key_exists($itemId$itemQuantities)) {
  186.                         $itemQuantities[$itemId] = $itemQuantities[$itemId] + $quantity;
  187.                     } else {
  188.                         $itemQuantities[$itemId] = $quantity;
  189.                     }
  190.                 }
  191.             }
  192.             // -- ここから先がお届け先を再生成する処理 --
  193.             // お届け先情報をすべて削除
  194.             /** @var Shipping $Shipping */
  195.             foreach ($Order->getShippings() as $Shipping) {
  196.                 foreach ($Shipping->getOrderItems() as $OrderItem) {
  197.                     $Shipping->removeOrderItem($OrderItem);
  198.                     $Order->removeOrderItem($OrderItem);
  199.                     $this->entityManager->remove($OrderItem);
  200.                 }
  201.                 $Order->removeShipping($Shipping);
  202.                 $this->entityManager->remove($Shipping);
  203.             }
  204.             // お届け先のリストを作成する
  205.             $ShippingList = [];
  206.             foreach ($data as $multiples) {
  207.                 $OrderItem $multiples->getData();
  208.                 $ProductClass $OrderItem->getProductClass();
  209.                 $Delivery $OrderItem->getShipping()->getDelivery();
  210.                 $saleTypeId $ProductClass->getSaleType()->getId();
  211.                 foreach ($multiples as $items) {
  212.                     foreach ($items as $item) {
  213.                         $CustomerAddress $item['customer_address']->getData();
  214.                         $customerAddressName $CustomerAddress->getShippingMultipleDefaultName();
  215.                         if (isset($ShippingList[$customerAddressName][$saleTypeId])) {
  216.                             continue;
  217.                         }
  218.                         $Shipping = new Shipping();
  219.                         $Shipping
  220.                             ->setOrder($Order)
  221.                             ->setFromCustomerAddress($CustomerAddress)
  222.                             ->setDelivery($Delivery);
  223.                         $Order->addShipping($Shipping);
  224.                         $ShippingList[$customerAddressName][$saleTypeId] = $Shipping;
  225.                     }
  226.                 }
  227.             }
  228.             // お届け先のリストを保存
  229.             foreach ($ShippingList as $ShippingListByAddress) {
  230.                 foreach ($ShippingListByAddress as $Shipping) {
  231.                     $this->entityManager->persist($Shipping);
  232.                 }
  233.             }
  234.             $ProductOrderType $this->orderItemTypeRepository->find(OrderItemType::PRODUCT);
  235.             // お届け先に、配送商品の情報(OrderItem)を関連付ける
  236.             foreach ($data as $multiples) {
  237.                 /** @var OrderItem $OrderItem */
  238.                 $OrderItem $multiples->getData();
  239.                 $ProductClass $OrderItem->getProductClass();
  240.                 $Product $OrderItem->getProduct();
  241.                 $saleTypeId $ProductClass->getSaleType()->getId();
  242.                 $productClassId $ProductClass->getId();
  243.                 foreach ($multiples as $items) {
  244.                     foreach ($items as $item) {
  245.                         $CustomerAddress $item['customer_address']->getData();
  246.                         $customerAddressName $CustomerAddress->getShippingMultipleDefaultName();
  247.                         // お届け先から商品の数量を取得
  248.                         $quantity 0;
  249.                         if (isset($arrOrderItemTemp[$customerAddressName]) && array_key_exists($productClassId$arrOrderItemTemp[$customerAddressName])) {
  250.                             $quantity $arrOrderItemTemp[$customerAddressName][$productClassId];
  251.                             unset($arrOrderItemTemp[$customerAddressName][$productClassId]);
  252.                         } else {
  253.                             // この配送先には送る商品がないのでスキップ(通常ありえない)
  254.                             continue;
  255.                         }
  256.                         // 関連付けるお届け先のインスタンスを取得
  257.                         $Shipping $ShippingList[$customerAddressName][$saleTypeId];
  258.                         // インスタンスを生成して保存
  259.                         $OrderItem = new OrderItem();
  260.                         $OrderItem->setShipping($Shipping)
  261.                             ->setOrder($Order)
  262.                             ->setProductClass($ProductClass)
  263.                             ->setProduct($Product)
  264.                             ->setProductName($Product->getName())
  265.                             ->setProductCode($ProductClass->getCode())
  266.                             ->setPrice($ProductClass->getPrice02())
  267.                             ->setQuantity($quantity)
  268.                             ->setOrderItemType($ProductOrderType);
  269.                         $ClassCategory1 $ProductClass->getClassCategory1();
  270.                         if (!is_null($ClassCategory1)) {
  271.                             $OrderItem->setClasscategoryName1($ClassCategory1->getName());
  272.                             $OrderItem->setClassName1($ClassCategory1->getClassName()->getName());
  273.                         }
  274.                         $ClassCategory2 $ProductClass->getClassCategory2();
  275.                         if (!is_null($ClassCategory2)) {
  276.                             $OrderItem->setClasscategoryName2($ClassCategory2->getName());
  277.                             $OrderItem->setClassName2($ClassCategory2->getClassName()->getName());
  278.                         }
  279.                         $Shipping->addOrderItem($OrderItem);
  280.                         $Order->addOrderItem($OrderItem);
  281.                         $this->entityManager->persist($OrderItem);
  282.                     }
  283.                 }
  284.             }
  285.             // 合計金額の再計算
  286.             $flowResult $this->executePurchaseFlow($Orderfalse);
  287.             if ($flowResult->hasError()) {
  288.                 return $this->redirectToRoute('shopping_error');
  289.             }
  290.             $this->entityManager->flush();
  291.             $event = new EventArgs(
  292.                 [
  293.                     'form' => $form,
  294.                     'Order' => $Order,
  295.                 ],
  296.                 $request
  297.             );
  298.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_SHOPPING_SHIPPING_MULTIPLE_COMPLETE);
  299.             log_info('複数配送設定処理完了', [$Order->getId()]);
  300.             $this->entityManager->refresh($Order);
  301.             $quantityByProductClass = [];
  302.             foreach ($Order->getProductOrderItems() as $Item) {
  303.                 $id $Item->getProductClass()->getId();
  304.                 if (isset($quantityByProductClass[$id])) {
  305.                     $quantityByProductClass[$id] += $Item->getQuantity();
  306.                 } else {
  307.                     $quantityByProductClass[$id] = $Item->getQuantity();
  308.                 }
  309.             }
  310.             $Cart $this->cartService->getCart();
  311.             if ($Cart) {
  312.                 foreach ($Cart->getCartItems() as $CartItem) {
  313.                     $id $CartItem->getProductClass()->getId();
  314.                     if (isset($quantityByProductClass[$id])) {
  315.                         $CartItem->setQuantity($quantityByProductClass[$id]);
  316.                     }
  317.                 }
  318.                 $this->cartPurchaseFlow->validate($Cart, new PurchaseContext($Cart$this->getUser()));
  319.                 // 注文フローで取得されるカートの入れ替わりを防止する
  320.                 // @see https://github.com/EC-CUBE/ec-cube/issues/4293
  321.                 $this->cartService->setPrimary($Cart->getCartKey());
  322.             }
  323.             return $this->redirectToRoute('shopping');
  324.         }
  325.         return [
  326.             'form' => $form->createView(),
  327.             'OrderItems' => $OrderItemsForFormBuilder,
  328.             'compItemQuantities' => $ItemQuantitiesByClassId,
  329.             'errors' => $errors,
  330.         ];
  331.     }
  332.     /**
  333.      * 複数配送設定時の新規お届け先の設定
  334.      *
  335.      * 会員ログイン時は会員のお届け先に追加する
  336.      * 非会員時はセッションに追加する
  337.      *
  338.      * @Route("/shopping/shipping_multiple_edit", name="shopping_shipping_multiple_edit", methods={"GET", "POST"})
  339.      * @Template("Shopping/shipping_multiple_edit.twig")
  340.      */
  341.     public function shippingMultipleEdit(Request $request)
  342.     {
  343.         // ログイン状態のチェック.
  344.         if ($this->orderHelper->isLoginRequired()) {
  345.             return $this->redirectToRoute('shopping_login');
  346.         }
  347.         // 受注の存在チェック
  348.         $preOrderId $this->cartService->getPreOrderId();
  349.         $Order $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
  350.         if (!$Order) {
  351.             return $this->redirectToRoute('shopping_error');
  352.         }
  353.         /** @var Customer $Customer */
  354.         $Customer $this->getUser();
  355.         $CustomerAddress = new CustomerAddress();
  356.         $builder $this->formFactory->createBuilder(ShoppingShippingType::class, $CustomerAddress);
  357.         $event = new EventArgs(
  358.             [
  359.                 'builder' => $builder,
  360.                 'Customer' => $Customer,
  361.             ],
  362.             $request
  363.         );
  364.         $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_SHOPPING_SHIPPING_MULTIPLE_EDIT_INITIALIZE);
  365.         $form $builder->getForm();
  366.         $form->handleRequest($request);
  367.         if ($form->isSubmitted() && $form->isValid()) {
  368.             log_info('複数配送のお届け先追加処理開始');
  369.             if ($this->isGranted('ROLE_USER')) {
  370.                 $CustomerAddresses $Customer->getCustomerAddresses();
  371.                 $count count($CustomerAddresses);
  372.                 if ($count >= $this->eccubeConfig['eccube_deliv_addr_max']) {
  373.                     return [
  374.                         'error' => trans('common.customer_address_count_is_over', [
  375.                             '%eccube_deliv_addr_max%' => $this->eccubeConfig->get('eccube_deliv_addr_max'),
  376.                         ]),
  377.                         'form' => $form->createView(),
  378.                     ];
  379.                 }
  380.                 // 会員情報変更時にメールを送信
  381.                 if ($this->baseInfoRepository->get()->isOptionMailNotifier()) {
  382.                     // 情報のセット
  383.                     $userData['userAgent'] = $request->headers->get('User-Agent');
  384.                     $userData['ipAddress'] = $request->getClientIp();
  385.                     $this->mailService->sendCustomerChangeNotifyMail($Customer$userDatatrans('front.mypage.delivery.notify_title'));
  386.                 }
  387.                 $CustomerAddress->setCustomer($Customer);
  388.                 $this->entityManager->persist($CustomerAddress);
  389.                 $this->entityManager->flush();
  390.             } else {
  391.                 // 非会員用のセッションに追加
  392.                 $CustomerAddresses $this->session->get(OrderHelper::SESSION_NON_MEMBER_ADDRESSES);
  393.                 $CustomerAddresses unserialize($CustomerAddresses);
  394.                 $CustomerAddresses[] = $CustomerAddress;
  395.                 $this->session->set(OrderHelper::SESSION_NON_MEMBER_ADDRESSESserialize($CustomerAddresses));
  396.             }
  397.             $event = new EventArgs(
  398.                 [
  399.                     'form' => $form,
  400.                     'CustomerAddresses' => $CustomerAddresses,
  401.                 ],
  402.                 $request
  403.             );
  404.             $this->eventDispatcher->dispatch($eventEccubeEvents::FRONT_SHOPPING_SHIPPING_MULTIPLE_EDIT_COMPLETE);
  405.             log_info('複数配送のお届け先追加処理完了');
  406.             return $this->redirectToRoute('shopping_shipping_multiple');
  407.         }
  408.         return [
  409.             'form' => $form->createView(),
  410.         ];
  411.     }
  412. }