src/Controller/GiftCertificatesController.php line 71

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