src/Controller/GiftCertificatesController.php line 69

Open in your IDE?
  1. <?php
  2. namespace Slivki\Controller;
  3. use libphonenumber\PhoneNumberUtil;
  4. use Slivki\Dao\GiftCertificate\GiftCertificateDaoInterface;
  5. use Slivki\Entity\Category;
  6. use Slivki\Entity\Comment;
  7. use Slivki\Entity\FoodFilterCounter;
  8. use Slivki\Entity\GiftCertificate;
  9. use Slivki\Entity\GiftCertificateOrder;
  10. use Slivki\Entity\Media;
  11. use Slivki\Entity\Offer;
  12. use Slivki\Entity\OfferOrderDetails;
  13. use Slivki\Entity\Seo;
  14. use Slivki\Entity\User;
  15. use Slivki\Entity\UserBalanceActivity;
  16. use Slivki\Entity\Visit;
  17. use Slivki\Enum\Order\PaymentType;
  18. use Slivki\Exception\Order\InsufficientBalanceFundsException;
  19. use Slivki\Repository\PurchaseCount\PurchaseCountRepositoryInterface;
  20. use Slivki\Repository\SeoRepository;
  21. use Slivki\Repository\User\CreditCardRepositoryInterface;
  22. use Slivki\Services\GiftCertificate\SplitPaymentGiftCertificateChecker;
  23. use Slivki\Services\GiftCertificateService;
  24. use Slivki\Services\Offer\CustomProductOfferSorter;
  25. use Slivki\Services\Offer\GiftCertificateSorter;
  26. use Slivki\Services\Offer\OfferCacheService;
  27. use Slivki\Services\PartnerBePaidService;
  28. use Slivki\Services\Payment\OnlineOrderPaymentMethodService;
  29. use Slivki\Services\Payment\PaymentService;
  30. use Slivki\Services\Seo\SeoResourceService;
  31. use Slivki\Services\Subscription\SubscriptionService;
  32. use Slivki\Util\CommonUtil;
  33. use Symfony\Component\HttpFoundation\JsonResponse;
  34. use Symfony\Component\HttpFoundation\Request;
  35. use Symfony\Component\HttpFoundation\Response;
  36. use Symfony\Component\Routing\Annotation\Route;
  37. use function in_array;
  38. class GiftCertificatesController extends SiteController
  39. {
  40.     /**
  41.      * @Route("/gift-certificate/select/{offerID}", name="giftCertificates")
  42.      */
  43.     public function giftCertificatesAction(
  44.         Request $request,
  45.         OfferCacheService $offerCacheService,
  46.         GiftCertificateService $giftCertificateService,
  47.         GiftCertificateSorter $giftCertificateSorter,
  48.         SeoResourceService $seoResourceService,
  49.         SubscriptionService $subscriptionService,
  50.         GiftCertificateDaoInterface $giftCertificateDao,
  51.         PurchaseCountRepositoryInterface $purchaseCountRepository,
  52.         $offerID
  53.     ): Response {
  54.         $response = new Response();
  55.         $entityManager $this->getDoctrine()->getManager();
  56.         $offer $offerCacheService->getOffer($offerIDfalsetrue);
  57.         if (!$offer) {
  58.             $offer $entityManager->find(Offer::class, $offerID);
  59.         }
  60.         if (null === $offer || !$offer->hasFreeCodes() || === $giftCertificateDao->getCountActiveByOfferId($offerID)) {
  61.             return $this->redirect($seoResourceService->getOfferSeo($offerID)->getMainAlias());
  62.         }
  63.         $ratingData $entityManager->getRepository(Comment::class)->getEntityRatingWithCount(Category::OFFER_CATEGORY_ID$offerID);
  64.         $certificates $giftCertificateService->getCertificates($offer);
  65.         $user $this->getUser();
  66.         $sortType $request->query->get('sort'CustomProductOfferSorter::DEFAULT_CUSTOM_PRODUCT_SORT);
  67.         $certificates $giftCertificateSorter->sort($certificates$sortType);
  68.         $purchaseCount $purchaseCountRepository->findByOfferId((int) $offerID);
  69.         $data = [
  70.             'dishes' => $certificates,
  71.             'options' => [],
  72.             'offer' => $offer,
  73.             'rating' => $ratingData['rating'] * 100 5,
  74.             'ratingCount' => $ratingData['ratingCount'],
  75.             'codeCostRegular' => 0,
  76.             'minSumForFreeDelivery' => 0,
  77.             'minOrderSum' => 0,
  78.             'showDelivery' => false,
  79.             'isCertificate' => true,
  80.             'footerOfferConditionID' => $offerID,
  81.             'pickupLocations' => '',
  82.             'offerGeoLocationData' => '',
  83.             'defaultLocationID' => null,
  84.             'visitCount' => $entityManager->getRepository(Visit::class)->getVisitCount($offerIDVisit::TYPE_OFFER30false),
  85.             'sortList' => $giftCertificateSorter::SORT_LIST,
  86.             'filterAction' => $entityManager->getRepository(FoodFilterCounter::class)->findOneBy(['entityID' => $offerID]),
  87.             'purchaseCountMonth' => null === $purchaseCount $purchaseCount->getPurchaseCountLastMonthWithCorrection(),
  88.         ];
  89.         if (null !== $user) {
  90.             if ($subscriptionService->isSubscriber($user)) {
  91.                 $data['allowedCodesToBuy'] = $subscriptionService->getSubscription($user)->getNumberOfCodes();
  92.             } elseif ($user->isBatchCodesAllowed()) {
  93.                 $data['allowedCodesToBuyBatchCodes'] = $user->getBatchCodesCount();
  94.             }
  95.         }
  96.         $data['codeCost'] = 0;
  97.         if (Offer::SOSEDI_OFFER_ID === $offerID) {
  98.             $hasSosediPurchase $giftCertificateService->hasSosediPurchase($user);
  99.             $data['isFirstSosediPurchase'] = !$hasSosediPurchase;
  100.             $data['hasSosediPurchaseForUser'] = $hasSosediPurchase;
  101.         }
  102.         $data['topDishIDList'] = [];
  103.         for ($i 0$i 3$i++) {
  104.             if (isset($crtPurchaseCount[$i]['id'])) {
  105.                 $data['topDishIDList'][] = $crtPurchaseCount[$i]['id'];
  106.             }
  107.         }
  108.         $offerRepository $entityManager->getRepository(Offer::class);
  109.         $data['director'] = $offerRepository->getDirector($offerID);
  110.         $data['logoMedia'] = $data['director']->getOnlinePaymentLogo();
  111.         if (!$data['logoMedia']) {
  112.             $data['logoMedia'] = $entityManager->getRepository(Media::class)->getDirectorLogo($data['director']->getID());
  113.         }
  114.         $data['formAction'] = '/gift-certificate/order/checkout';
  115.         $data['categoryName'] = 'Подарочные сертификаты';
  116.         $data['categoryURL'] = $entityManager->getRepository(Seo::class)->getSeoForEntity(SeoRepository::RESOURCE_URL_OFFER_CATEGORY24)->getMainAlias();
  117.         $view CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/order.html.twig' 'Slivki/delivery/order.html.twig';
  118.         $response->setContent($this->renderView($view$data));
  119.         return $response;
  120.     }
  121.     /**
  122.      * @Route("/gift-certificate/order/checkout", name="gift_certificate_order_checkout")
  123.      */
  124.     public function checkoutAction(
  125.         Request $request,
  126.         GiftCertificateService $giftCertificateService,
  127.         PartnerBePaidService $partnerBePaidService,
  128.         SeoResourceService $seoResourceService,
  129.         SubscriptionService $subscriptionService,
  130.         CreditCardRepositoryInterface $creditCardRepository,
  131.         OnlineOrderPaymentMethodService $onlineOrderPaymentMethodService
  132.     ): Response {
  133.         $response = new Response();
  134.         $offerID $request->request->getInt('offerID');
  135.         $entityManager $this->getDoctrine()->getManager();
  136.         $offer $entityManager->find(Offer::class, $offerID);
  137.         if (!$offer->isActive() || !$offer->isInActivePeriod()) {
  138.            throw $this->createNotFoundException();
  139.         }
  140.         if (!$offer->hasFreeCodes()) {
  141.             return $this->redirect($seoResourceService->getOfferSeo($offerID)->getMainAlias());
  142.         }
  143.         $codeCost $this->getOfferRepository()->getCodeCost($offer);
  144.         $counts $request->request->get('count');
  145.         /** @var User $user */
  146.         $user $this->getUser();
  147.         $codeCostRegular $codeCost;
  148.         if (null !== $user && $subscriptionService->isSubscriber($user)) {
  149.             $codeCost 0;
  150.             $allowedCodesCount $subscriptionService->getSubscription($user)->getNumberOfCodes();
  151.         } elseif ($user->isBatchCodesAllowed()) {
  152.             $codeCost 0;
  153.         }
  154.         $order = new GiftCertificateOrder();
  155.         $deviceType CommonUtil::isMobileDevice($request) ? SiteController::DEVICE_TYPE_MOBILE SiteController::DEVICE_TYPE_DESKTOP;
  156.         $order->setDeviceType($deviceType);
  157.         $order->setUser($this->getUser());
  158.         $order->setOffer($offer);
  159.         $codesCount 0;
  160.         $totalAmount 0;
  161.         $totalOfferAmount 0;
  162.         $totalCodes 0;
  163.         $items = [];
  164.         $isFreeStyle in_array($offerIDOffer::FREESTYLE_OFFER_IDStrue);
  165.         $isSosedi $offerID === 283793;
  166.         $hasSosediPurchase false;
  167.         if ($isSosedi) {
  168.             $hasSosediPurchase $giftCertificateService->hasSosediPurchase($user);
  169.         }
  170.         $isBuyOnlyCodeResponse false;
  171.         $loopFirst true;
  172.         foreach ($request->request->get('dishID') as $key => $certificateID) {
  173.             /** @var GiftCertificate $certificate */
  174.             $certificate $entityManager->find(GiftCertificate::class, $certificateID);
  175.             if (!$certificate) {
  176.                 continue;
  177.             }
  178.             if ($certificate->isBuyOnlyCode()) {
  179.                 $isBuyOnlyCodeResponse true;
  180.             }
  181.             $items[$key] = 0;
  182.             for ($i 0$i $counts[$key]; $i++) {
  183.                 if (
  184.                     Offer::BLACK_START_BURGER_OFFER_ID !== $offer->getID()
  185.                     && isset($allowedCodesCount) && $totalCodes >= $allowedCodesCount
  186.                 ) {
  187.                     break;
  188.                 }
  189.                 if ($isFreeStyle || $isSosedi) {
  190.                     $codeTill $offer->getCodeActiveTill()->setTime(23,59,59);
  191.                 } else {
  192.                     $codeTill =  new \DateTime("+" $certificate->getActiveDays() ." days");
  193.                 }
  194.                 $details = new OfferOrderDetails();
  195.                 $details->setGiftCertificate($certificate);
  196.                 $details->setItemsCount(1);
  197.                 $details->setCodeActiveTill($codeTill);
  198.                 $purchasePrice $certificate->getPriceOffer();
  199.                 if ($isSosedi) {
  200.                     if (!$hasSosediPurchase && $loopFirst && $i == && $certificate->getPrice() != 100 && $certificate->getPrice() != 50) {
  201.                         $purchasePrice $certificate->getPrice() * 0.9;
  202.                         $loopFirst false;
  203.                     }
  204.                     $totalOfferAmount += $purchasePrice;
  205.                 }
  206.                 $details->setPurchasePrice($purchasePrice);
  207.                 $order->addOfferOrderDetails($details);
  208.                 $totalCodes++;
  209.                 $items[$key] += 1;
  210.             }
  211.             $codesCount += $certificate->getCodesPerItem() * $items[$key];
  212.             $totalAmount += $certificate->getPriceRegular() * $items[$key];
  213.             if (!$isSosedi) {
  214.                 $totalOfferAmount += $certificate->getPriceOffer() * $items[$key];
  215.             }
  216.         }
  217.         if ($offer->getID() == 283384) {
  218.             $codesCount 1;
  219.         } else {
  220.             $codesCount ceil($codesCount);
  221.         }
  222.         $allowedCodesToBuyBalance false;
  223.         if ($codeCost !== && $user->isBalanceAllowed($codesCount $codeCost)) {
  224.             $codeCost 0;
  225.             $allowedCodesToBuyBalance true;
  226.         }
  227.         $order->setAmount($totalOfferAmount $codesCount $codeCost);
  228.         $order->setCodeCost($codeCost);
  229.         $order->setCodesCount($codesCount);
  230.         $entityManager->persist($order);
  231.         $entityManager->flush();
  232.         $view CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/delivery_checkout.html.twig'
  233.             'Slivki/delivery/delivery_checkout.html.twig';
  234.         $allowedPaymentMethodsForOffer $onlineOrderPaymentMethodService->getAllowedPaymentMethodsForGiftCertificateOffer($offerID);
  235.         $allowedPaymentMethods = [
  236.             'delivery' => [=> 0=> 0=> 0],
  237.             'pickup' => [
  238.                 => (int) $allowedPaymentMethodsForOffer->isOnline(),
  239.                 => (int) $allowedPaymentMethodsForOffer->isCash(),
  240.                 => (int) $allowedPaymentMethodsForOffer->isTerminal(),
  241.             ],
  242.         ];
  243.         $partnerBePaidService->setOrder($order);
  244.         $fullOrderAmount $order->getAmount();
  245.         if ($allowedCodesToBuyBalance) {
  246.             $fullOrderAmount += $codeCostRegular $order->getCodesCount();
  247.         }
  248.         $data = [
  249.             'order' => $order,
  250.             'offer' => $offer,
  251.             'codeCost' => $codeCost,
  252.             'codeCostRegular' => $codeCostRegular,
  253.             'deliveryPrice' => 0,
  254.             'offerURL' => $entityManager->getRepository(Seo::class)->getOfferURL($offer->getID())->getMainAlias(),
  255.             'totalAmount' => $totalAmount,
  256.             'director' => $offer->getDirectors()->first(),
  257.             'robotsMeta' => 'noindex, follow',
  258.             'offerID' => $offerID,
  259.             'adresses' => null,
  260.             'showCheckAddressButton' => false,
  261.             'streetSuggest' => false,
  262.             'workHourFrom' => 0,
  263.             'workHourTo' => 0,
  264.             'showDelivery' => false,
  265.             'pickupEnabled' => false,
  266.             'deliveryEnabled' => false,
  267.             'pickupLocations' => '',
  268.             'defaultLocationID' => null,
  269.             'footerOfferConditionID' => $offerID,
  270.             'pickupDiscount' => 0,
  271.             'allowedPaymentMethods' => $allowedPaymentMethods,
  272.             'isGiftCertificate' => true,
  273.             'pickupDeliveryType' => null,
  274.             'activeCreditCards' => !$offer->isRecurrentDisabled() ? $creditCardRepository->findActiveByUser($user) : [],
  275.             'allowedCodesToBuyBalance' => $allowedCodesToBuyBalance,
  276.             'isBuyOnlyCodeResponse' => $isBuyOnlyCodeResponse,
  277.             'isSlivkiPayAllowed' => $fullOrderAmount <= $user->getFullBalance() && $order->getAmount() <= $user->getMoneyBalance(),
  278.         ];
  279.         $data['categoryName'] = 'Подарочные сертификаты';
  280.         $data['categoryURL'] = $entityManager->getRepository(Seo::class)->getSeoForEntity(SeoRepository::RESOURCE_URL_OFFER_CATEGORY24)->getMainAlias();
  281.         $data['formAction'] = '/gift-certificate/order/pay';
  282.         $data['giftCertificate'] = true;
  283.         $content $this->renderView($view$data);
  284.         $response->setContent($content);
  285.         return $response;
  286.     }
  287.     /**
  288.      * @Route("/gift-certificate/order/pay", name="gift_certificate_order_pay")
  289.      */
  290.     public function payAction(
  291.         Request $request,
  292.         PartnerBePaidService $partnerBePaidService,
  293.         PaymentService $paymentService,
  294.         CreditCardRepositoryInterface $creditCardRepository,
  295.         SplitPaymentGiftCertificateChecker $splitPaymentGiftCertificateChecker,
  296.         SubscriptionService $subscriptionService,
  297.         PhoneNumberUtil $phoneNumberUtil,
  298.         SeoResourceService $seoResourceService
  299.     ): JsonResponse {
  300.         if (!$request->isMethod(Request::METHOD_POST)) {
  301.             throw $this->createNotFoundException();
  302.         }
  303.         $entityManager $this->getDoctrine()->getManager();
  304.         $orderID $request->request->getInt('orderID');
  305.         $order $entityManager->find(GiftCertificateOrder::class, $orderID);
  306.         if (!$order || $order->getUser()->getID() != $this->getUser()->getID() || $order->getStatus() != GiftCertificateOrder::STATUS_INIT) {
  307.             throw $this->createNotFoundException();
  308.         }
  309.         $phone $request->request->get('phone');
  310.         if (\mb_strlen($phone) > 0) {
  311.             $phoneNumberObject $phoneNumberUtil->parse($phone);
  312.             if (!$phoneNumberUtil->isValidNumber($phoneNumberObject)) {
  313.                 return new JsonResponse(['error' => true'message' => 'Введен некорректный номер телефона']);
  314.             }
  315.         }
  316.         $order->setComment($request->request->get('comment'));
  317.         $order->setUsername($request->request->get('name'));
  318.         $order->setUserPhone($phone);
  319.         $paymentMethod $request->request->getInt('paymentMethod'PaymentType::ONLINE);
  320.         $order->setPaymentType($paymentMethod);
  321.         $user $order->getUser();
  322.         $codeCost $this->getOfferRepository()->getCodeCost($order->getOffer(), $order->getCodesCount());
  323.         $subscriber false;
  324.         if ($subscriptionService->isSubscriber($user)) {
  325.             $subscriber true;
  326.             $codeCost 0;
  327.         }
  328.         $isBatchCodes false;
  329.         if ($user->isBatchCodesAllowed()) {
  330.             $isBatchCodes true;
  331.             $codeCost 0;
  332.         }
  333.         if ($paymentMethod === PaymentType::SLIVKI_PAY) {
  334.             $codeCostForSlivkiPay $order->getCodesCount() * $codeCost;
  335.             if ($user->isBalanceAllowed($codeCost $order->getCodesCount())) {
  336.                 $codeCost 0;
  337.             }
  338.             try {
  339.                 $user->payOrder($order->getAmount() - ($codeCost $order->getCodesCount()), $codeCostForSlivkiPay);
  340.                 $paymentService->createCode($order$order->getCodesCount(), false);
  341.             } catch (InsufficientBalanceFundsException $exception) {
  342.                 return new JsonResponse(['error' => true]);
  343.             }
  344.             return new JsonResponse(['error' => false]);
  345.         }
  346.         if ($paymentMethod PaymentType::ONLINE) {
  347.             if ($subscriber || $isBatchCodes) {
  348.                 $order->setAmount($codeCost);
  349.                 $paymentService->createCode(
  350.                     $order,
  351.                     $order->getCodesCount(),
  352.                     false,
  353.                     null,
  354.                     false,
  355.                     $isBatchCodes UserBalanceActivity::TYPE_REDUCTION_BATCH_CODES null
  356.                 );
  357.                 return new JsonResponse(['error' => false]);
  358.             }
  359.             $order->setAmount($order->getCodesCount() * $codeCost);
  360.             $entityManager->flush();
  361.             return new JsonResponse([
  362.                 'redirectURL' => $this->redirectToRoute('buyCode', [
  363.                     'offerID' => $order->getOffer()->getID(),
  364.                     'codesCount' =>  $order->getCodesCount(),
  365.                     'orderID' => $order->getID(),
  366.                 ])->getTargetUrl()
  367.             ]);
  368.         }
  369.         if ($splitPaymentGiftCertificateChecker->isCheck($order)) {
  370.             $amount 0;
  371.             foreach ($order->getOfferOrderDetails() as $orderDetails) {
  372.                 $amount += $orderDetails->getPurchasePrice();
  373.             }
  374.             $order->setAmount($amount);
  375.         }
  376.         $partnerBePaidService->setOrder($order);
  377.         if ($user->isBalanceAllowed($codeCost $order->getCodeCost())) {
  378.             $codeCost 0;
  379.         }
  380.         $card $creditCardRepository->findById($request->request->getInt('creditCardID'));
  381.         if (null === $card || !$card->isOwner($this->getUser()->getID())) {
  382.             $paymentToken $partnerBePaidService->getPaymentToken($ordernull$codeCost);
  383.             if (!$paymentToken) {
  384.                 return new JsonResponse(['error' => true]);
  385.             }
  386.             $partnerBePaidService->createBePaidPaiment($order$paymentToken['checkout']['token']);
  387.             return new JsonResponse(['token' => $paymentToken['checkout']['token']]);
  388.         }
  389.         $amount $order->getAmount();
  390.         $result $partnerBePaidService->checkoutByToken($order$card->getID(), $amount);
  391.         if (!$result) {
  392.             return new JsonResponse(['error' => true]);
  393.         }
  394.         if (is_array($result) && isset($result['token'])) {
  395.             return new JsonResponse(['token' => $result['token']]);
  396.         }
  397.         $partnerBePaidService->createBePaidPaiment($order$result);
  398.         $successModalView CommonUtil::isMobileDevice($request)
  399.             ? 'Slivki/mobile/delivery/modal/success.html.twig'
  400.             'Slivki/delivery/modal/success.html.twig';
  401.         return new JsonResponse([
  402.             'error' => false,
  403.             'successModal' => $this->renderView(
  404.                 $successModalView, [
  405.                     'offerURL' => $seoResourceService->getOfferSeo($order->getOffer()->getID())->getMainAlias(),
  406.                 ],
  407.             ),
  408.         ]);
  409.     }
  410. }