app/Customize/Service/CartService.php line 369

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 Customize\Service;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use Eccube\Entity\Cart;
  15. use Eccube\Entity\CartItem;
  16. use Eccube\Entity\ProductClass;
  17. use Eccube\Repository\CartRepository;
  18. use Eccube\Repository\CartItemRepository;
  19. use Eccube\Repository\OrderRepository;
  20. use Eccube\Repository\ProductClassRepository;
  21. use Eccube\Service\Cart\CartItemAllocator;
  22. use Eccube\Service\Cart\CartItemComparator;
  23. use Customize\Service\OrderHelper;
  24. use Eccube\Util\StringUtil;
  25. use Lm\Engine\EC\Entity\GoodsExtended;
  26. use Lm\Entity\Sku;
  27. use Lm\Service\Db\SqlService;
  28. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  29. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  30. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  31. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  32. use Symfony\Component\DependencyInjection\ContainerInterface;
  33. use Eccube\Common\EccubeConfig;
  34. class CartService extends \Eccube\Service\CartService
  35. {
  36.     const CartTypeNormal 1#通常
  37.     const CartTypeEstimate 2#見積シミュレーション
  38.     const CartTypeSample 3#サンプル
  39.     const CartTypeCatalog 4#カタログ
  40.     const CartTypeComposite 9#複合
  41.     const Estimate_Type_Print 2#プリント
  42.     const Estimate_Type_Susoage 1#裾上げ
  43.     const Session_ExclusionControlFlg 'Session_ExclusionControlFlg';
  44.     const Matrix_name 'product_matrix';
  45.     const DummyEstimateId 'xx';
  46.     const CartTypeRepeat '101'#リピート時 カートに商品がある
  47.     const RepeatError01 'RepeatError01';
  48.     const RepeatError02 'RepeatError02';
  49.     const RepeatError03 'RepeatError03';
  50.     const SaveCartType 'Session_SaveCartType';
  51.     /**
  52.      * ルーティング名 - 「カートに入れる」関連
  53.      */
  54.     const ROUTE_ADD_NORMAL 'add_Normal';
  55.     const ROUTE_VALID_ESTIMATE 'valid_estimate';
  56.     const ROUTE_ADD_ESTIMATE 'add_estimate';
  57.     const ROUTE_ADD_SAMPLE 'add_sample';
  58.     const ROUTE_ADD_CATALOG 'add_catalog';
  59.     const ROUTE_ADD_LINE 'add_line';
  60.     const ROUTE_ADD_HYBRID 'add_hybrid';
  61.     const ROUTE_ADD_REPEAT 'add_repeat';
  62.     /**
  63.      * Case can mix susoage and print:
  64.      * Option 1:
  65.      * 伝票1 BILL_1 = Type 1 (normal) + Kyoei (type 1 normal) + Type 1 (reservation) + Kyoei (type 1 reservation) + susoage (normal + reservation)
  66.      * 伝票2 BILL_2 = Print (type 2 normal + reservation)
  67.      * 伝票3 BILL_3 = Kyoei (type 2 normal + reservation)
  68.      *  Option 2:
  69.      * 伝票1 BILL_1 = Type 1 (normal) + Kyoei (type 1 normal)
  70.      * 伝票2 BILL_2 = Print (type 2 normal + reservation)
  71.      * 伝票3 BILL_3 = Kyoei (type 2 normal + reservation)
  72.      * 伝票4 BILL_4 = Type 1 (reservation) + Kyoei (type 1 reservation) + susoage (normal + reservation)
  73.     */
  74.     const BILL_1 "BILL_1";
  75.     const BILL_2 "BILL_2";
  76.     const BILL_3 "BILL_3";
  77.     const BILL_4 "BILL_4";
  78.     const GROUP_NORMAL 'GROUP_1_NORMAL';
  79.     const GROUP_RESERVATION 'GROUP_2_RESERVATION';
  80.     const GROUP_KYOUEI_WITH_NAIRE_PRINT 'GROUP_3_KYOUEI';
  81.     const SESSION_BULK_CHECKOUT_ENABLED 'cart.bulk_checkout.enabled';
  82.     protected $GoodsService;
  83.     protected $orderHelper;
  84.     protected $CartType 0;
  85.     protected $Quantitys;
  86.     protected $EstimateId 0#見積ID
  87.     protected $Container;
  88.     protected $MergeFlg true#商品が追加された場合 マージか アッドか?
  89.     protected $CartItemRepository;
  90.     protected $ProductClass = [];
  91.     protected $NewItems = [];
  92.     protected $ValidationData = [];
  93.     protected $CartItemIds = [];
  94.     protected $Estimates;
  95.     protected $EstimateOption = [];
  96.     protected $EccubeConfig;
  97.     /**
  98.      * @var array
  99.      */
  100.     protected $_buffer;
  101.     public function __construct(
  102.         SessionInterface              $session,
  103.         EntityManagerInterface        $entityManager,
  104.         ProductClassRepository        $productClassRepository,
  105.         CartRepository                $cartRepository,
  106.         CartItemComparator            $cartItemComparator,
  107.         CartItemAllocator             $cartItemAllocator,
  108.         OrderRepository               $orderRepository,
  109.         TokenStorageInterface         $tokenStorage,
  110.         AuthorizationCheckerInterface $authorizationChecker,
  111.         ContainerInterface            $Container,
  112.         CartItemRepository            $CartItemRepository,
  113.         EccubeConfig                  $EccubeConfig,
  114.         GoodsService                  $GoodsService,
  115.         OrderHelper                   $orderHelper
  116.     )
  117.     {
  118.         //
  119.         parent::__construct($session$entityManager$productClassRepository$cartRepository$cartItemComparator$cartItemAllocator$orderRepository$tokenStorage$authorizationChecker);
  120.         //
  121.         $this->Container $Container;
  122.         $this->CartItemRepository $CartItemRepository;
  123.         $this->EccubeConfig $EccubeConfig;
  124.         $this->orderHelper $orderHelper;
  125.     }
  126.     /**
  127.      * カートに商品を追加します.
  128.      * @param int $ProductClass 商品規格
  129.      * @param int $quantity 数量
  130.      * @param false|bool $noOptions
  131.      * @return bool 商品を追加できた場合はtrue
  132.      */
  133.     public function addProduct($ProductClass$quantity 1$noOptions false)
  134.     {
  135.         if (!$ProductClass instanceof ProductClass) {
  136.             $ProductClassId $ProductClass;
  137.             $ProductClass $this->entityManager
  138.                 ->getRepository(ProductClass::class)
  139.                 ->find($ProductClassId);
  140.             if (is_null($ProductClass)) {
  141.                 return false;
  142.             }
  143.         }
  144.         // use logic calculator in cart, and set for new Order
  145.         $ClassCategory1 $ProductClass->getClassCategory1();
  146.         $Patan $this->EccubeConfig['ESTIMATE_WHOIT_ONLY'];
  147.         if (!preg_match($Patan$ClassCategory1->getBackendname()) && !empty($this->Estimates)) {
  148.             $optionObject json_decode($this->Estimates,true);
  149.             $optionObject["white_only"] = 2;
  150.             $this->SetEstimates($optionObject);
  151.         }
  152.         if ($ClassCategory1 && !$ClassCategory1->isVisible()) {
  153.             return false;
  154.         }
  155.         $ClassCategory2 $ProductClass->getClassCategory2();
  156.         if ($ClassCategory2 && !$ClassCategory2->isVisible()) {
  157.             return false;
  158.         }
  159.         $newItem = new CartItem();
  160.         $newItem->setQuantity($quantity);
  161.         $newItem->setPrice($ProductClass->getPrice02IncTax());
  162.         $newItem->setProductClass($ProductClass);
  163.         //
  164.         if (!$noOptions) {
  165.             $newItem->setOptions($this->Estimates);
  166.         }
  167.         #見積もりIDの追加
  168.         $this->SetEstimateId();
  169.         $newItem->setEstimateId($this->EstimateId);
  170.         $allCartItems $this->mergeAllCartItems_2([$newItem]);
  171.         $this->restoreCarts($allCartItems);
  172.         return true;
  173.     }
  174.     /**
  175.      * @param CartItem[] $cartItems
  176.      *
  177.      * @return CartItem[]
  178.      *
  179.      * mergeCartItemsを2回読んでいるが
  180.      * 1度目は $allCartItems が空の配列なので Cart->getCartItems()を$allCartItems へ置き換えているだけ
  181.      * 2度目は $allCartItems==  Cart->getCartItems() で 2度目で始めたマージしている
  182.      * クーロンすれば ?
  183.      */
  184.     protected function mergeAllCartItems_2($cartItems = [])
  185.     {
  186.         /** @var CartItem[] $allCartItems */
  187.         //$allCartItems=[];
  188.         /**
  189.          * @var Object $allCartItems
  190.          */
  191.         $allCartItems count($this->getCarts()) > ? [] : (object)$cartItems;
  192.         foreach ($this->getCarts() as $Cart) {
  193.             // $allCartItems = $this->mergeCartItems($Cart->getCartItems(), $allCartItems);
  194.             $allCartItems $this->mergeCartItems_2($cartItems$Cart->getCartItems());
  195.         }
  196.         return clone $allCartItems;
  197.         // return $this->mergeCartItems($cartItems, $allCartItems);
  198.     }
  199.     /**
  200.      * @param $cartItems
  201.      * @param $allCartItems
  202.      *
  203.      * @return array
  204.      */
  205.     protected function mergeCartItems_2($cartItems$allCartItems)
  206.     {
  207.         foreach ($cartItems as $item) {
  208.             $itemExists false;
  209.             foreach ($allCartItems as $i => $itemInArray) {
  210.                 if (!= $itemInArray->getEstimateId()) {
  211.                     continue;
  212.                 }
  213.                 // 同じ明細があればマージする
  214.                 if ($this->cartItemComparator->compare($item$itemInArray) && $this->MergeFlg) {
  215.                     $itemInArray->setQuantity($itemInArray->getQuantity() + $item->getQuantity());
  216.                     $itemExists true;
  217.                     break;
  218.                 }
  219.             }
  220.             if (!$itemExists) {
  221.                 $allCartItems[] = $item;
  222.             }
  223.         }
  224.         return $allCartItems;
  225.     }
  226.     /**
  227.      * カートを更新します。
  228.      *
  229.      * @param $CartItemId int CartItem ID
  230.      * @param $ProductClass ProductClass 商品規格
  231.      * @param $quantity int 数量
  232.      * @param $options text オプション(見積りシミュレーションの結果、など)
  233.      *
  234.      * @return bool 商品を追加できた場合はtrue
  235.      */
  236.     public function updateCartItem($CartItemId$ProductClass$quantity 1$options "")
  237.     {
  238.         if (!$ProductClass instanceof ProductClass) {
  239.             $ProductClassId $ProductClass;
  240.             $ProductClass $this->entityManager
  241.                 ->getRepository(ProductClass::class)
  242.                 ->find($ProductClassId);
  243.             if (is_null($ProductClass)) {
  244.                 return false;
  245.             }
  246.         }
  247.         $ClassCategory1 $ProductClass->getClassCategory1();
  248.         if ($ClassCategory1 && !$ClassCategory1->isVisible()) {
  249.             return false;
  250.         }
  251.         $ClassCategory2 $ProductClass->getClassCategory2();
  252.         if ($ClassCategory2 && !$ClassCategory2->isVisible()) {
  253.             return false;
  254.         }
  255.         $newItem = new CartItem();
  256.         $newItem->setQuantity($quantity);
  257.         $newItem->setPrice($ProductClass->getPrice02IncTax());
  258.         $newItem->setProductClass($ProductClass);
  259.         $newItem->setOptions($options);
  260.         $allCartItems $this->mergeAllCartItems([$newItem]);
  261.         $this->restoreCarts($allCartItems);
  262.         return true;
  263.     }
  264.     /**
  265.      * EC-CUBEのカートデータを旧UTのカートデータに変換する
  266.      *
  267.      * @return array
  268.      * [
  269.      *   'cart' => [],
  270.      *   'tmp_cart' => [],
  271.      * ]
  272.      */
  273.     public function convertToLmCart()
  274.     {
  275.         $carts $this->getCart();
  276.         $lmCart = [];
  277.         foreach ($carts as $key => $value) {
  278.             if ($key === 'hoge') {
  279.                 $lmCart['cart']['piyo'] = $value;
  280.             } else if ($key === 'piyo') {
  281.                 $lmCart['tmp_cart']['piyo'] = $value;
  282.             }
  283.         }
  284.         return $lmCart;
  285.     }
  286.     public function save()
  287.     {
  288.         $cartKeys = [];
  289.         foreach ($this->carts as $Cart) {
  290.             $Tatal 0;
  291.             $Cart->setCustomer($this->getUser());
  292.             if (is_null($Cart->getDeliveryFeeTotal())) {
  293.                 $Cart->setDeliveryFeeTotal(0);
  294.             }
  295.             #2022/10/20 カートタイプを登録する 修正
  296.             if ($this->CartType) {
  297.                 $CartType $this->CartType == self::CartTypeComposite self::CartTypeEstimate $this->CartType;
  298.                 if ($Cart->getCartType() != $CartType) {
  299.                     $Cart->setCartType($CartType);
  300.                 }
  301.             }
  302.             $this->entityManager->persist($Cart);
  303.             foreach ($Cart->getCartItems() as $item) {
  304.                 $Tatal += $item->getPrice() * $item->getQuantity();
  305.                 $this->entityManager->persist($item);
  306.             }
  307.             if (is_null($Cart->getTotalPrice())) {
  308.                 $Cart->setTotalPrice($Tatal);
  309.             }
  310.             try {
  311.                 if (empty($Cart->CartType) || $Cart->CartType == 'null'){
  312.                     log_debug("[LM]Create Cart empty cart_type: CartInfo", [
  313.                         "Cart" => $Cart,
  314.                         "CartItem" => $Cart->getCartItems()
  315.                     ]);
  316.                 }
  317.             } catch (\Exception $exception){
  318.                 log_error("[LM]Create Cart EMPTY cart_type ERROR-  " $exception->getMessage());
  319.             }
  320.             $this->entityManager->flush();
  321.             $cartKeys[] = $Cart->getCartKey();
  322.         }
  323.         $this->session->set('cart_keys'$cartKeys);
  324.         return;
  325.     }
  326.     protected function restoreCarts($cartItems)
  327.     {
  328.         foreach ($this->getCarts() as $Cart) {
  329.             foreach ($Cart->getCartItems() as $i) {
  330.                 $this->entityManager->remove($i);
  331.                 $this->entityManager->flush();
  332.             }
  333.             $this->entityManager->remove($Cart);
  334.             $this->entityManager->flush();
  335.         }
  336.         $this->carts = [];
  337.         /** @var Cart[] $Carts */
  338.         $Carts = [];
  339.         foreach ($cartItems as $item) {
  340.             $allocatedId $this->cartItemAllocator->allocate($item);
  341.             $cartKey $this->createCartKey($allocatedId$this->getUser());
  342.             if (isset($Carts[$cartKey])) {
  343.                 $Cart $Carts[$cartKey];
  344.                 $Cart->addCartItem($item);
  345.                 #2022/03/28 カートタイプを登録する 4/7修正
  346. #                if($this->CartType){
  347. #                    $Cart->setCartType($this->CartType);
  348. #                }
  349.                 $item->setCart($Cart);
  350.             } else {
  351.                 #/ ** @var Cart $Cart * /
  352.                 $Cart $this->cartRepository->findOneBy(['cart_key' => $cartKey]);
  353.                 if ($Cart) {
  354.                     foreach ($Cart->getCartItems() as $i) {
  355.                         $this->entityManager->remove($i);
  356.                         $this->entityManager->flush();
  357.                     }
  358.                     $this->entityManager->remove($Cart);
  359.                     $this->entityManager->flush();
  360.                 }
  361.                 $Cart = new Cart();
  362.                 $Cart->setCartKey($cartKey);
  363.                 $Cart->addCartItem($item);
  364.                 #2022/03/28 カートタイプを登録する 4/7修正
  365. #                if($this->CartType){
  366. #                    $Cart->setCartType($this->CartType);
  367. #                }
  368.                 $item->setCart($Cart);
  369.                 $Carts[$cartKey] = $Cart;
  370.             }
  371.         }
  372.         $this->carts array_values($Carts);
  373.     }
  374.     /**
  375.      * 2022/06/16 tkgoya
  376.      *
  377.      * @return int|void
  378.      */
  379.     public function GetCartType($Flg false)
  380.     {
  381.         //
  382.         //return $this->CartHelper->GetCartType($Flg);
  383.         $Carts $this->getCarts();
  384.         if (count($Carts) < 1) {
  385.             return $Flg ?? $this->session->get(self::SaveCartType) ?? 0;
  386.         }
  387.         foreach ($Carts as $Cart) {
  388.             $this->session->set(self::SaveCartType$Cart->getCartType());
  389.             return $Cart->getCartType();
  390.         }
  391.     }
  392.     /**
  393.      * 2022/03/28 Kakeru
  394.      *
  395.      * @param int $CartType
  396.      *
  397.      */
  398.     public function SetCartType($CartType)
  399.     {
  400.         if ($this->CartType == $CartType) {
  401.             return;
  402.         }
  403.         $this->CartType $CartType;
  404.         /*foreach ($this->getCarts() as $Cart) {
  405.             $Cart->setCartType($CartType);
  406.             $this->entityManager->persist($Cart);
  407.             $this->entityManager->flush();
  408.         }*/
  409.     }
  410.     /** 20220409
  411.      * 会員が保持する永続化されたカートと、非会員時のカートをマージする.
  412.      * 2022/07 カートに商品がある場合は前回の商品はマージしない
  413.      */
  414.     public function mergeFromPersistedCart()
  415.     {
  416.         $sessionCarts $this->getSessionCarts();
  417.         $persistedCarts = [];
  418.         if (count($sessionCarts) < 1) {
  419.             $persistedCarts $this->getPersistedCarts();
  420.         }
  421.         $CartItems = [];
  422.         // 永続化されたカートとセッションのカートが同一の場合はマージしない #4574
  423.         $cartKeys $this->session->get('cart_keys', []);
  424.         if ((count($persistedCarts) > 0) && !in_array($persistedCarts[0]->getCartKey(), $cartKeystrue)) {
  425.             foreach ($persistedCarts as $Cart) {
  426.                 $this->CartType $Cart->getCartType();
  427.                 $CartItems $this->mergeCartItems($Cart->getCartItems(), $CartItems);
  428.             }
  429.         }
  430.         // セッションにある非会員カートとDBから取得した会員カートをマージする.
  431.         foreach ($sessionCarts as $Cart) {
  432.             $this->CartType $Cart->getCartType();
  433.             $CartItems $this->mergeCartItems($Cart->getCartItems(), $CartItems);
  434.         }
  435.         $this->restoreCarts($CartItems);
  436.     }
  437.     /**
  438.      * カートの合計数を ClassId で取得する
  439.      *
  440.      * @param int $ClassId
  441.      *
  442.      * @return int $Quantity
  443.      */
  444.     public function getQuantitys($ClassId)
  445.     {
  446.         if (!$this->Quantitys) {
  447.             if (!$Carts $this->getCarts()) {
  448.                 return 0;
  449.             };
  450.             foreach ($Carts as $Cart) {
  451.                 if (!$Items $Cart->getItems()) {
  452.                     return 0;
  453.                 }
  454.                 foreach ($Items as $Item) {
  455.                     if (!$Item->isProduct()) {
  456.                         continue;
  457.                     }
  458.                     $Class $Item->getProductClass();
  459.                     $Id $Class->getId();
  460.                     $this->Quantitys[$Id] = $this->Quantitys[$Id] ?? 0;
  461.                     $this->Quantitys[$Id] += $Item->getQuantity();
  462.                 }
  463.             }
  464.         }
  465.         return $this->Quantitys[$ClassId] ?? 0;
  466.     }
  467.     /**
  468.      * EstimateIdの設定
  469.      *
  470.      *
  471.      */
  472.     public function SetEstimateId($Id null)
  473.     {
  474.         if ($Id) {
  475.             $this->EstimateId $Id;
  476.             return;
  477.         }
  478.         # 1  通常と加工の混在
  479.         if ($this->CartType == self::CartTypeComposite) {
  480. # 10/20     $this->CartType =  self::CartTypeNormal;
  481.             $this->EstimateId 0;
  482.             return;
  483.         }
  484.         #加工でなければ
  485.         if ($this->CartType != self::CartTypeEstimate) {
  486.             return;
  487.         }
  488.         #3 既に設定している
  489.         if ($this->EstimateId !== 0) {
  490.             return;
  491.         }
  492.         #4EstimateIdの作成
  493.         $this->MergeFlg false;
  494.         $this->EstimateId $this->getMaxEstimateId() + 1;
  495.         return;
  496.     }
  497.     public function getMaxEstimateId()
  498.     {
  499.         $em $this->Container->get('doctrine.orm.entity_manager');
  500.         $Qb $em->createQueryBuilder();
  501.         $MaxEstimateId $Qb
  502.             ->select('COALESCE(MAX(CI.EstimateId), 0)')
  503.             ->from("Eccube\\Entity\\CartItem"'CI')
  504.             ->getQuery()
  505.             ->getSingleResult();
  506.         return $MaxEstimateId[1] ?? 0;
  507.     }
  508.     /**
  509.      * GetEstimateId を返す
  510.      * @return int $this->EstimateId;
  511.      */
  512.     public function GetEstimateId()
  513.     {
  514.         return $this->EstimateId;
  515.     }
  516.     public function getLmCartItems()
  517.     {
  518.         #カートが空なら
  519.         if (count($this->carts) < 1) {
  520.             return [];
  521.         }
  522.         $Cart $this->carts[0];
  523.         #カタログなら
  524.         if ($Cart->getCartType() == self::CartTypeCatalog) {
  525.             return [];
  526.         }
  527.         $em $this->Container->get('doctrine.orm.entity_manager');
  528.         $Qb $em->createQueryBuilder();
  529.         $Items $Qb
  530.             ->select('CI')
  531.             ->from("Eccube\\Entity\\CartItem"'CI')
  532.             ->innerJoin('CI.ProductClass''pc')
  533.             ->orderBy('pc.Product''ASC')
  534.             ->addOrderBy('CI.EstimateId''ASC')
  535.             ->addOrderBy('CI.id''ASC')
  536.             ->where('CI.Cart = :cart')
  537.             ->setParameter('cart'$Cart)
  538.             ->getQuery()
  539.             ->getResult();
  540.         $Cart->setCartItems($Items);
  541.         return;
  542.     }
  543.     public function GetProductClass($ProductClassId)
  544.     {
  545.         if (isset($this->ProductClass[$ProductClassId])) {
  546.             return $this->ProductClass[$ProductClassId];
  547.         }
  548.         $this->ProductClass[$ProductClassId] = $this->entityManager
  549.             ->getRepository(ProductClass::class)
  550.             ->find($ProductClassId);
  551.         return $this->ProductClass[$ProductClassId];
  552.     }
  553.     /**
  554.      * @param int $CartItemId
  555.      * @return $this
  556.      */
  557.     public function RemoveItem($CartItemId)
  558.     {
  559.         $this->CartType $this->GetCartType();
  560.         $CartItems = [];
  561.         $Flg true;
  562.         $productClassIdDeleted '';
  563.         $estimateIdDeleted '';
  564.         foreach ($this->getCarts() as $Cart) {
  565.             foreach ($Cart->getCartItems() as $CartItem) {
  566.                 if ($CartItemId == $CartItem->getId()) {
  567.                     $productClassIdDeleted $CartItem->getProductClass()->getId()??'';
  568.                     $estimateIdDeleted $CartItem->getEstimateId();
  569.                 }
  570.             }
  571.             foreach ($Cart->getCartItems() as $CartItem) {
  572.                 if ($CartItemId == $CartItem->getId()) {
  573.                     continue;
  574.                 }
  575.                 $cartItemOptions $CartItem->getOptions();
  576.                 $cartItemOptions json_decode($cartItemOptions,true);
  577.                 if($CartItem->getEstimateId() == $estimateIdDeleted && isset($cartItemOptions['susoage']) && is_array($cartItemOptions['susoage'])){
  578.                     if(isset($cartItemOptions['susoage'][$productClassIdDeleted]) && is_array($cartItemOptions['susoage'][$productClassIdDeleted])){
  579.                         foreach ($cartItemOptions['susoage'][$productClassIdDeleted] as &$item){
  580.                             $item['do'] = 0;
  581.                         }
  582.                     }
  583.                 }
  584.                 $cartItemOptions $cartItemOptions json_encode($cartItemOptions) : null;
  585.                 if (!empty($cartItemOptions)) {
  586.                     $this->SetEstimateOption($CartItem->getEstimateId(), $CartItem->getProductClass(), $CartItem->getQuantity(), $cartItemOptions);
  587.                 }
  588.                 $CartItems[] = clone $CartItem;
  589.                 if ($CartItem->getEstimateId()) {
  590.                     $Flg false;
  591.                 }
  592.             }
  593.         }
  594.         #加工と 通常混在の場合 加工を削除すると 
  595.         if ($this->CartType == self::CartTypeEstimate && $Flg) {
  596.             $this->CartType self::CartTypeNormal;
  597.         }
  598.         $this->restoreCarts($CartItems);
  599.         $this->save();
  600.         return $this;
  601.     }
  602.     /**
  603.      * カートにてDATaの追加変更を行う
  604.      * @param $Datas
  605.      */
  606.     public function AddCartLine($Datas)
  607.     {
  608.         $Items = [];
  609.         $Options = [];
  610.         foreach ($this->getCarts() as $Cart) {
  611.             $this->CartType $Cart->getCartType();
  612.             foreach ($Cart->getCartItems() as $Item) {
  613.                 $Items[$Item->getId()] = $Item;
  614. //                $Options[$Item->getEstimateId()] = $Item->getOptions();
  615.             }
  616.         }
  617.         $Errors = [];
  618.         $AddLineFlg false;
  619.         foreach ($Datas as $EstimateId => $Data) {
  620.             $Options null;
  621.             foreach ($Data as $ItemId => $Product) {
  622.                 $ProductClass null;
  623.                 if (is_numeric($ItemId)) {
  624.                     $Item $Items[$ItemId] ?? null# もしエラーなら
  625.                     if($Item != null){
  626.                         if ($ProductClass $Item->getProductClass()) { #もしえらーなら 下記もエラー
  627.                             $ClassCategory1 $ProductClass->getClassCategory1();
  628.                             $ClassCategory2 $ProductClass->getClassCategory2();
  629.                         }
  630.                         $Options $Item->getOptions();
  631.                     } else {
  632.                         $Options null;
  633.                     }
  634.                     switch (true) {
  635.                         case !$Item || !$ProductClass:
  636.                             $Errors[0] = 13;
  637.                             break;
  638.                         #内容が同じなら
  639.                         case $ClassCategory1->getId() == $Product['color']
  640.                             && $ClassCategory2->getId() == $Product['size']
  641.                             && $Item->getQuantity() == $Product['quantity']:
  642.                             $this->AddValidationData($ProductClass$Product['quantity']);
  643.                             $this->NewItems[] = clone $Item;
  644.                             break;
  645.                         default :
  646.                             $AddLineFlg true;
  647.                             if (== $Product['quantity']) {
  648.                                 $Errors[$ProductClass->getId()] = 8;
  649.                             }
  650.                             $ProductClass $this->AddNewItem($Product$EstimateId$Options);
  651.                             break;
  652.                     }
  653.                     #新規套路
  654.                 } else {
  655.                     if ($Product['quantity']) {
  656.                         if (is_numeric($Product['quantity'])) {
  657.                             $Ids explode('-'$ItemId);
  658.                             $Product['product'] = $Ids[1] ?? null;
  659.                             $AddLineFlg true;
  660.                             $ProductClass $this->AddNewItem($Product$EstimateId$Options$ItemId);
  661.                         } else {
  662.                             $Errors[$ItemId] = 4;
  663.                         }
  664.                     }
  665.                 }
  666.                 #2022/09/09 見積シミュレーション options 内容変更
  667.                 if (!empty($Options)) {
  668.                     $this->SetEstimateOption($EstimateId$ProductClass$Product['quantity'], $Options);
  669.                 }
  670.             }
  671.         }
  672.         if (!$AddLineFlg) {
  673.             $Errors[0] = 14;
  674.         }
  675.         return [$this->ValidationData$Errors];
  676.     }
  677.     protected function AddNewItem($Product$EstimateId$Options$ItemId null)
  678.     {
  679.         $ProductId $Product['product'];
  680.         $ClassCategoryId1 $Product['color'];
  681.         $ClassCategoryId2 $Product['size'];
  682.         $Quantity $Product['quantity'];
  683.         $ProductClass $this->productClassRepository->findOneBy(['Product' => $ProductId,
  684.             'ClassCategory1' => $ClassCategoryId1,
  685.             'ClassCategory2' => $ClassCategoryId2,
  686.         ]);
  687. #            echo $ProductId.':'. $ClassCategoryId1 .';'. $ClassCategoryId2;
  688. #            echo gettype($ProductClass);
  689.         #キャッシュとバリデーションDATA 保存
  690.         if ($ProductClass) {
  691.             $this->AddValidationData($ProductClass$Product['quantity']);
  692.         }
  693.         #追加アイテムの保存
  694.         if ($ItemId) {
  695.             $this->CartItemIds[$ProductClass->getId()][] = $ItemId;
  696.         }
  697.         $newItem = new CartItem();
  698.         $newItem->setQuantity($Quantity)
  699.             ->setPrice($ProductClass->getPrice02IncTax())
  700.             ->setProductClass($ProductClass)
  701.             ->setOptions($Options)
  702.             ->setEstimateId($EstimateId);
  703.         $this->NewItems[] = $newItem;
  704.         return $ProductClass;
  705.     }
  706.     /*
  707.     * 行の追加で 同じEstimateIde で 同じProductId で 同じ ProductClassId の場合マージする
  708.     *
  709.     */
  710.     protected function MergeNewItem()
  711.     {
  712.         $NewItems = [];
  713.         foreach ($this->NewItems as $Item) {
  714.             $ProductClass $Item->getProductClass();
  715.             $Product $ProductClass->getProduct();
  716.             $EstimateId $Item->getEstimateId();
  717.             $ProductId $Product->getId();
  718.             $ProductClassId $ProductClass->getId();
  719.             if (isset($NewItems[$EstimateId][$ProductId][$ProductClassId])) {
  720.                 $Quantity $NewItems[$EstimateId][$ProductId][$ProductClassId]->getQuantity() + $Item->getQuantity();
  721.                 $NewItems[$EstimateId][$ProductId][$ProductClassId]->setQuantity($Quantity);
  722.             } else {
  723.                 $NewItems[$EstimateId][$ProductId][$ProductClassId] = $Item;
  724.             }
  725.         }
  726.         $ReNewItem = [];
  727.         foreach ($NewItems as $EstimateId => $Product) {
  728.             foreach ($Product as $ProductId => $ProductClass) {
  729.                 foreach ($ProductClass as $ProductClassId => $Item)
  730.                     $ReNewItem[] = $Item;
  731.             }
  732.         }
  733.         $goodsColorKeys array_map(function ($item) {
  734.             /**
  735.              * @var CartItem $item
  736.              */
  737.             return $item->getProductClass()->getJancode()->getGoodsColor()->getGclDisplay();
  738.         }, $ReNewItem);
  739.         $goodsSizeKeys array_map(function ($item) {
  740.             /**
  741.              * @var CartItem $item
  742.              */
  743.             return $item->getProductClass()->getJancode()->getGoodsPrice()->getGpDisplay();
  744.         }, $ReNewItem);
  745.         array_multisort($goodsColorKeysSORT_ASCSORT_NUMERIC,
  746.             $goodsSizeKeysSORT_ASCSORT_NUMERIC,
  747.             $ReNewItem
  748.         );
  749.         return $ReNewItem;
  750.     }
  751.     public function MakeValidationData()
  752.     {
  753.         $CartType null;
  754.         foreach ($this->getCarts() as $Cart) {
  755.             $CartType $Cart->getCartType();
  756.             foreach ($Cart->getCartItems() as $Item) {
  757.                 $ProductClass $Item->getProductClass();
  758.                 if ($ProductClass) {
  759.                     $this->AddValidationData($ProductClass$Item->getQuantity());
  760.                 }
  761.             }
  762.         }
  763.         return [$CartType$this->ValidationData];
  764.     }
  765.     protected function AddValidationData($ProductClass$Quantity)
  766.     {
  767.         #キャッシュ
  768.         $this->ProductClass[$ProductClass->getId()] = $ProductClass;
  769.         $ClassId $ProductClass->getId();
  770.         if (isset($this->ValidationData[$ClassId])) {
  771.             $this->ValidationData[$ClassId] += $Quantity;
  772.         } else {
  773.             $this->ValidationData[$ClassId] = $Quantity;
  774.         }
  775.     }
  776.     /**
  777.      *  マトリックスからのDATを コンバートする
  778.      *
  779.      *
  780.      */
  781.     public function CartItemConv($Products)
  782.     {
  783.         if (!$Products) {
  784.             return null;
  785.         }
  786.         $ReProducts = [];
  787.         foreach ($Products as $ClassId => $Quantity) {
  788.             if (!$Quantity) {
  789.                 continue;
  790.             }
  791.             #ここでDATAのコンバートをする
  792.             #1 2バイト文字をIバイト文字に変換
  793.             $Quantity mb_convert_kana($Quantity'n');
  794.             $ReProducts[$ClassId] = $Quantity;
  795.         }
  796.         return $ReProducts;
  797.     }
  798.     public function convertProductsForSetPurchase($Products)
  799.     {
  800.         //
  801.         $janIdList array_keys($Products);
  802.         //
  803.         $janIdListCsv implode(','$janIdList);
  804.         $sql "SELECT
  805.                     T1.jan_id
  806.                 ,   T.goods_id
  807.                 ,   T.goods_set_purchase_flg
  808.                 ,   GROUP_CONCAT(DISTINCT T6.jan_id ORDER BY T2.gsp_type SEPARATOR ',') AS `child_jan_id_list`
  809.                 FROM goods_table AS T
  810.                 INNER Join jancode_table AS T1 ON T.goods_id = T1.jan_goods
  811.                 LEFT JOIN goods_set_purchase_table AS T2 ON T.goods_id = T2.gsp_goods_parent
  812.                 LEFT JOIN goods_table AS T3 ON T3.goods_id = T2.gsp_goods_child
  813.                 LEFT JOIN gsp_gcl_table AS T4 ON T4.gsp_gcl_parent = T1.jan_color
  814.                 LEFT JOIN gsp_gp_table AS T5 ON T5.gsp_gp_parent = T1.jan_price
  815.                 LEFT JOIN jancode_table AS T6 ON T3.goods_id = T6.jan_goods AND (T6.jan_color, T6.jan_price) IN ((T4.gsp_gcl_main, T5.gsp_gp_main), (T4.gsp_gcl_sub, T5.gsp_gp_sub), (T4.gsp_gcl_other, T5.gsp_gp_other))
  816.                 WHERE T1.jan_id IN ($janIdListCsv)
  817.                 GROUP By T.goods_id, T1.jan_id
  818.                 ORDER By T.goods_id, T1.jan_id
  819.                 ";
  820.         //
  821.         $result = (new SqlService())
  822.             ->Sql($sql)
  823.             ->FetchAll();
  824.         //
  825.         $_Products = [];
  826.         //
  827.         foreach ($result as $jan) {
  828.             //
  829.             $parentJanId $jan['jan_id'];
  830.             $quantity $Products[$parentJanId];
  831.             //
  832.             if ($jan['goods_set_purchase_flg'] == && ($childJanIdList explode(','$jan['child_jan_id_list']))) {
  833.                 //
  834.                 foreach ($childJanIdList as $childJanId) {
  835.                     //
  836.                     $_Products[$childJanId] = ($_Products[$childJanId] ?? 0) + $quantity;
  837.                 }
  838.             } else {
  839.                 $_Products[$parentJanId] = ($_Products[$parentJanId] ?? 0) + $quantity;
  840.             }
  841.         }
  842.         //
  843.         return $_Products;
  844.     }
  845.     /**
  846.      *
  847.      *
  848.      */
  849.     public function AddProducts()
  850.     {
  851.         $NewItems $this->MergeNewItem();
  852.         $this->restoreCarts($NewItems);
  853.     }
  854.     /**
  855.      *  AddLine で 追加分のDATAを返す
  856.      * @param int $ProductClassId
  857.      *
  858.      * @return array()
  859.      */
  860.     public function GetAddlines($ProductClassId)
  861.     {
  862.         if (!$this->CartItemIds) {
  863.             return null;
  864.         } #不要?
  865.         return $this->CartItemIds[$ProductClassId] ?? null;
  866.     }
  867.     /**
  868.      *  $Estimates 見積DATAを格納する
  869.      * @param $Estimates
  870.      *
  871.      */
  872.     public function SetEstimates($Estimates)
  873.     {
  874.         if ($Estimates) {
  875.             $this->Estimates json_encode($Estimates);
  876.         }
  877.     }
  878.     /**
  879.      *  見積もりシミュレーション ハイブリット 戻り値の登録
  880.      *
  881.      */
  882.     public function SetHybrid($CartItemId)
  883.     {
  884.         $CasrtItemIds explode(','$CartItemId);
  885.         /**
  886.          * @var CartItem[] $CartItems
  887.          */
  888.         $CartItems $this->CartItemRepository->findBy(['id' => $CasrtItemIds]);
  889.         foreach ($CartItems as $CartItem) {
  890.             //
  891.             $noOptions $this->isProductNoOptions($CartItem->getProductClass()->getProduct()->getId());
  892.             //
  893.             $Cart $CartItem->getCart();
  894.             if ($Cart->getCartType() != self::CartTypeEstimate) {
  895.                 $Cart->setCartType(self::CartTypeEstimate);
  896.                 $CartItem->setCart($Cart);
  897.             }
  898.             //
  899.             if (!$noOptions) {
  900.                 $CartItem->setOptions($this->Estimates);
  901.             }
  902.             if (!$CartItem->getEstimateId()) {
  903.                 $this->SetEstimateId();
  904.                 $CartItem->setEstimateId($this->EstimateId);
  905.             }
  906.             $this->entityManager->persist($CartItem);
  907.             $this->entityManager->flush();
  908.         }
  909.     }
  910.     public function resetEstimateOptions()
  911.     {
  912.         $this->EstimateOption = [];
  913.     }
  914.     public function checkExistOption($estimateOptions$estimateId$optionName)
  915.     {
  916.         foreach ($estimateOptions as $options) {
  917.             if(isset($options[$estimateId][$optionName])) {
  918.                 return true;
  919.             }
  920.         }
  921.         return false;
  922.     }
  923.     /**
  924.      * @param object $Item
  925.      *
  926.      */
  927.     public function GetEstimateOptionData($Items$Page 'cart')
  928.     {
  929.         foreach ($Items as $Item) {
  930.             if (!$Item->getOptions()) {
  931.                 continue;
  932.             }
  933.             #OrderItemの時 不要かな?
  934.             if ('order' == $Page) {
  935.                 if (!= $Item->getOrderItemTypeId()) {
  936.                     continue;
  937.                 }
  938.             }
  939.             $EstimateId $Item->getEstimateId();
  940.             $Quantity $Item->getQuantity();
  941.             $ProductClass $Item->getProductClass();
  942.             $this->SetEstimateOption($EstimateId$ProductClass$Quantity);
  943.         }
  944.         return $this->GetEstimateOption();
  945.     }
  946.     /**
  947.      * 見積もりシミュレーション合計値を計算する
  948.      * 金額は金額モジュールより
  949.      *
  950.      * @param int $EstimateId
  951.      * @param object $ProductClass
  952.      * @param string $Option
  953.      */
  954.     public function SetEstimateOption($EstimateId$ProductClass$Quantity$Options null)
  955.     {
  956.         #加工なし
  957.         if (!$EstimateId) {
  958.             return;
  959.         }
  960.         #数量設定なし
  961.         if (!$Quantity) {
  962.             return;
  963.         }
  964.         #Option の登録
  965.         if (!isset($this->EstimateOption[$EstimateId]['option']) && $Options) {
  966.             $this->EstimateOption[$EstimateId]['option'] = $Options;
  967.         }
  968.         #合計金額の算出
  969.         if (isset($this->EstimateOption[$EstimateId]['product_total'])) {
  970.             $this->EstimateOption[$EstimateId]['product_total'] += $Quantity $ProductClass->getPrice02IncTax();
  971.         } else {
  972.             $this->EstimateOption[$EstimateId]['product_total'] = $Quantity $ProductClass->getPrice02IncTax();
  973.         }
  974.         #数量の算出
  975.         if (isset($this->EstimateOption[$EstimateId]['quantity'])) {
  976.             $this->EstimateOption[$EstimateId]['quantity'] += $Quantity;
  977.         } else {
  978.             $this->EstimateOption[$EstimateId]['quantity'] = $Quantity;
  979.         }
  980.         if (!isset($this->EstimateOption[$EstimateId]['white_only'])) {
  981.             $this->EstimateOption[$EstimateId]['white_only'] = 1;
  982.         }
  983.         $ClassCategory1 $ProductClass->getClassCategory1();
  984.         $Patan $this->EccubeConfig['ESTIMATE_WHOIT_ONLY'];
  985.         if (!preg_match($Patan$ClassCategory1->getBackendname())) {
  986.             $this->EstimateOption[$EstimateId]['white_only'] = 2;
  987.         }
  988.         return;
  989.     }
  990.     public function GetEstimateOption()
  991.     {
  992.         return $this->EstimateOption[self::DummyEstimateId] ?? $this->EstimateOption;
  993.     }
  994.     public function UpEstimateOption()
  995.     {
  996.         if (count($this->EstimateOption) < 1) {
  997.             return;
  998.         }
  999.         $Columns = ['product_total''quantity''white_only'];
  1000.         foreach ($this->EstimateOption as $EstimateId => $Data) {
  1001.             $Flg false;
  1002.             if (empty($Data['option'])) continue;
  1003.             $Options json_decode($Data['option'], true);
  1004.             foreach ($Columns as $Column) {
  1005.                 if (($Options[$Column] ?? null) != $Data[$Column]) {
  1006.                     $Flg true;
  1007.                     $Options[$Column] = $Data[$Column];
  1008.                 }
  1009.             }
  1010.             if ($Flg) {
  1011.                 $this->RunEstimateOptions($EstimateIdjson_encode($Options));
  1012.             }
  1013.         }
  1014.     }
  1015.     public function UpRepeatEstimateOption()
  1016.     {
  1017.         if (!$this->EstimateOption) {
  1018.             return;
  1019.         }
  1020.         $this->RunEstimateOptions($this->EstimateId$this->Estimates);
  1021.     }
  1022.     protected function RunEstimateOptions($EstimateId$Options)
  1023.     {
  1024.         foreach ($this->getCarts() as $cart) {
  1025.             $this->CartItemRepository
  1026.             ->createQueryBuilder('ci')
  1027.             ->update()
  1028.             ->set('ci.options'':Options')
  1029.             ->andWhere('ci.Cart = :CartId')
  1030.             ->andWhere('ci.EstimateId = :EstimateId')
  1031.             ->andWhere('ci.options IS NOT NULL')
  1032.             ->setParameter('Options'$Options)
  1033.             ->setParameter('CartId'$cart->getId())
  1034.             ->setParameter('EstimateId'$EstimateId)
  1035.             ->getQuery()
  1036.             ->execute();
  1037.         }
  1038.     }
  1039.     /**
  1040.      * 分割処理により 
  1041.      * 加工
  1042.      * プリント =2 裾上げ =1 を返す
  1043.      *
  1044.      * @return inr
  1045.      */
  1046.     public function getEstimateType()
  1047.     {
  1048.         foreach ($this->getCarts() as $i => $Cart) {
  1049.             foreach ($Cart->getCartItems() as $Items) {
  1050.                 if (!$Options $Items->getOptions()) {
  1051.                     continue;
  1052.                 }
  1053.                 $Option json_decode($Optionstrue);
  1054.                 return $Option['type'] ?? 1;
  1055.             }
  1056.         }
  1057.     }
  1058.     /**
  1059.      * 2022/10/22 カートに 商品を追加する
  1060.      *
  1061.      *
  1062.      */
  1063.     public function AddCartProduct($Products)
  1064.     {
  1065.         //
  1066.         $this->clearBuffer('isProductNoOptions');
  1067.         //
  1068.         foreach ($Products as $ClassId => $Quantity) {
  1069.             if (!$Quantity) {
  1070.                 continue;
  1071.             }
  1072.             /**
  1073.              * @var ProductClass $ProductClass
  1074.              */
  1075.             $ProductClass $this->GetProductClass($ClassId) ?? $ClassId;
  1076.             //
  1077.             $noOptions $this->isProductNoOptions($ProductClass->getProduct()->getId());
  1078.             //
  1079.             $this->addProduct($ProductClass$Quantity$noOptions);
  1080.         }
  1081.         $this->save();
  1082.     }
  1083.     public function InitiarizeEstimate()
  1084.     {
  1085.         $this->Estimates null;
  1086.         $this->EstimateId null;
  1087.     }
  1088.     /**
  1089.      * @param string $name
  1090.      * @return void
  1091.      */
  1092.     public function clearBuffer($name null)
  1093.     {
  1094.         if ($name === null) {
  1095.             //
  1096.             $this->_buffer = [];
  1097.         } else {
  1098.             //
  1099.             unset($this->_buffer[$name]);
  1100.         }
  1101.     }
  1102.     /**
  1103.      * @param int $productId
  1104.      * @return bool
  1105.      */
  1106.     public function isProductNoOptions($productId)
  1107.     {
  1108.         //
  1109.         $result false;
  1110.         //
  1111.         if (!isset($this->_buffer['isProductNoOptions'])) {
  1112.             //
  1113.             $this->_buffer['isProductNoOptions'] = $productId;
  1114.         } else  {
  1115.             //
  1116.             $result = ($this->_buffer['isProductNoOptions'] != $productId);
  1117.         }
  1118.         //
  1119.         return $result;
  1120.     }
  1121.     /**
  1122.      * @return ProductClass[]
  1123.      */
  1124.     public function getAllProductClasses()
  1125.     {
  1126.         /**
  1127.          * @var ProductClass[] $ProductClasses
  1128.          */
  1129.         $ProductClasses = [];
  1130.         //
  1131.         foreach ($this->getCarts() as $Cart) {
  1132.             //
  1133.             foreach ($Cart->getCartItems() as $CartItem) {
  1134.                 //
  1135.                 if ($CartItem->isProduct()) {
  1136.                     //
  1137.                     $ProductClasses[] = $CartItem->getProductClass();
  1138.                 }
  1139.             }
  1140.         }
  1141.         //
  1142.         return $ProductClasses;
  1143.     }
  1144.     /**
  1145.      * @return ProductClass[]
  1146.      */
  1147.     public function getEstimateProductClasses()
  1148.     {
  1149.         /**
  1150.          * @var ProductClass[] $ProductClasses
  1151.          */
  1152.         $ProductClasses = [];
  1153.         //
  1154.         foreach ($this->getCarts() as $Cart) {
  1155.             //
  1156.             foreach ($Cart->getCartItems() as $CartItem) {
  1157.                 //
  1158.                 if ($CartItem->isProduct() && !empty($CartItem->getOptions())) {
  1159.                     //
  1160.                     $ProductClasses[] = $CartItem->getProductClass();
  1161.                 }
  1162.             }
  1163.         }
  1164.         //
  1165.         return $ProductClasses;
  1166.     }
  1167.     public function hasSusoage()
  1168.     {
  1169.         //
  1170.         return GoodsService::isSusoageExistInJanIdList(array_map(function ($ProductClass) {
  1171.             //
  1172.             return $ProductClass->getId();
  1173.         }, $this->getEstimateProductClasses()));
  1174.     }
  1175.     public function hasNairePrint()
  1176.     {
  1177.         //
  1178.         return GoodsService::isNairePrintExistInJanIdList(array_map(function ($ProductClass) {
  1179.             //
  1180.             return $ProductClass->getId();
  1181.         }, $this->getEstimateProductClasses()));
  1182.     }
  1183.     public function hasKyouei()
  1184.     {
  1185.         //
  1186.         return GoodsService::isKyoueiExistInJanIdList(array_map(function ($ProductClass) {
  1187.             //
  1188.             return $ProductClass->getId();
  1189.         }, $this->getAllProductClasses()));
  1190.     }
  1191.     public function hasNairePrintWithKyouei()
  1192.         //
  1193.     {
  1194.         return GoodsService::isNairePrintWithKyoueiExistInJanIdList(array_map(function ($ProductClass) {
  1195.             //
  1196.             return $ProductClass->getId();
  1197.         }, $this->getEstimateProductClasses()));
  1198.     }
  1199.     public function hasNairePrintWithoutKyouei()
  1200.         //
  1201.     {
  1202.         return GoodsService::isNairePrintWithoutKyoueiExistInJanIdList(array_map(function ($ProductClass) {
  1203.             //
  1204.             return $ProductClass->getId();
  1205.         }, $this->getEstimateProductClasses()));
  1206.     }
  1207.     public function detectCartTypeByRouteName($routeName)
  1208.     {
  1209.         switch ($routeName) {
  1210.             case self::ROUTE_ADD_NORMAL:
  1211.             case self::ROUTE_ADD_LINE:
  1212.                 //
  1213.                 return self::CartTypeNormal;
  1214.                 break;
  1215.             case self::ROUTE_VALID_ESTIMATE:
  1216.             case self::ROUTE_ADD_ESTIMATE:
  1217.             case self::ROUTE_ADD_HYBRID:
  1218.                 //
  1219.                 return self::CartTypeEstimate;
  1220.                 break;
  1221.             case self::ROUTE_ADD_SAMPLE:
  1222.                 //
  1223.                 return self::CartTypeSample;
  1224.                 break;
  1225.             case self::ROUTE_ADD_CATALOG:
  1226.                 //
  1227.                 return self::CartTypeCatalog;
  1228.                 break;
  1229.             case self::ROUTE_ADD_REPEAT:
  1230.                 // TODO: リピート注文の排他制御対応
  1231.                 return $this->GetCartType();
  1232.                 break;
  1233.             default:
  1234.                 //
  1235.                 throw new NotFoundHttpException();
  1236.         }
  1237.     }
  1238.     /**
  1239.      * @param string $routeName
  1240.      * @param array $janIdList
  1241.      * @param int|null $currentCartType
  1242.      * @return int[]|true
  1243.      */
  1244.     public function checkMixCart($routeName, array $janIdList$pendingCartType null$currentCartType null)
  1245.     {
  1246.         //
  1247.         $result = [];
  1248.         //
  1249.         if ($pendingCartType === null) {
  1250.             //
  1251.             $pendingCartType $this->detectCartTypeByRouteName($routeName);
  1252.         }
  1253.         //
  1254.         if ($currentCartType === null) {
  1255.             //
  1256.             $currentCartType $this->GetCartType();
  1257.         }
  1258.         //
  1259.         if ($currentCartType === CartService::CartTypeNormal) {
  1260.             //
  1261.             if ($pendingCartType === CartService::CartTypeSample) {
  1262.                 // 購入(加工なし) × 貸出サンプル
  1263.                 return [
  1264.                     CartService::CartTypeNormal,
  1265.                     CartService::CartTypeSample,
  1266.                 ];
  1267.             } else if ($pendingCartType === CartService::CartTypeCatalog) {
  1268.                 // 購入(加工なし) × カタログ請求
  1269.                 return [
  1270.                     CartService::CartTypeNormal,
  1271.                     CartService::CartTypeCatalog,
  1272.                 ];
  1273.             }
  1274.         } else if ($currentCartType === CartService::CartTypeEstimate) {
  1275.             $canMixPrintAndSusoage $this->EccubeConfig['MIX_PRINT_AND_SUSOAGE']['Enabled'] ?? false;
  1276.             //
  1277.             if ($pendingCartType === CartService::CartTypeSample) {
  1278.                 // 購入(加工あり) × 貸出サンプル
  1279.                 return [
  1280.                     CartService::CartTypeEstimate,
  1281.                     CartService::CartTypeSample,
  1282.                 ];
  1283.             } else if ($pendingCartType === CartService::CartTypeCatalog) {
  1284.                 // 購入(加工あり) × カタログ請求
  1285.                 return [
  1286.                     CartService::CartTypeEstimate,
  1287.                     CartService::CartTypeCatalog,
  1288.                 ];
  1289.             } else if ($pendingCartType === CartService::CartTypeEstimate) {
  1290.                 // 購入(加工あり) × 購入(加工あり)
  1291.                 if ($this->hasSusoage()) {
  1292.                     //
  1293.                     if (GoodsService::isNairePrintExistInJanIdList($janIdList) && !$canMixPrintAndSusoage) {
  1294.                         // 購入(加工あり)(裾上げ) × 購入(名入れ/プリント)
  1295.                         return [
  1296.                             CartService::CartTypeEstimate,
  1297.                             CartService::CartTypeEstimate,
  1298.                             \Lm\Entity\Estimate::TYPE_SUSOAGE,
  1299.                             \Lm\Entity\Estimate::TYPE_NAIRE_PRINT,
  1300.                         ];
  1301.                     }
  1302.                 } else if ($this->hasNairePrint()) {
  1303.                     //
  1304.                     if (GoodsService::isSusoageExistInJanIdList($janIdList) && !$canMixPrintAndSusoage) {
  1305.                         // 購入(名入れ/プリント) × 購入(加工あり)(裾上げ)
  1306.                         return [
  1307.                             CartService::CartTypeEstimate,
  1308.                             CartService::CartTypeEstimate,
  1309.                             \Lm\Entity\Estimate::TYPE_NAIRE_PRINT,
  1310.                             \Lm\Entity\Estimate::TYPE_SUSOAGE,
  1311.                         ];
  1312.                     } else if ($this->hasKyouei()) {
  1313.                         //
  1314.                         if (GoodsService::isNairePrintWithoutKyoueiExistInJanIdList($janIdList) && !$canMixPrintAndSusoage) {
  1315.                             // 購入(名入れ/プリント)(共栄) × 購入(名入れ/プリント)(共栄以外)
  1316.                             return [
  1317.                                 CartService::CartTypeEstimate,
  1318.                                 CartService::CartTypeEstimate,
  1319.                                 \Lm\Entity\Estimate::TYPE_NAIRE_PRINT_KYOUEI,
  1320.                                 \Lm\Entity\Estimate::TYPE_NAIRE_PRINT,
  1321.                             ];
  1322.                         }
  1323.                     } else if (GoodsService::isNairePrintWithKyoueiExistInJanIdList($janIdList) && !$canMixPrintAndSusoage) {
  1324.                         // 購入(名入れ/プリント)(共栄以外) × 購入(名入れ/プリント)(共栄)
  1325.                         return [
  1326.                             CartService::CartTypeEstimate,
  1327.                             CartService::CartTypeEstimate,
  1328.                             \Lm\Entity\Estimate::TYPE_NAIRE_PRINT,
  1329.                             \Lm\Entity\Estimate::TYPE_NAIRE_PRINT_KYOUEI,
  1330.                         ];
  1331.                     }
  1332.                 }
  1333.             }
  1334.         } else if ($currentCartType === CartService::CartTypeSample) {
  1335.             //
  1336.             if ($pendingCartType === self::CartTypeNormal) {
  1337.                 // 貸出サンプル × 購入(加工なし)
  1338.                 return [
  1339.                     CartService::CartTypeSample,
  1340.                     CartService::CartTypeNormal,
  1341.                 ];
  1342.             } else if ($pendingCartType === self::CartTypeEstimate) {
  1343.                 // 貸出サンプル × 購入(加工あり)
  1344.                 return [
  1345.                     CartService::CartTypeSample,
  1346.                     CartService::CartTypeEstimate,
  1347.                 ];
  1348.             } else if ($pendingCartType === self::CartTypeCatalog) {
  1349.                 // 貸出サンプル × カタログ請求
  1350.                 return [
  1351.                     CartService::CartTypeSample,
  1352.                     CartService::CartTypeCatalog,
  1353.                 ];
  1354.             }
  1355.         } else if ($currentCartType === CartService::CartTypeCatalog) {
  1356.             // カタログの場合、カタログ以外を入れようとすると上書きするように
  1357.         }
  1358.         //
  1359.         return $result ?: true;
  1360.     }
  1361.     function createCommonCartKey()
  1362.     {
  1363.         if ($currentCustomer $this->getUser()) {
  1364.             return $currentCustomer->getId() . '_type_%s';
  1365.         }
  1366.         if ($this->session->has('cart_key_prefix')) {
  1367.             return $this->session->get('cart_key_prefix') . '_type_%s';
  1368.         }
  1369.         do {
  1370.             $random StringUtil::random(32);
  1371.             $cartKey $random '_type_%s';
  1372.             $cart $this->cartRepository->findOneBy(['cart_key' => $cartKey]);
  1373.         } while ($cart);
  1374.         $this->session->set('cart_key_prefix'$random);
  1375.         return $cartKey;
  1376.     }
  1377.     function removeCart($cart)
  1378.     {
  1379.         foreach ($cart->getCartItems() as $i) {
  1380.             $this->entityManager->remove($i);
  1381.             $this->entityManager->flush();
  1382.         }
  1383.         $preOrderId $cart->getPreOrderId();
  1384.         $Order $this->orderHelper->getPurchaseProcessingOrder($preOrderId);
  1385.         if ($Order) {
  1386.             $this->entityManager->remove($Order);
  1387.         }
  1388.         $this->entityManager->remove($cart);
  1389.         $this->entityManager->flush();
  1390.     }
  1391.     /**
  1392.      * @return CartItem[]
  1393.      */
  1394.     function getAllCartsItems()
  1395.     {
  1396.         //
  1397.         return array_merge(...(array_map(function ($cart) {
  1398.             return is_array(($cartItems $cart->getCartItems())) ? $cartItems $cartItems->toArray();
  1399.         }, $this->getCarts()) ?: [[]]));
  1400.     }
  1401.     public function removeCartItems($cartItemIds)
  1402.     {
  1403.         $cartItems $this->getAllCartsItems();
  1404.         foreach ($cartItems as $item) {
  1405.             if (in_array($item->getId(), $cartItemIds)) {
  1406.                 $this->entityManager->remove($item);
  1407.             }
  1408.         }
  1409.         $this->entityManager->flush();
  1410.     }
  1411.     /**
  1412.      * @param bool|null $enabled
  1413.      * @return bool|void
  1414.      */
  1415.     public function bulkCheckoutEnabled($enabled null)
  1416.     {
  1417.         if ($enabled === null) {
  1418.             return $this->session->get(self::SESSION_BULK_CHECKOUT_ENABLED);
  1419.         } else {
  1420.             $this->session->set(self::SESSION_BULK_CHECKOUT_ENABLED$enabled);
  1421.         }
  1422.     }
  1423.     /**
  1424.      * 在庫切れの商品が含まれていないかを確認する
  1425.      * @return bool
  1426.      * @throws \Exception
  1427.      */
  1428.     public function isItemsStockAvailable()
  1429.     {
  1430.         //
  1431.         foreach ($this->getCarts() as $cart) {
  1432.             foreach ($cart->getCartItems() as $cartItem) {
  1433.                 if ($skuInfo $cartItem->getProductClass()->getSkuInfo()) {
  1434.                     if ($skuInfo->getBackOrder() === Sku::BACK_ORDER_UNAVAILABLE && $skuInfo->getStockAvailability() === Sku::STOCK_AVL_OUT_OF_STOCK) {
  1435.                         // 入荷予定: なし
  1436.                         // 在庫状況: 在庫切れ
  1437.                         return false;
  1438.                     }
  1439.                 }
  1440.             }
  1441.         }
  1442.         //
  1443.         return true;
  1444.     }
  1445.     /**
  1446.      * check cart has error Susoage has warning when change size, color, qty
  1447.      * @return bool
  1448.      * @throws \Exception
  1449.      */
  1450.     public function listSusoageChange()
  1451.     {
  1452.         $listOrder = [];
  1453.         foreach ($this->getCarts() as $cart) {
  1454.             foreach ($cart->getCartItems() as $cartItem) {
  1455.                 $qty 0;
  1456.                 $qtyItem intval($cartItem->getQuantity());
  1457.                 $options $cartItem->getOptions();
  1458.                 $options json_decode($optionstrue);
  1459.                 if (isset($options['susoage']) and is_array($options['susoage'])) {
  1460.                     $productClass $cartItem->getProductClass();
  1461.                     if ($productClass) {
  1462.                         if (!isset($options['susoage'][$productClass->getId()])) {
  1463.                             $listOrder[$cartItem->getEstimateId()] = $cartItem->getEstimateId();
  1464.                         }
  1465.                     }
  1466.                     foreach ($options['susoage'] as $classId =>$susoage) {
  1467.                         if($classId  == $productClass->getId()){
  1468.                             $qty += count($susoage);
  1469.                         }
  1470.                     }
  1471.                     if ($qty != $qtyItem) {
  1472.                         $listOrder[$cartItem->getEstimateId()] = $cartItem->getEstimateId();
  1473.                     }
  1474.                 }
  1475.             }
  1476.         }
  1477.         //
  1478.         return $listOrder;
  1479.     }
  1480. }