app/Customize/EventListener/AkiCustomizerListener.php line 548

Open in your IDE?
  1. <?php
  2. namespace Customize\EventListener;
  3. use Customize\Controller\Trait\ConstanceTrait;
  4. use Customize\Controller\Trait\KrakiFileTrait;
  5. use Customize\Service\Cache\UserDataCache;
  6. use Eccube\Entity\Order;
  7. use Eccube\Entity\TaxRule;
  8. use Eccube\Entity\Master\OrderItemType;
  9. use Customize\Common\Utils;
  10. use Eccube\Event\EventArgs;
  11. use Eccube\Entity\OrderItem;
  12. use Eccube\Event\EccubeEvents;
  13. use Customize\Common\Constants;
  14. use Eccube\Common\EccubeConfig;
  15. use Eccube\Entity\ProductClass;
  16. use Eccube\Event\TemplateEvent;
  17. use Eccube\Service\CartService;
  18. use Symfony\Component\Yaml\Parser;
  19. use Customize\Entity\ProductUseDays;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use Eccube\Service\PurchaseFlow\PurchaseFlow;
  22. use Symfony\Component\Security\Core\Security;
  23. use Customize\Entity\OrderDetailAdditionalInfo;
  24. use Eccube\Service\PurchaseFlow\PurchaseContext;
  25. use Symfony\Component\HttpKernel\KernelInterface;
  26. use Symfony\Component\Validator\Constraints as Assert;
  27. use Symfony\Component\Form\Extension\Core\Type\TextType;
  28. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  29. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  30. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  31. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  32. use Symfony\Component\Form\Extension\Core\Type\TextareaType;
  33. use Symfony\Component\HttpFoundation\RequestStack;
  34. use Symfony\Component\Validator\Context\ExecutionContextInterface;
  35. use Customize\Entity\GrayoutManagement;
  36. use Carbon\Carbon;
  37. class AkiCustomizerListener implements EventSubscriberInterface
  38. {
  39.     use ConstanceTrait;
  40.     use KrakiFileTrait;
  41.     /**
  42.      * entityManagerInterface
  43.      *
  44.      * @var EntityManagerInterface
  45.      */
  46.     private $entityManagerInterface;
  47.     /**
  48.      * session
  49.      *
  50.      * @var SessionInterface
  51.      */
  52.     private $session;
  53.     /**
  54.      * kernelInterface
  55.      *
  56.      * @var KernelInterface
  57.      */
  58.     private $kernelInterface;
  59.     /**
  60.      * eccubeConfig
  61.      *
  62.      * @var EccubeConfig
  63.      */
  64.     private $eccubeConfig;
  65.     /**
  66.      * cartService
  67.      *
  68.      * @var CartService
  69.      */
  70.     private $cartService;
  71.     private $purchaseFlow;
  72.     private $security;
  73.     private $securePackProductClass;
  74.     private $requestStack;
  75.     public function __construct(
  76.         EntityManagerInterface $entityManagerInterface,
  77.         SessionInterface $session,
  78.         KernelInterface $kernelInterface,
  79.         EccubeConfig $eccubeConfig,
  80.         CartService $cartService,
  81.         PurchaseFlow $cartPurchaseFlow,
  82.         Security $security,
  83.         UserDataCache $userDataCache,
  84.         RequestStack $requestStack
  85.     ) {
  86.         $this->entityManagerInterface $entityManagerInterface;
  87.         $this->session $session;
  88.         $this->kernelInterface $kernelInterface;
  89.         $this->eccubeConfig $eccubeConfig;
  90.         $this->cartService $cartService;
  91.         $this->purchaseFlow $cartPurchaseFlow;
  92.         $this->security $security;
  93.         $this->requestStack $requestStack;
  94.         $this->setUpValue();
  95.         $this->getSettingFile($this->eccubeConfig);
  96.         $this->securePackProductClass $userDataCache->getSecurePackProductClass();
  97.     }
  98.     public function onRenderProductDetail(TemplateEvent $event)
  99.     {
  100.         $parameters $event->getParameters();
  101.         $product $parameters["Product"];
  102.         $request $this->requestStack->getCurrentRequest();
  103.         $locale $request->getLocale();
  104.         $productId $product->getId();
  105.         // if product is foreign
  106.         if ($locale != Constants::LOCALE_JAPAN) {
  107.             $not_available_dates = [];
  108.         } else {
  109.             $productClassId $product->getProductClasses()[0]->getId();
  110.             $beforeUseDays $this->DEFAULT_BEFORE_USE_DAYS;
  111.             $afterUseDays $this->DEFAULT_AFTER_USE_DAYS;
  112.             // show unavailable days
  113.             $useDays $this->entityManagerInterface->getRepository(ProductUseDays::class)
  114.                 ->findOneBy(["product_id" => $productId]);
  115.             if ($useDays) {
  116.                 $beforeUseDays $useDays->getBeforeUseDays();
  117.                 $afterUseDays $useDays->getAfterUseDays();
  118.             }
  119.             $today date("Y-m-d"strtotime("-10 days"));
  120.             $query $this->entityManagerInterface->createQueryBuilder()
  121.                 ->select("odai")
  122.                 ->from(OrderDetailAdditionalInfo::class, "odai")
  123.                 ->innerJoin(Order::class, 'odr')
  124.                 ->where('odai.product_class_id = :product_class_id and odai.wear_date >= :wear_date')
  125.                 ->andWhere('odai.order_id = odr.id')
  126.                 ->andWhere('odr.OrderStatus <> 3')
  127.                 ->setParameter('product_class_id'$productClassId)
  128.                 ->setParameter('wear_date'$today)
  129.                 ->getQuery();
  130.             $orderDetailAdditionalInfoList $query->getResult();
  131.             $not_available_dates = array();
  132.             foreach ($orderDetailAdditionalInfoList as $orderDetailAdditionalInfo) {
  133.                 if (!empty($orderDetailAdditionalInfo->getBeforeUseDays())) {
  134.                     $beforeUseDays $orderDetailAdditionalInfo->getBeforeUseDays();
  135.                 }
  136.                 if (!empty($orderDetailAdditionalInfo->getAfterUseDays())) {
  137.                     $afterUseDays $orderDetailAdditionalInfo->getAfterUseDays();
  138.                 }
  139.                 $wearDate $orderDetailAdditionalInfo->getWearDate()->format('Y-m-d');
  140.                 $not_available_dates[] = $wearDate;
  141.                 for ($i $beforeUseDays$i 0$i--) {
  142.                     $tmpDate strtotime($wearDate " - {$i} day");
  143.                     $not_available_dates[] = date("Y-m-d"$tmpDate);
  144.                 }
  145.                 for ($i 1$i <= $afterUseDays$i++) {
  146.                     $tmpDate strtotime($wearDate " + {$i} day");
  147.                     $not_available_dates[] = date("Y-m-d"$tmpDate);
  148.                 }
  149.             }
  150.             // Custom grayout manage
  151.             $grayoutDays $this->entityManagerInterface->getRepository(GrayoutManagement::class)
  152.                 ->findBy(["product_id" => $productId]);
  153.             if ($grayoutDays) {
  154.                 $dates = [];
  155.                 foreach ($grayoutDays as $grayoutDay) {
  156.                     $startDate Carbon::parse($grayoutDay->getStartDate());
  157.                     $endDate Carbon::parse($grayoutDay->getEndDate());
  158.                     // When startdate is less than or equal, add 1 day
  159.                     while ($startDate->lte($endDate)) {
  160.                         $dates[] = $startDate->format('Y-m-d');
  161.                         $startDate->addDay();
  162.                     }
  163.                 }
  164.                 $not_available_dates array_merge($not_available_dates$dates);
  165.                 $not_available_dates array_unique($not_available_dates);
  166.                 sort($not_available_dates);
  167.             }
  168.         }
  169.         $parameters += ["not_available_dates" => $not_available_dates];
  170.         $time time();
  171.         $today date("d"$time);
  172.         $year date("Y"$time);
  173.         $month date("m"$time);
  174.         $end_of_month date("t"$time);
  175.         $start_week date('w'strtotime("$year/$month/1"));
  176.         $next_month_time strtotime("$year/$month/1 + 1 month");
  177.         $next_month_year date("Y"$next_month_time);
  178.         $next_month date("m"$next_month_time);
  179.         $next_end_of_month date("t"$next_month_time);
  180.         $next_month_start_week date('w'$next_month_time);
  181.         $parameters += ["year" => intval($year)];
  182.         $parameters += ["current_month" => intval($month)];
  183.         $parameters += ["today" => intval($today)];
  184.         $parameters += ["current_end_of_month" => intval($end_of_month)];
  185.         $parameters += ["start_week" => intval($start_week)];
  186.         $parameters += ["next_month_year" => intval($next_month_year)];
  187.         $parameters += ["next_month" => intval($next_month)];
  188.         $parameters += ["next_end_of_month" => intval($next_end_of_month)];
  189.         $parameters += ["next_month_start_week" => intval($next_month_start_week)];
  190.         $parameters += ["product_id" => $productId];
  191.         $parameters += ["order_type" => ""];
  192.         if ($this->cartService->getCart()) {
  193.             $cartItems $this->cartService->getCart()->getItems();
  194.             foreach ($cartItems as $cartItem) {
  195.                 if ($cartItem->getOrderType()) {
  196.                     $parameters["order_type"] = $cartItem->getOrderType();
  197.                     break;
  198.                 }
  199.             }
  200.         }
  201.         /*
  202.             If you come from a date search, set the search date as the default for ``
  203.             select date of use'' and ``desired store to visit for dressing''. (Date can be changed)
  204.         */
  205.         $searchDate "";
  206.         if ($this->session->has(Constants::SEARCH_DATE)) {
  207.             $searchDate $this->session->get(Constants::SEARCH_DATE);
  208.         }
  209.         $parameters += [Constants::SEARCH_DATE => $searchDate];
  210.         $settings $this->settings;
  211.         $form_settings = [
  212.             "order_type" => Utils::getOrderType($settings),
  213.             "purpose" => Utils::getPurpose($settings),
  214.             "foot_size" => Utils::getFootSize($settings),
  215.             "body_height" => Utils::getBodyHeight($settings),
  216.             "body_type" => Utils::getBodyType($settings),
  217.             "hair_make" => Utils::getHairMake($settings),
  218.             "time_departure" => Utils::getTimeDeparture($settings),
  219.             "visit_store" => Utils::getVisitStore($settings),
  220.             "secure_pack" => Utils::getSecurePack($settings),
  221.             "photo_plan" => Utils::getPhotoPlan($settings),
  222.             "decade" => Utils::getDecade($settings),
  223.             "number_of_guests" => Utils::getNumberOfGuests($settings),
  224.             "gender" => Utils::getGender($settings)
  225.         ];
  226.         $parameters += [Constants::FORM_SETTINGS => $form_settings];
  227.         $event->setParameters($parameters);
  228.     }
  229.     public function onRenderCartIndex(TemplateEvent $event)
  230.     {
  231.         $parameters $event->getParameters();
  232.         $settings $this->settings;
  233.         $parameters += ["secure_pack_code" => $this->securePackProductClass->getCode()];
  234.         $parameters += ["secure_pack_price" => intval($settings["secure_pack"]["price"])];
  235.         $event->setParameters($parameters);
  236.     }
  237.     //getOrderTypeForSession in AKI old
  238.     private function getOrderTypeForCart()
  239.     {
  240.         $orderType "";
  241.         if (!empty($this->cartService->getCart())) {
  242.             $itemList $this->cartService->getCart()->getItems();
  243.             foreach ($itemList as $item) {
  244.                 //order type of cart is the order type of the first kimono product in cart
  245.                 if ($item->getOrderType()) {
  246.                     $orderType $item->getOrderType();
  247.                     break;
  248.                 }
  249.             }
  250.         }
  251.         return $orderType;
  252.     }
  253.     private function getActualPrice()
  254.     {
  255.         $cart $this->cartService->getCart();
  256.         $actual_price 0;
  257.         if (is_null($cart))
  258.             return $actual_price;
  259.         foreach ($cart->getCartItems() as $cartItem) {
  260.             $productClass $cartItem->getProductClass();
  261.             $actual_price += $productClass->getPrice02();
  262.         }
  263.         return $actual_price;
  264.     }
  265.     //onFrontProductDetailInitialize in AKI_D-old
  266.     public function onFrontProductDetailInitialize(EventArgs $event)
  267.     {
  268.         $locale $event->getRequest()->get('_locale') ?? CONSTANTS::LOCALE_JAPAN;
  269.         $isJapanese $locale === Constants::LOCALE_JAPAN;
  270.         /** custom01 */
  271.         $builder $event->getArgument('builder');
  272.         $settings $this->settings;
  273.         // 来店着付け OR 宅配レンタルの隠し項目
  274.         $builder->add(
  275.             Constants::PLG_ORDER_TYPE_NAME,
  276.             HiddenType::class,
  277.             [
  278.                 'required' => true,
  279.                 'label' => false,
  280.                 'mapped' => false,
  281.                 'attr' => array('value' => 'visit'),
  282.                 'constraints' => array(
  283.                     new Assert\NotBlank()
  284.                 )
  285.             ]
  286.         );
  287.         /** custom03 フォーム再構築 */
  288.         // 着用日
  289.         $builder->add(
  290.             Constants::PLG_WEAR_DATE_NAME,
  291.             TextType::class,
  292.             array(
  293.                 'required' => true,
  294.                 'label' => "着用日を選択して下さい",
  295.                 'mapped' => false,
  296.                 'constraints' => array(
  297.                     new Assert\NotBlank(),
  298.                     new Assert\Date()
  299.                 )
  300.             )
  301.         );
  302.         // 用途
  303.         if ($locale === Constants::LOCALE_JAPAN) {
  304.             $builder->add(
  305.                 Constants::PLG_PURPOSE_NAME,
  306.                 ChoiceType::class,
  307.                 array(
  308.                     'required' => true,
  309.                     'label' => "用途:",
  310.                     'mapped' => false,
  311.                     'choices' => Utils::getPurpose($settings),
  312.                     'constraints' => array(
  313.                         new Assert\NotBlank()
  314.                     )
  315.                 )
  316.             );
  317.         }
  318.         if (!$isJapanese) {
  319.             $builder->add(
  320.                 Constants::PLG_NUMBER_OF_GUESTS,
  321.                 ChoiceType::class,
  322.                 [
  323.                     'required' => false,
  324.                     'label' => "number_of_guests",
  325.                     'mapped' => false,
  326.                     'choices' => Utils::getNumberOfGuests($settings),
  327.                 ]
  328.             );
  329.             $builder->add(
  330.                 Constants::PLG_GENDER,
  331.                 ChoiceType::class,
  332.                 [
  333.                     'required' => true,
  334.                     'label' => "Gender",
  335.                     'mapped' => false,
  336.                     'choices' => Utils::getGender($settings),
  337.                     'constraints' => new Assert\Callback([$this'validateEmptyOnNumberOfGuests'])
  338.                 ]
  339.             );
  340.         }
  341.         // 身長
  342.         $builder->add(
  343.             Constants::PLG_BODY_HEIGHT_NAME,
  344.             ChoiceType::class,
  345.             array(
  346.                 'required' => true,
  347.                 'label' => "身長:",
  348.                 'mapped' => false,
  349.                 'choices' => Utils::getBodyHeight($settings),
  350.                 'constraints' => $isJapanese ? [new Assert\NotBlank()] : [new Assert\Callback([$this'validateEmptyOnNumberOfGuests'])]
  351.             )
  352.         );
  353.         // 足のサイズ
  354.         $builder->add(
  355.             Constants::PLG_FOOT_SIZE_NAME,
  356.             ChoiceType::class,
  357.             array(
  358.                 'required' => true,
  359.                 'label' => "足のサイズ:",
  360.                 'mapped' => false,
  361.                 'choices' => Utils::getFootSize($settings),
  362.                 'constraints' => $isJapanese ? [new Assert\NotBlank()] : [new Assert\Callback([$this'validateEmptyOnNumberOfGuests'])]
  363.             )
  364.         );
  365.         if ($locale === Constants::LOCALE_JAPAN) {
  366.             // 年代
  367.             $builder->add(
  368.                 Constants::PLG_DECADE,
  369.                 ChoiceType::class,
  370.                 array(
  371.                     'required' => true,
  372.                     'label' => "年代:",
  373.                     'mapped' => false,
  374.                     'choices' => Utils::getDecade($settings),
  375.                     'constraints' => array(
  376.                         new Assert\NotBlank()
  377.                     )
  378.                 )
  379.             );
  380.         }
  381.         if ($locale != Constants::LOCALE_JAPAN) {
  382.             $builder->add(
  383.                 Constants::PLG_REMARK,
  384.                 TextareaType::class,
  385.                 [
  386.                     'required' => false,
  387.                     'label' => 'Remark',
  388.                     'mapped' => false,
  389.                     'attr' => [
  390.                         'maxlength' => 3000,
  391.                         'rows' => 5,
  392.                     ],
  393.                 ]
  394.             );
  395.         }
  396.         // 体型
  397.         $builder->add(
  398.             Constants::PLG_BODY_TYPE_NAME,
  399.             ChoiceType::class,
  400.             array(
  401.                 'required' => false,
  402.                 'label' => "体型:",
  403.                 'mapped' => false,
  404.                 'choices' => Utils::getBodyType($settings),
  405.                 'expanded' => true,
  406.                 'multiple' => true
  407.             )
  408.         );
  409.         // 安心パック
  410.         $builder->add(
  411.             Constants::PLG_SECURE_PACK_NAME,
  412.             ChoiceType::class,
  413.             array(
  414.                 'required' => false,
  415.                 'label' => "安心パック",
  416.                 'mapped' => false,
  417.                 'choices' => Utils::getSecurePack($settings),
  418.                 'expanded' => true,
  419.                 'multiple' => true
  420.             )
  421.         );
  422.         /**
  423.          * 来店着付けの場合フォームの項目追加
  424.          */
  425.         if ("visit" == $event->getRequest()->request->get("plg_order_type")) {
  426.             // フォト
  427.             $builder->add(
  428.                 Constants::PLG_NEED_PHOTO,
  429.                 ChoiceType::class,
  430.                 array(
  431.                     'required' => false,
  432.                     'label' => "フォト",
  433.                     'mapped' => false,
  434.                     'choices' => Utils::getPhotoPlan($settings)
  435.                 )
  436.             );
  437.             // ヘアメイク有り無し
  438.             $builder->add(
  439.                 Constants::PLG_NEED_HAIR_MAKE,
  440.                 ChoiceType::class,
  441.                 array(
  442.                     'required' => true,
  443.                     'label' => "ヘア・メイクのご希望の有無",
  444.                     'mapped' => false,
  445.                     'choices' => Utils::getHairMake($settings),
  446.                     'constraints' => array(
  447.                         new Assert\NotBlank()
  448.                     )
  449.                 )
  450.             );
  451.             // 来店希望店舗
  452.             $builder->add(
  453.                 Constants::PLG_VISIT_STORE_NAME,
  454.                 ChoiceType::class,
  455.                 array(
  456.                     'required' => false,
  457.                     'label' => "着付けご来店希望店舗",
  458.                     'mapped' => false,
  459.                     'choices' => Utils::getVisitStore($settings)
  460.                 )
  461.             );
  462.             // ご出発予定時間
  463.             $builder->add(
  464.                 Constants::PLG_TIME_DEPARTURE_NAME,
  465.                 ChoiceType::class,
  466.                 array(
  467.                     'required' => true,
  468.                     'label' => "ご出発予定時間",
  469.                     'mapped' => false,
  470.                     'choices' => Utils::getTimeDeparture($settings),
  471.                     'constraints' => array(
  472.                         new Assert\NotBlank(),
  473.                         // new Assert\Time()
  474.                     )
  475.                 )
  476.             );
  477.         }
  478.     }
  479.     public function validateEmptyOnNumberOfGuests($valueExecutionContextInterface $context)
  480.     {
  481.         $form $context->getRoot();
  482.         $numberOfGuest $form->get(Constants::PLG_NUMBER_OF_GUESTS)->getData();
  483.         if ($numberOfGuest == && empty($value)) {
  484.             $context->buildViolation('This field cannot be empty if number of guests is 1.')
  485.                 ->addViolation();
  486.         }
  487.     }
  488.     //onFrontProductDetailComplete in AKI_D-old
  489.     public function onFrontProductAddCartComplete(EventArgs $eventArgs)
  490.     {
  491.         $form $eventArgs->getArgument("form");
  492.         $data = [];
  493.         foreach ($form->all() as $field => $valueForm) {
  494.             $data[$field] = $valueForm->getData();
  495.         }
  496.         // FIXME 安心パック
  497.         $settings $this->settings;
  498.         if (!empty($data[Constants::PLG_SECURE_PACK_NAME])) {
  499.             //create secure_pack item
  500.             $this->cartService->addProductOverride($this->securePackProductClass->getId(), 1);
  501.             $Carts $this->cartService->getCarts();
  502.             foreach ($Carts as $Cart) {
  503.                 $result $this->purchaseFlow->validate($Cart, new PurchaseContext($Cart$this->security->getUser()));
  504.                 // 復旧不可のエラーが発生した場合は追加した明細を削除.
  505.                 if ($result->hasError()) {
  506.                     $this->cartService->removeProduct($this->securePackProductClass->getId());
  507.                     foreach ($result->getErrors() as $error) {
  508.                         $errorMessages[] = $error->getMessage();
  509.                     }
  510.                 }
  511.                 foreach ($result->getWarning() as $warning) {
  512.                     $errorMessages[] = $warning->getMessage();
  513.                 }
  514.             }
  515.             $this->cartService->save();
  516.         }
  517.     }
  518.     public function onRenderShoppingIndex(TemplateEvent $event)
  519.     {
  520.         $parameters $event->getParameters();
  521.         $orderType "";
  522.         $orderDetailAdditionalInfoList $this->getVariantListFromCart();
  523.         if (!empty($orderDetailAdditionalInfoList)) {
  524.             $orderType $orderDetailAdditionalInfoList[0]->getOrderType();
  525.         }
  526.         $parameters += ['orderType' => $orderType];
  527.         $parameters += ['OrderDetailAdditionalInfoList' => $orderDetailAdditionalInfoList];
  528.         $parameters += ["secure_pack_code" => $this->securePackProductClass->getCode()];
  529.         $parameters += ["secure_pack_price" => intval($this->settings["secure_pack"]["price"])];
  530.         $form_settings = ["pay_method" => Utils::getPayMethod($this->settings)];
  531.         $parameters += [Constants::FORM_SETTINGS => $form_settings];
  532.         $event->setParameters($parameters);
  533.     }
  534.     // Before checkout. add ordertype and additional info to the mailtemplate
  535.     public function onControllerShoppingCheckoutBefore(EventArgs $event)
  536.     {
  537.         $cart $this->cartService->getCart();
  538.         $preOrderId $cart["pre_order_id"];
  539.         $Order $this->entityManagerInterface->getRepository(Order::class)->findOneBy(
  540.             [
  541.                 'pre_order_id' => $preOrderId,
  542.                 'OrderStatus' => $this->eccubeConfig['order_processing'],
  543.             ]
  544.         );
  545.         if (!$Order) {
  546.             return;
  547.         }
  548.         $this->session->set("KrAkiCustomizer.orderId"$Order["id"]);
  549.         $orderDetailAdditionalInfoList $this->getVariantListFromCart();
  550.         //Add orderType parameter to mail template
  551.         $orderType "";
  552.         if (!empty($orderDetailAdditionalInfoList)) {
  553.             $orderType $orderDetailAdditionalInfoList[0]->getOrderType();
  554.         }
  555.         $Order->orderDetailInfo $orderDetailAdditionalInfoList;
  556.         $Order->orderType $orderType;
  557.         $this->entityManagerInterface->persist($Order);
  558.         $this->entityManagerInterface->flush();
  559.         $this->entityManagerInterface->getConnection()->commit();
  560.     }
  561.     public function onFrontShoppingCompleteInitialize(EventArgs $event)
  562.     {
  563.         $this->entityManagerInterface->getConnection()->beginTransaction();
  564.         $orderDetailAdditionalInfoList $this->getVariantListFromCart();
  565.         $session $this->session;
  566.         if (empty($orderDetailAdditionalInfoList)) {
  567.             return;
  568.         }
  569.         $orderId $session->get("KrAkiCustomizer.orderId");
  570.         $order $this->entityManagerInterface->getRepository(Order::class)->find($orderId);
  571.         $orderDetails = [];
  572.         foreach ($order->getShippings() as $shipping) {
  573.             foreach ($shipping->getProductOrderItems() as $item) {
  574.                 $orderDetails[] = $item;
  575.             }
  576.         }
  577.         foreach ($orderDetailAdditionalInfoList as $orderDetailAdditionalInfo) {
  578.             foreach ($orderDetails as $orderDetail) {
  579.                 if ($this->isMatchingDetail($orderDetail$orderDetailAdditionalInfo)) {
  580.                     $orderDetailAdditional $this->createOrderDetailAdditional($order$orderDetail$orderDetailAdditionalInfo);
  581.                     $this->entityManagerInterface->persist($orderDetailAdditional);
  582.                     break;
  583.                 }
  584.             }
  585.         }
  586.         $this->entityManagerInterface->flush();
  587.         $this->entityManagerInterface->getConnection()->commit();
  588.         $this->cartService->clear();
  589.     }
  590.     private function isMatchingDetail($orderDetail$orderDetailAdditionalInfo)
  591.     {
  592.         return $orderDetail->getProductClass()->getId() == $orderDetailAdditionalInfo->getProductClass()->getId();
  593.     }
  594.     private function createOrderDetailAdditional($order$orderDetail$orderDetailAdditionalInfo)
  595.     {
  596.         $request $this->requestStack->getCurrentRequest();
  597.         $isJapanese $request->getLocale() == Constants::LOCALE_JAPAN true false;
  598.         $orderDetailAdditional = new OrderDetailAdditionalInfo;
  599.         $orderDetailAdditional->setOrderDetailId($orderDetail->getId());
  600.         $orderDetailAdditional->setOrderId($order->getId());
  601.         $orderDetailAdditional->setProductClassId(intval($orderDetailAdditionalInfo->getProductClass()->getId()));
  602.         $bodyType $orderDetailAdditionalInfo->getBodyType();
  603.         if (!empty($bodyType)) {
  604.             $orderDetailAdditional->setBodyType(($bodyType));
  605.         } else {
  606.             $orderDetailAdditional->setBodyType(null);
  607.         }
  608.         $secure_pack $orderDetailAdditionalInfo->getSecurePack();
  609.         if (!empty($secure_pack)) {
  610.             $orderDetailAdditional->setSecurePack($secure_pack[0]);
  611.         } else {
  612.             $orderDetailAdditional->setSecurePack(null);
  613.         }
  614.         $orderDetailAdditional->setActualPrice($orderDetail->getProductClass()->getPrice02());
  615.         $orderType $orderDetailAdditionalInfo->getOrderType();
  616.         if ($orderType === 'fitting') {
  617.             $beforeUseDays Constants::FITTING_BEFORE_USE_DAYS;
  618.             $afterUseDays Constants::FITTING_AFTER_USE_DAYS;
  619.         } else {
  620.             $beforeUseDays $this->DEFAULT_BEFORE_USE_DAYS;
  621.             $afterUseDays $this->DEFAULT_AFTER_USE_DAYS;
  622.         }
  623.         if ($_SERVER['SERVER_NAME'] !== env("SALON_URL")) {
  624.             $productId $orderDetail->getProduct()->getId();
  625.             $useDays $this->entityManagerInterface->getRepository(ProductUseDays::class)->findOneBy([
  626.                 "product_id" => $productId
  627.             ]);
  628.             if ($useDays) {
  629.                 $beforeUseDays $useDays['before_use_days'];
  630.                 $afterUseDays $useDays['after_use_days'];
  631.             }
  632.         }
  633.         if ($isJapanese) {
  634.             $orderDetailAdditional->setBeforeUseDays($beforeUseDays);
  635.             $orderDetailAdditional->setAfterUseDays($afterUseDays);
  636.         }
  637.         //-------------------------------------------------------------
  638.         $orderDetailAdditional->setOrderType($orderDetailAdditionalInfo->getOrderType());
  639.         $orderDetailAdditional->setWearDate($orderDetailAdditionalInfo->getWearDate());
  640.         $orderDetailAdditional->setPurpose($orderDetailAdditionalInfo->getPurpose());
  641.         $orderDetailAdditional->setBodyHeight($orderDetailAdditionalInfo->getBodyHeight());
  642.         $orderDetailAdditional->setFootSize($orderDetailAdditionalInfo->getFootSize());
  643.         $orderDetailAdditional->setNeedPhoto($orderDetailAdditionalInfo->getNeedPhoto());
  644.         $orderDetailAdditional->setNeedHairMake($orderDetailAdditionalInfo->getNeedHairMake());
  645.         // $orderDetailAdditional->setDateVisit(); => date_visit alway null
  646.         $orderDetailAdditional->setTimeDeparture($orderDetailAdditionalInfo->getTimeDeparture());
  647.         $orderDetailAdditional->setVisitStore($orderDetailAdditionalInfo->getVisitStore());
  648.         $orderDetailAdditional->setDecade($orderDetailAdditionalInfo->getDecade());
  649.         $orderDetailAdditional->setRemark($orderDetailAdditionalInfo->getRemark());
  650.         $orderDetailAdditional->setGender($orderDetailAdditionalInfo->getGender());
  651.         if (!$isJapanese) {
  652.             $orderDetailAdditional->setNumberOfGuests($orderDetailAdditionalInfo->getNumberOfGuests());
  653.         }
  654.         return $orderDetailAdditional;
  655.     }
  656.     public function getVariantListFromCart()
  657.     {
  658.         $orderDetailAddtionalList = [];
  659.         if ($this->cartService->getCart()) {
  660.             foreach ($this->cartService->getCart()->getItems() as $cartItem) {
  661.                 // if cart item is not secure_pack
  662.                 if ($cartItem->getProductClass()->getId() != $this->securePackProductClass->getId()) {
  663.                     $orderDetailAddtionalList[] = $cartItem;
  664.                 }
  665.             }
  666.         }
  667.         return $orderDetailAddtionalList;
  668.     }
  669.     public static function getSubscribedEvents()
  670.     {
  671.         return [
  672.             EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE => 'onFrontProductDetailInitialize',
  673.             EccubeEvents::FRONT_PRODUCT_CART_ADD_INITIALIZE => 'onFrontProductDetailInitialize',
  674.             EccubeEvents::FRONT_PRODUCT_CART_ADD_COMPLETE => 'onFrontProductAddCartComplete',
  675.             'Product/detail.twig' => 'onRenderProductDetail',
  676.             'Cart/index.twig' => 'onRenderCartIndex',
  677.             'Shopping/index.twig' => 'onRenderShoppingIndex',
  678.             'Shopping/confirm.twig' => 'onRenderShoppingIndex',
  679.             'FRONT_SHOPPING_CHECKOUT_BEFORE' => 'onControllerShoppingCheckoutBefore',
  680.             'onProcessingWhenOrderSuccess' => 'onFrontShoppingCompleteInitialize'
  681.         ];
  682.     }
  683. }