src/Services/CartService.php line 87

Open in your IDE?
  1. <?php
  2. namespace App\Services;
  3. use App\Entity\Cart;
  4. use App\Entity\CartProduct;
  5. use App\Entity\CartProductEquipment;
  6. use App\Entity\CartProductParameterValue;
  7. use App\Entity\Currency;
  8. use App\Entity\Language;
  9. use App\Entity\Product;
  10. use App\Entity\ProductEquipment;
  11. use App\Entity\ProductLangParam;
  12. use App\Entity\ProductParameterValue;
  13. use App\Entity\ProductPriceVariants;
  14. use App\Entity\RebateCode;
  15. use App\Entity\SubProduct;
  16. use App\Repository\CartRepository;
  17. use App\Repository\DeliveryCountryRepository;
  18. use App\Repository\DeliveryMethodRepository;
  19. use App\Repository\PaymentMethodRepository;
  20. use App\Exception\CartException;
  21. use Doctrine\Common\Collections\ArrayCollection;
  22. use Doctrine\ORM\EntityManagerInterface;
  23. use Symfony\Component\HttpFoundation\JsonResponse;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  26. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
  27. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  28. use Symfony\Contracts\Translation\TranslatorInterface;
  29. class CartService
  30. {
  31.     private $em;
  32.     private $translator;
  33.     private $cartRepository;
  34.     private $tokenStorage;
  35.     private $session;
  36.     private $deliveryCountryRepository;
  37.     private $productManager;
  38.     /**
  39.      * CartService constructor.
  40.      * @param EntityManagerInterface $em
  41.      * @param TranslatorInterface $translator
  42.      * @param CartRepository $cartRepository
  43.      */
  44.     public function __construct(PaymentMethodRepository $paymentMethodRepositoryDeliveryMethodRepository $deliveryMethodRepositoryDeliveryCountryRepository $deliveryCountryRepositoryEntityManagerInterface $emTranslatorInterface $translatorCartRepository $cartRepositoryTokenStorageInterface $tokenStorageSessionInterface $sessionProductManager $productManager) {
  45.         $this->em $em;
  46.         $this->translator $translator;
  47.         $this->deliveryCountryRepository $deliveryCountryRepository;
  48.         $this->cartRepository $cartRepository;
  49.         $this->tokenStorage $tokenStorage;
  50.         $this->session $session;
  51.         $this->deliveryMethodRepository $deliveryMethodRepository;
  52.         $this->paymentMethodRepository $paymentMethodRepository;
  53.         $this->productManager $productManager;
  54.     }
  55.     /**
  56.      * Get cart session
  57.      * @return mixed
  58.      */
  59.     public function getCartSession() {
  60.         return $this->session->get('cart_session');
  61.     }
  62.     /**
  63.      * @return string locale
  64.      */
  65.     public function getLocale() {
  66.         return $this->session->get('_locale');
  67.     }
  68.     /**
  69.      * @return Currency
  70.      */
  71.     public function getCurrency() {
  72.         return $this->session->get('currency');
  73.     }
  74.     /**
  75.      * @return Cart
  76.      * @throws CartException
  77.      */
  78.     public function getCart() {
  79.         $cart $this->em->getRepository(Cart::class)->findOneBy(['session'=>$this->session->get('cart_session')]);
  80.         if ($cart instanceof Cart) {
  81.             return $cart;
  82.         }
  83.         $create $this->getOrCreateCart();
  84.         if ($create instanceof Cart) {
  85.             return $create;
  86.         }
  87.         throw new CartException("Cart did not found");
  88.     }
  89.     /**
  90.      * * Get Sum of products in the cart
  91.      * @param bool $withRebate - whether with rebate code (RebateCode entity) or not
  92.      * @return array
  93.      */
  94.     public function getSum($withRebate false$withVat true) {
  95.         $sum 0;
  96.         $rebate = ($withRebate && is_object($this->getCart()->getRebateCode()) && $this->getCart()->getRebateCode()->getCodeType() == RebateCode::CODE_TYPE_PERCENT) ? true false;
  97.         /** @var $cart CartProduct */
  98.         foreach ($this->getCartProducts() as $cart) {
  99.             $sum $sum + ($this->calculateProductSinglePrice($cart$rebate$withVat) * $cart->getQuantity());
  100.         }
  101.         if ($withRebate and is_object($this->getCart()->getRebateCode()) and $this->getCart()->getRebateCode()->getCodeType() == RebateCode::CODE_TYPE_AMOUNT and $this->getCart()->isCartApplicableForAmountDiscount()) {
  102.             $sum $sum $this->getCart()->getRebateCode()->getPrice();
  103.         }
  104.         if ($sum 0) {
  105.             $sum 0;
  106.         }
  107.         return ['sum'=>$sum'currency'=>$this->getCurrency()];
  108.     }
  109.     public function getSumWithVat(Cart $cart) {
  110.         $sum 0;
  111.         /** @var $cartProduct CartProduct */
  112.         foreach ($cart->getProducts() as $cartProduct) {
  113.             $price $cartProduct->getProduct()->getPrice($cartProduct->getCurrency(), $cartProduct->getVat());
  114.             $sum $sum + ($cartProduct->getQuantity() * $price['price']);
  115.         }
  116.         return $sum;
  117.     }
  118.     /**
  119.      * Calculate price of single record product from cart
  120.      *
  121.      * @param CartProduct $cartProduct
  122.      * @param bool $withRebate
  123.      * @return mixed
  124.      * @throws CartException
  125.      */
  126.     public function calculateProductSinglePrice(CartProduct $cartProduct$withRebate false$withVat true) {
  127.         $currencyDefault $this->em->getRepository(Currency::class)->findOneBy(['isDefault'=>true'deletedBy'=>false]);
  128.         $currency $this->session->get('currency'$currencyDefault);
  129.         //brutto!
  130.         if ($withVat) {
  131.             if ($cartProduct->getCart()->getLanguage()->getLocaleShort() == 'ro') {
  132.                 $params $cartProduct->getProduct()->getLangParams();
  133.                 foreach ($params as $param) {
  134.                     if ($param->getLanguage()->getLocaleShort() == 'ro') {
  135.                         $vat $param->getVat();
  136.                         $vatRate = ($vat->getValue()+100)/100;
  137.                         if ($withRebate === false) {
  138.                             return $cartProduct->getPriceNet() * $vatRate;
  139.                         } else {
  140.                             $rebateCode $this->getCart()->getRebateCode();
  141.                             if ($rebateCode && $rebateCode->getCodeType() == RebateCode::CODE_TYPE_PERCENT && $this->getCart()->isProductApplicableForRebate($cartProduct->getProduct())) {
  142.                                 $discount $cartProduct->getPriceNet() * $vatRate * ($rebateCode->getPercent() / 100);
  143.                                 return $cartProduct->getPriceNet() * $vatRate $discount;
  144.                             } else {
  145.                                 return $cartProduct->getPriceNet() * $vatRate;
  146.                             }
  147.                         }
  148.                     }
  149.                 }
  150.             }
  151.             $price['price'] = $cartProduct->getPrice();
  152.         }
  153.         if (!isset($price['price'])) {
  154.             throw new CartException('Price of product not found');
  155.         }
  156.         if (is_object($this->getCart()->getRebateCode()) and $cartProduct->getSubProduct() == null and $this->getCart()->isProductApplicableForRebate($cartProduct->getProduct()) and $withRebate) {
  157.             /** @var $rebateCode RebateCode */
  158.             $rebateCode $this->getCart()->getRebateCode();
  159.             if ($rebateCode->getCodeType() == RebateCode::CODE_TYPE_PERCENT) {
  160.                 $priceForDiscount $cartProduct->getProduct()->getPrice($currency$cartProduct->getVat());
  161.                 $priceForDiscount['price'] = $cartProduct->getPrice();
  162.                 $discount $priceForDiscount['price'] * ($rebateCode->getPercent() / 100);
  163.                 $newVatPrice $priceForDiscount['price'] - $discount;
  164.                 return $newVatPrice;
  165.                 //$vatRate = ($cartProduct->getVat()->getValue()+100)/100;
  166.                 //return round($newVatPrice/$vatRate,2);
  167.             } else {
  168.                 return $price['price'];
  169.             }
  170.         } else {
  171.             return $price['price'];
  172.         }
  173.     }
  174.     /**
  175.      * Dynamically calculate total cost with shipping when user change delivery and payment method
  176.      *
  177.      * @param null $deliveryMethodId
  178.      * @param null $paymentMethodId
  179.      * @return array
  180.      */
  181.     public function ajaxCalculateSum($deliveryMethodId null$paymentMethodId null) {
  182.         $calculate $this->getSum(falsetrue);
  183.         $calculateWithRebate $this->getSum($withRebate truetrue);
  184.         //dump($calculateWithRebate);
  185.         //dump($calculate);
  186.         //exit();
  187.         $cartSum $calculateWithRebate['sum'];
  188.         $sum $calculate['sum'];
  189.         $sumWithRebate $calculateWithRebate['sum'];
  190.         if ($deliveryMethodId) {
  191.             $deliveryPrice $this->deliveryMethodRepository->getPrice($deliveryMethodId$this->getCurrency());
  192.             $sum $sum $deliveryPrice;
  193.             $sumWithRebate $sumWithRebate $deliveryPrice;
  194.         }
  195.         if ($paymentMethodId) {
  196.             $paymentPrice $this->paymentMethodRepository->getPrice($paymentMethodId$this->getCurrency());
  197.             $sum $sum $paymentPrice;
  198.             $sumWithRebate $sumWithRebate $paymentPrice;
  199.         }
  200.         $shippingCost $sumWithRebate $cartSum;
  201.         if ($this->getCurrency()->getId() == 4) {
  202.             //return ['savings'=>$sumWithRebate-$sum, 'sum'=>(int)$sum, 'sumWithRebate'=>(int)$sumWithRebate, 'shippingCost'=>(int)$shippingCost];
  203.         }
  204.         return ['savings'=>$sumWithRebate-$sum'sum'=>$sum'sumWithRebate'=>$sumWithRebate'shippingCost'=>$shippingCost];
  205.     }
  206.     /**
  207.      * Todo - dorobić tutaj sprawdzanie czy produkt jest widoczny dla danej wersji jÄ™zykowej
  208.      * @return ArrayCollection
  209.      * @throws CartException
  210.      */
  211.     public function getCartProducts() {
  212.         $collection = new ArrayCollection();
  213.         /** @var $cart CartProduct */
  214.         foreach ($this->getCart()->getProducts() as $cart) {
  215.             /** @var $langParamEntity ProductLangParam */
  216.             $langParamEntity $this->em->getRepository(ProductLangParam::class)->findOneBy(['language'=>$cart->getCart()->getLanguage(), 'product'=>$cart->getProduct()]);
  217.             if ($langParamEntity->getVisible()) {
  218.                 $collection->add($cart);
  219.             }
  220.         }
  221.         return $collection;
  222.     }
  223.     /**
  224.      * Simple counter of products in cart
  225.      *
  226.      * @return int
  227.      * @throws CartException
  228.      */
  229.     public function countProducts() {
  230.         $count 0;
  231.         foreach ($this->getCartProducts() as $cartProduct) {
  232.             $count $count+$cartProduct->getQuantity();
  233.         }
  234.         return $count;
  235.     }
  236.     /**
  237.      * Recalculate cart (when currency changed for example)
  238.      */
  239.     public function cartRecalculate(Language $language) {
  240.         /** @var $cart CartProduct */
  241.         foreach ($this->getCartProducts() as $cart) {
  242.             $priceData = ['price'=>$this->productManager->getPrice($cart->getProduct(), $language$cart->getVariant(), $cart), 'currency'=>$language->getCurrency()];
  243.             if ($cart->getSubProduct()) {
  244.                 $priceData['price'] = $cart->getSubProduct()->getPrice();
  245.             }
  246.             if (isset($priceData['price'])) {
  247.                 $cart->setPrice($priceData['price']);
  248.                 $cart->setCurrency($priceData['currency']);
  249.             }
  250.             $this->em->persist($cart);
  251.         }
  252.         $this->em->flush();
  253.     }
  254.     /**
  255.      * * Check if record with given parameter, product and session exists
  256.      * @param Request $request
  257.      * @return \App\Entity\CartProduct|bool|null|object
  258.      */
  259.     public function checkDoubleRecord(Request $request) {
  260.         $record $this->em->getRepository(CartProduct::class)->findOneBy([
  261.             'session' => $this->session->get('cart_session'),
  262.             'product' => $this->getProductEntity($request->request->get('product_id')),
  263.             'subProduct' => $request->request->get('sub'),
  264.             'code' => $this->recordCode($request->request->get('parameters'), $request->request->get('product_id'), $request->request->get('equipments')),
  265.         ]);
  266.         if (is_object($record)) {
  267.             return $record;
  268.         }
  269.         return false;
  270.     }
  271.     /**
  272.      * @param $variant
  273.      * @return null|ProductPriceVariants
  274.      */
  275.     public function getVariantEntity($variant) {
  276.         if ($variant) {
  277.             return $this->em->getRepository(ProductPriceVariants::class)->find($variant);
  278.         }
  279.         return null;
  280.     }
  281.     /**
  282.      * @return \App\Entity\Currency|null|object
  283.      */
  284.     public function getDefaultCurrency() {
  285.         return $this->em->getRepository(Currency::class)->findOneBy(['isDefault'=>true'deletedBy'=>null]);
  286.     }
  287.     /**
  288.      * @param $id
  289.      * @return \App\Entity\Product|null
  290.      */
  291.     public function getProductEntity($id) {
  292.         return $this->em->getRepository(Product::class)->findOneBy(['id'=>$id'deletedBy'=>null]);
  293.     }
  294.     public function removeInvisible(Cart $cart) {
  295.         /** @var $cartProduct CartProduct */
  296.         foreach ($cart->getProducts() as $cartProduct) {
  297.             $langParamEntity $this->em->getRepository(ProductLangParam::class)->findOneBy(['language'=>$cart->getLanguage(), 'product'=>$cartProduct->getProduct()]);
  298.             if (!$langParamEntity->getVisible()) {
  299.                 foreach ($cartProduct->getEquipments() as $equipment) {
  300.                     $this->em->remove($equipment);
  301.                 }
  302.                 foreach ($cartProduct->getParameterValues() as $parameterValue) {
  303.                     $this->em->remove($parameterValue);
  304.                 }
  305.                 $this->em->remove($cartProduct);
  306.             }
  307.         }
  308.         if ($cart->getRebateCode() && $cart->getRebateCode()->getValidTo()) {
  309.             $now = new \DateTime();
  310.             $validTo $cart->getRebateCode()->getValidTo();
  311.             if ($validTo->getTimestamp() > $now->getTimestamp()) {
  312.                 #OK!
  313.             } else {
  314.                 $cart->setRebateCode(null);
  315.                 $cart->setRebateCodeContent(null);
  316.                 $this->em->persist($cart);
  317.                 $this->em->flush();
  318.             }
  319.         }
  320.         $this->em->flush();
  321.     }
  322.     /**
  323.      * @return Cart
  324.      */
  325.     public function getOrCreateCart() {
  326.         $cart $this->em->getRepository(Cart::class)->findOneBy(['session'=>$this->session->get('cart_session')]);
  327.         if (is_object($cart)) {
  328.             return $cart;
  329.         }
  330.         return $this->create();
  331.     }
  332.     public function recordCode($parameters$productId$equipments null) {
  333.         if (!is_array($parameters) && $equipments === null) {
  334.             return md5($productId);
  335.         }
  336.         $code $productId;
  337.         if (!$parameters && !$equipments) {
  338.             $code md5($productId);
  339.         } else {
  340.             $string '';
  341.             if (is_array($parameters)) {
  342.                 foreach ($parameters as $parameter) {
  343.                     $string .= $string.$parameter['value'];
  344.                 }
  345.                 $code md5($string);
  346.             }
  347.         }
  348.         if ($equipments && is_array($equipments)) {
  349.             foreach ($equipments as $equipment) {
  350.                 $code 'eq'.$code.$equipment;
  351.             }
  352.         }
  353.         return $code;
  354.     }
  355.     public function updateQuantityCart(Request $request) {
  356.         $product $this->getProductEntity($request->request->get('product_id'));
  357.         /** @var $record CartProduct */
  358.         $record $this->em->getRepository(CartProduct::class)->findOneBy(
  359.             [
  360.                 'id'=>$request->request->get('record_id'),
  361.                 'product'=>$product,
  362.                 'session' => $this->session->get('cart_session'),
  363.             ]
  364.         );
  365.         if ($record) {
  366.             $record->setQuantity($request->request->get('quantity'));
  367.             $this->em->persist($record);
  368.             $this->em->flush();
  369.         }
  370.         return new JsonResponse(['message'=>'success']);
  371.     }
  372.     public function isSubProductInCart(Request $request) {
  373.         $product $this->getProductEntity($request->request->get('product_id'));
  374.         /** @var $record CartProduct */
  375.         $record $this->em->getRepository(CartProduct::class)->findOneBy(
  376.             [
  377.                 'id'=>$request->request->get('record_id'),
  378.                 'product'=>$product,
  379.                 'session' => $this->session->get('cart_session'),
  380.             ]
  381.         );
  382.         if ($record->getSubProduct()) {
  383.             return true;
  384.         }
  385.         return false;
  386.     }
  387.     public function removeFromCart(Request $request) {
  388.         $product $this->getProductEntity($request->request->get('product_id'));
  389.         $record $this->em->getRepository(CartProduct::class)->findOneBy(
  390.             [
  391.                 'id'=>$request->request->get('record_id'),
  392.                 'product'=>$product,
  393.                 'session' => $this->session->get('cart_session'),
  394.             ]
  395.         );
  396.         if ($record) {
  397.             $this->em->remove($record);
  398.             $this->em->flush();
  399.         }
  400.         return new JsonResponse(['message'=>'success']);
  401.     }
  402.     public function isMaxQuantityExceeded(Product $product$quantity) {
  403.         if (!$product->getMaxQuantity()) {
  404.             return false;
  405.         }
  406.         return $quantity $product->getMaxQuantity();
  407.     }
  408.     private function subProductAddedNotification(SubProduct $product) {
  409.         $html 'Dodano do koszyka produkt "Kup taniej": '.$product->getName();
  410.         $content = [
  411.             'fromField'=>['fromFieldId'=>'f'],
  412.             'subject'=>'Dodano do koszyka produkt z sekcji "Kup taniej"',
  413.             'content'=>['html'=>$html'plain'=>$html],
  414.             'recipients'=>['to'=>['email'=>'marketing@centrumkrzesel.pl']],
  415.         ];
  416.         $body json_encode($content);
  417.         $ch curl_init();
  418.         curl_setopt($chCURLOPT_URL"https://api3.getresponse360.pl/v3/transactional-emails");
  419.         curl_setopt($chCURLOPT_RETURNTRANSFER1);
  420.         curl_setopt($chCURLOPT_POSTFIELDS$body);
  421.         curl_setopt($chCURLOPT_POST1);
  422.         $headers = array();
  423.         $headers[] = "Content-Type: application/json";
  424.         $headers[] = "X-Auth-Token: api-key gs478s9uv59n5ekulmpmgn5p0uqpepbn";
  425.         $headers[] = "X-Domain: centrumkrzesel.com";
  426.         curl_setopt($chCURLOPT_HTTPHEADER$headers);
  427.         $result curl_exec($ch);
  428.         curl_close ($ch);
  429.         return $result;
  430.     }
  431.     private function getUserDetails(Request $request): array
  432.     {
  433.         // Get the user's IP address
  434.         $userIp $request->getClientIp();
  435.         // Get the user's browser information
  436.         $browserInfo $request->headers->get('User-Agent');
  437.         // Return the details as an array
  438.         return [
  439.             'ip' => $userIp,
  440.             'browser' => $browserInfo,
  441.         ];
  442.     }
  443.     /**
  444.      * @param Request $request
  445.      * @return CartProduct|bool|null|object
  446.      * @throws CartException
  447.      * @throws \Doctrine\ORM\ORMException
  448.      */
  449.     public function addToCart(Request $request) {
  450.         $product $this->getProductEntity($request->request->get('product_id'));
  451.         $variant $request->request->get('variant');
  452.         $code $this->recordCode($request->request->get('parameters'), $request->request->get('product_id'), $request->request->get('equipments'));
  453.         /** @var $language Language */
  454.         $language $this->em->getRepository(Language::class)->findOneBy(['deletedBy'=>null'locale'=>$request->getLocale()]);
  455.         /** @var $langParam ProductLangParam */
  456.         $langParam $this->em->getRepository(ProductLangParam::class)->findOneBy(['product'=>$product'language'=>$language]);
  457.         $cart $this->getOrCreateCart();
  458.         $this->em->persist($cart);
  459.         $sub null;
  460.         if ($request->request->get('sub')) {
  461.             /** @var $sub SubProduct */
  462.             $sub $this->em->getRepository(SubProduct::class)->find($request->request->get('sub'));
  463.             $sub->setActive(false);
  464.             $sub->setAddToCartTime(new \DateTime());
  465.             $this->em->persist($sub);
  466.             $this->subProductAddedNotification($sub);
  467.             $priceData['price'] = $sub->getPrice();
  468.             $priceData['currency'] = $language->getCurrency();
  469.         } else {
  470.             $priceData = ['price'=>$this->productManager->getPrice($product$language$variant), 'currency'=>$language->getCurrency()];
  471.         }
  472.         if (isset($priceData['price'])) {
  473.             $productPrice $priceData['price'];
  474.             $double $this->checkDoubleRecord($request);
  475.             $quantity $request->request->get('quantity');
  476.             if (!is_numeric($quantity)) {
  477.                 $quantity 1;
  478.             }
  479.             if (!$this->session->get('cart_session')) {
  480.                 $data serialize($request->request->all());
  481.                 throw new CartException("Brak sesji - odÅ›wież przeglÄ…darkÄ™: ".$data.' DATA: '.serialize($this->getUserDetails($request)));
  482.             }
  483.             $cartRecord = (is_object($double)) ? $double : new CartProduct();
  484.             $cartRecord->setProduct($product);
  485.             if ($variant) {
  486.                 $cartRecord->setVariant($this->getVariantEntity($variant));
  487.                 $net $cartRecord->getVariant()->getProductPrice()->getPrice();
  488.                 if ($request->request->get('equipments')) {
  489.                     foreach ($request->request->get('equipments') as $equipmentId) {
  490.                         /** @var $equipmentEntity ProductEquipment */
  491.                         $equipmentEntity $this->em->getReference(ProductEquipment::class, $equipmentId);
  492.                         $net $net $equipmentEntity->getPriceNet();
  493.                     }
  494.                 }
  495.                 $cartRecord->setPriceNet($net);
  496.             } else {
  497.                 $net $this->productManager->getPriceNet($product$language);
  498.                 if ($request->request->get('equipments')) {
  499.                     foreach ($request->request->get('equipments') as $equipmentId) {
  500.                         /** @var $equipmentEntity ProductEquipment */
  501.                         $equipmentEntity $this->em->getReference(ProductEquipment::class, $equipmentId);
  502.                         $net $net $equipmentEntity->getPriceNet();
  503.                     }
  504.                 }
  505.                 $cartRecord->setPriceNet($net);
  506.             }
  507.             $cartRecord->setCart($cart);
  508.             $cartRecord->setCode($code);
  509.             $cartRecord->setSubProduct($sub);
  510.             $cartRecord->setVat($langParam->getVat());
  511.             $cartRecord->setSession($this->session->get('cart_session'));
  512.             $cartRecord->setPrice($productPrice);
  513.             $cartRecord->setCurrency($priceData['currency']);
  514.             if ($sub) {
  515.                 $cartRecord->setQuantity(1);
  516.             } else {
  517.                 if (!$this->isMaxQuantityExceeded($product$cartRecord->getQuantity() + $quantity)) {
  518.                     $cartRecord->setQuantity($cartRecord->getQuantity() + $quantity);
  519.                 }
  520.             }
  521.             $cartRecord->setPriceInitial($productPrice);
  522.             if (!is_object($double) and $request->request->get('parameters') and $sub === null) {
  523.                 foreach ($request->request->get('parameters') as $parameter) {
  524.                     $valueEntity $this->em->getReference(ProductParameterValue::class, $parameter['value']);
  525.                     $parameterEntity $valueEntity->getParameter();
  526.                     $value = new CartProductParameterValue();
  527.                     $checkDouble $this->em->getRepository(CartProductParameterValue::class)->findOneBy(['cartProduct'=>$cartRecord'parameter'=>$parameterEntity'parameterValue'=>$valueEntity]);
  528.                     if (!is_object($checkDouble)) {
  529.                         $value->setCartProduct($cartRecord);
  530.                         $value->setParameterValue($valueEntity);
  531.                         $value->setParameter($parameterEntity);
  532.                         $this->em->persist($value);
  533.                     }
  534.                 }
  535.             }
  536.             if (!is_object($double) and $request->request->get('equipments')) {
  537.                 foreach ($request->request->get('equipments') as $equipmentId) {
  538.                     $equipmentEntity $this->em->getReference(ProductEquipment::class, $equipmentId);
  539.                     $newEquipment = new CartProductEquipment();
  540.                     $newEquipment->setQuantity(1);
  541.                     $newEquipment->setEquipment($equipmentEntity);
  542.                     $newEquipment->setProduct($cartRecord->getProduct());
  543.                     $newEquipment->setCartProduct($cartRecord);
  544.                     $newEquipment->setSession($this->session->get('cart_session'));
  545.                     $newEquipment->setPrice($equipmentEntity->getPrice());
  546.                     $this->em->persist($newEquipment);
  547.                 }
  548.             }
  549.             $this->em->persist($cartRecord);
  550.             $this->em->flush();
  551.             $this->cartRecalculate($language);
  552.             return $cartRecord;
  553.         } else {
  554.             throw new CartException("Product price not found");
  555.         }
  556.     }
  557.     /**
  558.      * @return Cart
  559.      * @throws CartException
  560.      */
  561.     public function create() {
  562.         $cart = new Cart();
  563.         $cart->setSession($this->session->get('cart_session'));
  564.         /** @var $language Language */
  565.         $language $this->em->getRepository(Language::class)->findOneBy(['locale'=>$this->session->get('_locale'), 'deletedBy'=>null]);
  566.         if (!is_object($language)) {
  567.             throw new CartException("Language session not found in cart");
  568.         }
  569.         $cart->setIp($_SERVER['REMOTE_ADDR']);
  570.         $cart->setLanguage($language);
  571.         $cart->setUserAgent($_SERVER['HTTP_USER_AGENT']);
  572.         return $cart;
  573.     }
  574.     /**
  575.      * @param $session
  576.      */
  577.     public function delete($session) {
  578.         $cart $this->getRepository()->find($session);
  579.         $this->em->remove($cart);
  580.         $this->em->flush();
  581.     }
  582.     /**
  583.      * @return CartRepository
  584.      */
  585.     public function getRepository() {
  586.         return $this->cartRepository;
  587.     }
  588.     /**
  589.      * Discard rebate code - set to null in cart
  590.      */
  591.     public function discardRebateCode() {
  592.         $cart $this->getCart();
  593.         $cart->setRebateCodeContent('');
  594.         $rebateCode $this->getCart()->getRebateCode();
  595.         if (!is_object($rebateCode)) {
  596.             return;
  597.         }
  598.         if ($rebateCode->getMultiple() !== true) {
  599.             $rebateCode->setUsed(false);
  600.             $this->em->persist($rebateCode);
  601.         }
  602.         $cart->setRebateCode(null);
  603.         $this->em->persist($cart);
  604.         $this->em->flush();
  605.     }
  606.     /**
  607.      * @param $countryId
  608.      * @param $deliveryId
  609.      * @param $paymentId
  610.      * @return Cart
  611.      * @throws CartException
  612.      */
  613.     public function prepareToCheckout($deliveryId$paymentId) {
  614.         $deliveryMethod $this->deliveryMethodRepository->getRepository()->find($deliveryId);
  615.         $paymentMethod $this->paymentMethodRepository->getRepository()->find($paymentId);
  616.         if (!is_object($deliveryMethod) or !is_object($paymentMethod)) {
  617.             throw new CartException("Delivery, Payment or Country not an object");
  618.         }
  619.         $cart $this->getCart();
  620.         $cart->setDeliveryMethod($deliveryMethod);
  621.         $cart->setPaymentMethod($paymentMethod);
  622.         $this->em->persist($cart);
  623.         $this->em->flush();
  624.         return $cart;
  625.     }
  626.     public function getSpecialDeliveryMethodsIds(Cart $cart) {
  627.         $special = [];
  628.         /** @var $cartProduct CartProduct */
  629.         foreach ($cart->getProducts() as $cartProduct) {
  630.             $product $cartProduct->getProduct();
  631.             foreach ($product->getSpecialDeliveryMethods() as $deliveryMethod) {
  632.                 if (!in_array($deliveryMethod->getId(), $special)) {
  633.                     $special[] = $deliveryMethod->getId();
  634.                 }
  635.             }
  636.         }
  637.         return $special;
  638.     }
  639.     public function getCrossSellingProducts(Cart $cart) {
  640.         $crossSell = new ArrayCollection();
  641.         /** @var $cartProduct CartProduct */
  642.         foreach ($this->getCartProducts() as $cartProduct) {
  643.             $product $cartProduct->getProduct();
  644.             $crossSelling $product->getCrossSelling();
  645.             foreach ($crossSelling as $crossSellingRow) {
  646.                 if ($crossSellingRow->getDeletedBy()) {
  647.                     continue;
  648.                 }
  649.                 if ($crossSellingRow->getCrossSellingProduct()->getDeletedBy()) {
  650.                     continue;
  651.                 }
  652.                 $langParamEntity $this->em->getRepository(ProductLangParam::class)->findOneBy(['language'=>$cart->getLanguage(), 'product'=>$crossSellingRow->getCrossSellingProduct()]);
  653.                 if ($langParamEntity and $langParamEntity->getVisible()) {
  654.                     $crossSell->add($crossSellingRow->getCrossSellingProduct());
  655.                 }
  656.             }
  657.         }
  658.         return $crossSell;
  659.     }
  660. }