<?php
namespace Slivki\Controller;
use Doctrine\DBAL\Connection;
use Doctrine\Persistence\ManagerRegistry;
use libphonenumber\PhoneNumberUtil;
use Slivki\Dao\FastDelivery\OfferFastDeliveryDaoInterface;
use Slivki\Dao\Offer\DeliveryZoneDaoInterface;
use Slivki\Dao\Order\OfferOrderPurchaseCountDaoInterface;
use Slivki\Entity\City;
use Slivki\Entity\Director;
use Slivki\Entity\FoodOfferExtension;
use Slivki\Entity\FoodOfferOptionExtension;
use Slivki\Entity\FoodOrder;
use Slivki\Entity\GeoLocation;
use Slivki\Entity\Media\OfferExtensionMedia;
use Slivki\Entity\Offer;
use Slivki\Entity\OfferExtension;
use Slivki\Entity\OfferExtensionVariant;
use Slivki\Entity\OfferOrder;
use Slivki\Entity\OfferOrderDetails;
use Slivki\Entity\OnlineOrderHistory;
use Slivki\Entity\PriceDeliveryType;
use Slivki\Entity\Seo;
use Slivki\Entity\Street;
use Slivki\Entity\UserAddress;
use Slivki\Entity\UserBalanceActivity;
use Slivki\Entity\Visit;
use Slivki\Enum\OfferCode\PurchaseCountPeriod;
use Slivki\Enum\Order\PaymentType;
use Slivki\Exception\Order\InsufficientBalanceFundsException;
use Slivki\Handler\Order\OnlineOrderHistoryHandler;
use Slivki\Helpers\PhoneNumberHelper;
use Slivki\Helpers\WeightParserHelper;
use Slivki\Repository\Delivery\FoodFilterCounterRepositoryInterface;
use Slivki\Repository\Director\DirectorRepositoryInterface;
use Slivki\Repository\Offer\DeliveryZoneRepositoryInterface;
use Slivki\Repository\Offer\FoodOfferExtensionRepositoryInterface;
use Slivki\Repository\PurchaseCount\PurchaseCountRepositoryInterface;
use Slivki\Repository\SeoRepository;
use Slivki\Repository\StreetRepository;
use Slivki\Repository\User\CreditCardRepositoryInterface;
use Slivki\Services\ImageService;
use Slivki\Services\Mailer;
use Slivki\Services\MapProviders\CoordinatesYandex;
use Slivki\Services\Offer\CustomProductOfferSorter;
use Slivki\Services\Offer\DeliveryZoneSorter;
use Slivki\Services\Offer\OfferCacheService;
use Slivki\Services\Offer\ProductFastDeliveryService;
use Slivki\Services\PartnerBePaidService;
use Slivki\Services\Payment\PaymentService;
use Slivki\Services\Seo\SeoResourceService;
use Slivki\Services\ShippingSchedulerService;
use Slivki\Services\Subscription\SubscriptionService;
use Slivki\Util\CommonUtil;
use Slivki\Util\Iiko\AbstractDelivery;
use Slivki\Util\Iiko\Dominos;
use Slivki\Util\Iiko\IikoUtil;
use Slivki\Util\Iiko\SushiChefArts;
use Slivki\Util\Iiko\SushiHouse;
use Slivki\Util\Iiko\SushiVesla;
use Slivki\Util\Logger;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class IikoOrderController extends SiteController
{
private const KILOGRAM = 1000;
public const NEARLY = 'Ближайшее';
/** @Route("/delivery/select/{offerID}", name = "deliveryOrder") */
public function indexAction(
Request $request,
ContainerInterface $container,
FoodFilterCounterRepositoryInterface $foodFilterCounterRepository,
SeoResourceService $seoResourceService,
SubscriptionService $subscriptionService,
PurchaseCountRepositoryInterface $purchaseCountRepository,
OfferCacheService $offerCacheService,
DirectorRepositoryInterface $directorRepository,
OfferFastDeliveryDaoInterface $offerFastDeliveryDao,
$offerID
) {
$response = new Response();
$entityManager = $this->getDoctrine()->getManager();
/** @var Offer|false $offerCached */
$offerCached = $offerCacheService->getOffer($offerID, true, true);
if (false === $offerCached
|| !$offerCached->hasFreeCodes()
|| !($offerCached->isFoodOnlineOrderAllowedOnSite() || $offerCached->isAvailableOnFood())) {
return $this->redirect($seoResourceService->getOfferSeo($offerID)->getMainAlias());
}
$orderUtil = AbstractDelivery::instance($offerCached);
$orderUtil->setContainer($container);
$isDominos = $orderUtil instanceof Dominos;
$isSushiHouse = $orderUtil instanceof SushiHouse;
$data['isDominos'] = $isDominos;
$data['showSortingIndexOrder'] = !($isSushiHouse || $isDominos);
$cityID = $entityManager->getRepository(Offer::class)->getCityID($offerID);
$city = $entityManager->find(City::class, $cityID);
$request->getSession()->set(City::CITY_ID_SESSION_KEY, $city->getID());
$request->getSession()->set(City::CITY_DOMAIN_SESSION_KEY, $city->getDomain());
$data['offer'] = $offerCached;
Logger::instance('IIKO-DEBUG')->info($offerID);
$director = $directorRepository->getById((int) $offerCached->getDirectorID());
$data['company'] = $director;
$data['domain'] = $orderUtil->getDomain();
if (null !== $offerCached->getOnlineOrderSettings() && $offerCached->getOnlineOrderSettings()->getDomain()) {
$data['domain'] = $offerCached->getOnlineOrderSettings()->getDomain();
}
$data['dishes'] = [];
$user = $this->getUser();
if (null !== $user) {
if ($subscriptionService->isSubscriber($user)) {
$data['allowedCodesToBuy'] = $subscriptionService->getSubscription($user)->getNumberOfCodes();
} elseif ($user->isBatchCodesAllowed()) {
$data['allowedCodesToBuyBatchCodes'] = $user->getBatchCodesCount();
}
}
$data['options'] = [];
$data['robotsMeta'] = 'noindex, follow';
$data['offerID'] = $offerID;
$data['director'] = $director;
$data['minSumForFreeDelivery'] = $orderUtil->getMinSumForFreeDelivery();
$data['minOrderSum'] = $orderUtil->getMinOrderSum();
$data['foodOffer'] = true;
$data['formAction'] = '/delivery/order/checkout';
$data['showDelivery'] = true;
$data['categoryName'] = $orderUtil::CATEGORY_NAME;
$data['footerOfferConditionID'] = $offerID;
$data['categoryURL'] = $entityManager->getRepository(Seo::class)->getSeoForEntity(SeoRepository::RESOURCE_URL_OFFER_CATEGORY, $orderUtil::CATEGORY_ID)->getMainAlias();
$data['deliveryPrice'] = $orderUtil->getDeliveryPriceSettings();
$data['pickupEnabled'] = $orderUtil->isPickupEnabled();
$data['deliveryEnabled'] = $orderUtil->isDeliveryEnabled();
$data['isBuyCodeDisable'] = $offerCached->isBuyCodeDisable();
$data['isOnlineOrderAllowed'] = $offerCached->isFoodOnlineOrderAllowedOnSite();
$data['isAvailableOnFood'] = $offerCached->isAvailableOnFood();
$data['visitCount'] = $entityManager->getRepository(Visit::class)->getVisitCount($orderUtil::OFFER_ID, Visit::TYPE_OFFER, 30, true);
$data['filterAction'] = $foodFilterCounterRepository->findByOfferId((int) $offerID);
$purchaseCount = $purchaseCountRepository->findByOfferId((int) $offerID);
$data['purchaseCountMonth'] = null === $purchaseCount ? 0 : $purchaseCount->getPurchaseCountLastMonthWithCorrection();
$data['sortList'] = CustomProductOfferSorter::SORT_LIST;
if (!$offerFastDeliveryDao->isOfferHasActiveFastDelivery($offerID)) {
unset($data['sortList'][CustomProductOfferSorter::FAST_CUSTOM_PRODUCT_SORT]);
}
$view = CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/order.html.twig' : 'Slivki/delivery/order.html.twig';
$response->setContent($this->renderView($view, $data));
return $response;
}
/** @Route("/delivery/order/checkout", name = "deliveryOrderCheckout") */
public function checkoutAction(
Request $request,
ShippingSchedulerService $shippingSchedulerService,
ContainerInterface $container,
ManagerRegistry $registry,
SeoResourceService $seoResourceService,
SubscriptionService $subscriptionService,
DeliveryZoneDaoInterface $deliveryZoneDao,
DeliveryZoneSorter $deliveryZoneSorter
) {
ini_set('memory_limit', '1g');
$additionalDominos = null;
$response = new Response();
$offerID = $request->request->getInt('offerID');
$entityManager = $this->getDoctrine()->getManager();
$requestBasket = $request->request->get('basket');
$pickupDeliveryType = empty($request->request->get('pickupDeliveryType')) ? FoodOfferExtension::DELIVERY_METHOD : $request->request->getInt('pickupDeliveryType');
if (!$requestBasket) {
return $this->redirectToRoute('deliveryOrder', ['offerID' => $offerID]);
}
$request->getSession()->set(OnlineOrderHistory::SORT_SESSION_NAME, $request->request->get('dishSortBy'));
/** @var Offer $offer */
$offer = $entityManager->find(Offer::class, $offerID);
if (!$offer->hasFreeCodes()) {
return $this->redirect($seoResourceService->getOfferSeo($offerID)->getMainAlias());
}
$iikoUtil = AbstractDelivery::instance($offer);
$iikoUtil->setContainer($container);
$isSushiVesla = $iikoUtil instanceof SushiVesla;
$isDominos = $iikoUtil instanceof Dominos;
if ($isDominos) {
$dominosSpesialData = [
'amountPizza' => 0,
];
}
$requestBasket = json_decode($requestBasket, true);
$basket = [];
foreach ($requestBasket as $basketItem) {
$key = array_key_first($basketItem);
$variants = [];
if (is_array($basketItem[$key])) {
foreach ($basketItem[$key] as $variantItem) {
$variantKey = array_key_first($variantItem);
$variants[$variantKey] = $variantItem[$variantKey];
}
} else {
$variants = $basketItem[$key];
}
$basket[$key] = $variants;
}
$totalDishCount = 0;
foreach ($basket as $dishID => $variants) {
$extension = $entityManager->find(OfferExtension::class, $dishID);
if (!$extension || $extension instanceof FoodOfferOptionExtension) {
continue;
}
$dishCount = 0;
if (!is_array($variants)) {
$dishCount = $variants;
} else {
foreach ($variants as $variantID => $variantCount) {
$extensionVariant = $entityManager->find(OfferExtensionVariant::class, $variantID);
if (!$extensionVariant) {
continue;
}
$dishCount += $variantCount;
if ($isDominos) {
$dominosSpesialData['amountPizza'] += $variantCount;
}
}
}
$totalDishCount += $dishCount;
}
if ($isDominos && $dominosSpesialData['amountPizza'] === 0) {
return new JsonResponse(['status' => 'error', 'error' => true, 'message' => 'Скидка на доп. меню действует только при заказе пиццы']);
}
if ($totalDishCount == 0) {
return $this->redirectToRoute('deliveryOrder', ['offerID' => $offerID]);
}
$user = $this->getUser();
/** @var OfferOrder $order */
$order = new FoodOrder();
$order->setUser($user);
$order->setStatus(FoodOrder::STATUS_INIT);
$order->setOffer($offer);
$totalAmount = 0;
$totalOfferAmount = 0;
$codesCount = 0;
$city = $entityManager->find(City::class, $iikoUtil::CITY_ID);
$request->getSession()->set(City::CITY_ID_SESSION_KEY, $city->getID());
$request->getSession()->set(City::CITY_DOMAIN_SESSION_KEY, $city->getDomain());
$offersDetails = [];
foreach ($basket as $dishID => $variants) {
/** @var OfferExtension $extension */
$extension = $entityManager->find(OfferExtension::class, $dishID);
if (!$extension) {
continue;
}
if (is_array($variants)) {
foreach ($variants as $variantID => $variantCount) {
/** @var OfferExtensionVariant $extensionVariant */
$extensionVariant = $entityManager->find(OfferExtensionVariant::class, $variantID);
if (!$extensionVariant) {
continue;
}
$productsPerCode = $extension->getProductsPerCode();
if ($productsPerCode > 0) {
$codesCount += $productsPerCode == 1 ? $variantCount : $variantCount/$productsPerCode;
}
$variantOfferPrice = PriceDeliveryType::calcDeliveryPickupPrice(
$extension,
$pickupDeliveryType,
$extensionVariant->getRegularPrice(),
$extensionVariant->getOfferPrice(),
$additionalDominos
);
$totalOfferAmount += $variantCount * $variantOfferPrice;
$totalAmount += $variantCount * $extensionVariant->getRegularPrice();
$details = new OfferOrderDetails();
$details->setOfferExtension($extension);
$details->setOfferExtensionVariant($extensionVariant);
$details->setItemsCount($variantCount);
$order->addOfferOrderDetails($details);
}
} else {
$count = (int) $variants;
if (0 === $count) {
continue;
}
$product = $isSushiVesla
? $iikoUtil->getProductByDB($extension->getPartnerItemID(), $registry)
: $iikoUtil->getProduct($extension->getPartnerItemID());
if ($product->regularPrice == 0) {
$product->regularPrice = $extension->getPrice();
}
$totalAmount += $count * $product->regularPrice;
$recalculatedOfferPriceValue = PriceDeliveryType::calcDeliveryPickupPrice(
$extension,
$pickupDeliveryType,
$product->regularPrice,
$extension->getCurrentPrice(null, $pickupDeliveryType),
);
$product->offerPrice = $recalculatedOfferPriceValue;
$totalOfferAmount += $count * $product->offerPrice;
if (!$extension instanceof FoodOfferOptionExtension) {
$productsPerCode = $extension->getProductsPerCode();
if ($productsPerCode > 0) {
$codesCount += $productsPerCode == 1 ? $count : $count/$productsPerCode;
}
}
$details = new OfferOrderDetails();
$details->setOfferExtension($extension);
$details->setItemsCount($count);
$order->addOfferOrderDetails($details);
}
}
$codesCount = \ceil($codesCount);
$codeCost = $this->getOfferRepository()->getCodeCost($offer, $codesCount);
$codeCostRegular = $codeCost;
$user = $order->getUser();
$allowedCodesToBuyBalance = false;
if ($subscriptionService->isSubscriber($user) || $user->isBatchCodesAllowed()) {
$codeCost = 0;
} elseif ($user->isBalanceAllowed($codesCount * $codeCost)) {
$codeCost = 0;
$allowedCodesToBuyBalance = true;
}
$totalAmountWithoutCode = $totalOfferAmount;
$totalOfferAmount += $codesCount * $codeCost;
$order->setCodesCount($codesCount);
$deliveryPrice = $iikoUtil->getMinSumForFreeDelivery() > 0 && $totalAmountWithoutCode < $iikoUtil->getMinSumForFreeDelivery() ? $iikoUtil->getDeliveryPriceSettings() : 0;
// Delivery price will be calculated after choosing the address
if (null !== $offer->getOfferDeliveryZone() && $offer->getOfferDeliveryZone()->count() > 0) {
$deliveryPrice = 0;
}
if ($pickupDeliveryType === FoodOfferExtension::DELIVERY_METHOD_PICKUP) {
$deliveryPrice = 0;
}
$order->setAmount($totalOfferAmount + $deliveryPrice);
$order->setDeliveryCost($deliveryPrice);
if (CommonUtil::isMobileDevice($request)) {
$order->setDeviceType(SiteController::DEVICE_TYPE_MOBILE);
} else {
$order->setDeviceType(SiteController::DEVICE_TYPE_DESKTOP);
}
$entityManager->persist($order);
$entityManager->flush();
$entityManager->detach($order);
$deliveryAddresses = $user->getAvailableUserAddresses($offerID);
$defaultDeliveryAddress = empty($deliveryAddresses) ? false : $deliveryAddresses[0];
$deliveryAddressesGift = $user->getAvailableUserAddressesGift($offerID);
if ($order->isOnlineGift()) {
$defaultDeliveryAddress = $deliveryAddressesGift[0] ?? false;
$deliveryAddresses = $deliveryAddressesGift;
}
$brandboxEnabled = $offer->getBrandboxEnabled();
$deliveryEnabled = $iikoUtil->isDeliveryEnabled();
$pickupEnabled = $iikoUtil->isPickupEnabled();
$isAjaxScheduleForDelivery = false;
$schedule = $shippingSchedulerService->getEmptySchedule($iikoUtil, $pickupDeliveryType);
if (
($brandboxEnabled && $pickupDeliveryType === FoodOfferExtension::DELIVERY_METHOD && $deliveryAddresses) ||
(!$brandboxEnabled && $deliveryEnabled && $deliveryAddresses)
) {
$schedule = $shippingSchedulerService->getDeliverySchedule($iikoUtil, $pickupDeliveryType);
}
$citySelect = '';
$citySelectData = $iikoUtil->getCitySelectData($entityManager);
if ($citySelectData) {
$citySelect = $this->renderView(CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/city_select.html.twig'
: 'Slivki/delivery/city_select.html.twig', ['deliveryLocations' => $citySelectData]);
}
$workHourFrom = 0;
$workHourTo = 0;
$pickupLocations = '';
$defaultLocationID = null;
/** @var GeoLocation $geoLocation */
foreach ($offer->getGeoLocations() as $geoLocation) {
if (!$geoLocation->isActive()) {
continue;
}
if (!$defaultLocationID) {
$defaultLocationID = $geoLocation->getID();
}
$pickupPointScheduleParsed = $geoLocation->getPickupPointScheduleParsed();
if (!$pickupPointScheduleParsed) {
continue;
}
$pickupLocations .= $this->renderView('Slivki/delivery/pickup_location_item.html.twig', [
'location' => $geoLocation,
]);
}
$nearestTime = 'Ближайшее';
$deliveryTimeFrom = $iikoUtil->getDeliveryTimeFrom();
$deliveryTimeTill = $iikoUtil->getDeliveryTimeTill();
$additionalDominos = !(null === $additionalDominos);
$this->reCalcOrder(
$order,
0,
$pickupDeliveryType,
$subscriptionService->isSubscriber($this->getUser()),
);
$data = [
'order' => $order,
'offer' => $offer,
'codeCost' => $codeCost,
'codeCostRegular' => $codeCostRegular,
'deliveryPrice' => $deliveryPrice,
'offerURL' => $entityManager->getRepository(Seo::class)->getOfferURL($offer->getID())->getMainAlias(),
'totalAmount' => $totalAmount + $deliveryPrice,
'director' => $offer->getDirectors()->first(),
'robotsMeta' => 'noindex, follow',
'offerID' => $offerID,
'showCheckAddressButton' => $iikoUtil::SHOW_CHECK_ADDRESS_BUTTON,
'streetSuggest' => $iikoUtil::STREET_SUGGEST,
'workHourFrom' => $workHourFrom,
'workHourTo' => $workHourTo,
'citySelect' => $citySelect,
'multipleLocationDelivery' => $iikoUtil::MULTIPLE_LOCATIONS_DELIVERY,
'formAction' => '/delivery/order/check-payment',
'categoryName' => $iikoUtil::CATEGORY_NAME,
'categoryURL' => $entityManager->getRepository(Seo::class)->getSeoForEntity(SeoRepository::RESOURCE_URL_OFFER_CATEGORY, $iikoUtil::CATEGORY_ID)->getMainAlias(),
'pickupLocations' => $pickupLocations,
'nearestTimeLabel' => $nearestTime,
'showDelivery' => true,
'defaultLocationID' => $defaultLocationID,
'pickupEnabled' => $pickupEnabled,
'deliveryEnabled' => $deliveryEnabled,
'allowedPaymentMethods' => $iikoUtil->getAllowedPaymentMethods(),
'footerOfferConditionID' => $offerID,
'pickupDiscount' => $iikoUtil->getPickupDiscount(),
'pickupDeliveryType' => $pickupDeliveryType,
'deliveryTimeFrom' => $deliveryTimeFrom,
'deliveryTimeTill' => $deliveryTimeTill,
'orderPeriodInDays' => $iikoUtil->getOrderPeriodInDays(),
'offersDetails' => $offersDetails,
'schedule' => $schedule,
'deliveryAddresses' => $deliveryAddresses,
'deliveryAddressesGift' => $deliveryAddressesGift,
'defaultDeliveryAddress' => $defaultDeliveryAddress,
'brandboxEnabled' => $brandboxEnabled,
'additionalDominos' => $additionalDominos,
'isSushiVesla' => $isSushiVesla,
'isDominos' => $isDominos,
'isAjaxScheduleForDelivery' => $isAjaxScheduleForDelivery,
'isOnlineGift' => $offer->isOnlineOrderGiftEnabled(),
'allowedCodesToBuyBalance' => $allowedCodesToBuyBalance,
'deliveryZones' => $deliveryZoneSorter->sortByDefault($deliveryZoneDao->findByOfferId($offerID)),
];
$data['iikoOrder'] = true;
$view = CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/delivery_checkout.html.twig' : 'Slivki/delivery/delivery_checkout.html.twig';
$content = $this->renderView($view, $data);
$response->setContent($content);
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
return $response;
}
/**
* @Route("/delivery/order/payment/{orderID}", name="delivery_order_payment")
*/
public function deliveryOrderPaymentAction(
Request $request,
PartnerBePaidService $partnerBePaidService,
OnlineOrderHistoryHandler $onlineOrderHistoryHandler,
SubscriptionService $subscriptionService,
CreditCardRepositoryInterface $creditCardRepository,
DirectorRepositoryInterface $directorRepository,
$orderID
) {
$entityManager = $this->getDoctrine()->getManager();
$response = new Response();
/** @var FoodOrder $order */
$order = $entityManager->find(FoodOrder::class, $orderID);
if (!$order) {
throw $this->createNotFoundException();
}
$user = $order->getUser();
$offer = $order->getOffer();
$offerID = $offer->getID();
$iikoUtil = IikoUtil::instance($offer);
$iikoUtil->setContainer($this->kernel->getContainer());
$isPickup = $order->getDeliveryAddress()->isPickup();
$codeCost = $this->getOfferRepository()->getCodeCost($offer);
$regularCodeCost = $codeCost;
$allowedCodesToBuyBalance = false;
if ($subscriptionService->isSubscriber($user) || $user->isBatchCodesAllowed()) {
$codeCost = 0;
} elseif ($user->isBalanceAllowed($codeCost * $order->getCodesCount())) {
$codeCost = 0;
$allowedCodesToBuyBalance = true;
}
$detailIdCount = [];
$totalAmount = 0;
/** @var OfferOrderDetails $details */
foreach ($order->getOfferOrderDetails() as $details) {
if ($iikoUtil instanceof SushiHouse) {
$extension = $details->getOfferExtension();
if (isset($detailIdCount[$extension->getID()])) {
$detailIdCount[$extension->getID()] += $details->getItemsCount();
} else {
$detailIdCount[$extension->getID()] = $details->getItemsCount();
}
}
$variant = $details->getOfferExtensionVariant();
$regularPrice = $variant ? $variant->getRegularPrice() : $details->getOfferExtension()->getPrice();
$totalAmount += $details->getItemsCount() * $regularPrice;
$extension = $details->getOfferExtension();
$sortByFromDelivery = $request->getSession()->get(OnlineOrderHistory::SORT_SESSION_NAME);
if (null !== $sortByFromDelivery) {
$onlineOrderHistoryHandler->handle(
$order,
$extension->getID(),
$sortByFromDelivery
);
}
}
$request->getSession()->set(OnlineOrderHistory::SORT_SESSION_NAME, null);
$pickupDeliveryType = $isPickup ? FoodOfferExtension::DELIVERY_METHOD_PICKUP : FoodOfferExtension::DELIVERY_METHOD;
$deliveryCost = 0;
if ($pickupDeliveryType === FoodOfferExtension::DELIVERY_METHOD || !$isPickup) {
$totalAmount += $order->getDeliveryCost();
$deliveryCost = $order->getDeliveryCost();
}
$partnerBePaidService->setOrder($order);
$paymentToken = $partnerBePaidService->getPaymentToken($order, null, $codeCost);
$view = CommonUtil::isMobileDevice($request)
? 'Slivki/mobile/delivery/delivery_payment.html.twig'
: 'Slivki/delivery/delivery_payment.html.twig';
$offersDetails = [];
$director = $directorRepository->findById($offer->getDirectorID());
$fullOrderAmount = $order->getAmount();
if ($allowedCodesToBuyBalance) {
$fullOrderAmount += $regularCodeCost * $order->getCodesCount();
}
$content = $this->renderView($view, [
'order' => $order,
'offer' => $offer,
'offerURL' => $entityManager->getRepository(Seo::class)->getOfferURL($offerID)->getMainAlias(),
'offerID' => $offerID,
'categoryName' => $iikoUtil::CATEGORY_NAME,
'deliveryPrice' => $deliveryCost,
'codeCost' => $codeCost,
'totalAmount' => $totalAmount,
'showCheckAddressButton' => false,
'categoryURL' => $entityManager->getRepository(Seo::class)->getSeoForEntity(SeoRepository::RESOURCE_URL_OFFER_CATEGORY, $iikoUtil::CATEGORY_ID)->getMainAlias(),
'isPickup' => $isPickup,
'allowedPaymentMethods' => $iikoUtil->getAllowedPaymentMethods()[$isPickup ? 'pickup' : 'delivery'],
'pickupDiscount' => $isPickup ? $iikoUtil->getPickupDiscount() : 0,
'pickupDeliveryType' => $pickupDeliveryType,
'paymentToken' => $paymentToken['checkout']['token'],
'offersDetails' => $offersDetails,
'additionalDominos' => false,
'isDominos' => $iikoUtil instanceof Dominos,
'activeCreditCards' => !$offer->isRecurrentDisabled() ? $creditCardRepository->findActiveByUser($user) : [],
'directorName' => $director instanceof Director ? $director->getName() : '',
'allowedCodesToBuyBalance' => $allowedCodesToBuyBalance,
'isSlivkiPayAllowed' => $fullOrderAmount <= $user->getFullBalance() && $order->getAmount() <= $user->getMoneyBalance(),
'allowedCashbackSumToPay' => $iikoUtil->getAllowedCashbackSumToPay($order, $entityManager),
'allowedFastDeliveryForSushiHouse' => $iikoUtil->enabledFastDelivery($order),
]);
$response->setContent($content);
return $response;
}
/** @Route("/delivery/order/check-payment", name = "deliveryOrderCheckPayment") */
public function checkPaymentAction(
Request $request,
CoordinatesYandex $coordinatesYandex,
DeliveryZoneRepositoryInterface $deliveryZoneRepository,
ShippingSchedulerService $shippingSchedulerService,
SubscriptionService $subscriptionService,
PhoneNumberUtil $phoneNumberUtil,
PhoneNumberHelper $phoneNumberHelper
) {
if (!$request->isMethod(Request::METHOD_POST)) {
throw $this->createNotFoundException();
}
$entityManager = $this->getDoctrine()->getManager();
$orderID = $request->request->getInt('orderID');
$pickupDeliveryType = $request->request->get('pickupDeliveryType');
$pickupDeliveryType = $pickupDeliveryType ? (int) $pickupDeliveryType : null;
$isOnlineOrderGift = $request->request->getBoolean('isOnlineGift');
$discount = 0;
/** @var FoodOrder $order */
$order = $entityManager->find(FoodOrder::class, $orderID);
if (!$order || $order->getUser()->getID() != $this->getUser()->getID() || $order->getStatus() != FoodOrder::STATUS_INIT) {
throw $this->createNotFoundException();
}
$order->setComment($request->request->get('comment'));
$order->setDeliveryTime($request->request->get('deliveryTime'));
$order->setIsOnlineGift($isOnlineOrderGift);
$iikoUtil = IikoUtil::instance($order->getOffer());
$iikoUtil->setContainer($this->kernel->getContainer());
$possibilityOrder = $iikoUtil->getPossibilityOrderStatus($order);
if ($possibilityOrder['status'] === 'error') {
return new JsonResponse(['status' => 'error', 'error' => true, 'message' => $possibilityOrder['message']]);
}
$isSushiHouse = $iikoUtil instanceof SushiHouse;
$isSushiVesla = $iikoUtil instanceof SushiVesla;
if (!$isSushiHouse && !$isSushiVesla) {
$this->reCalcOrder(
$order,
0,
$pickupDeliveryType,
$subscriptionService->isSubscriber($this->getUser()),
);
}
$request->getSession()->set("pickupDiscount", null);
if ($request->request->has('pickup')) {
$addressID = $request->request->getInt('pickupAddressID');
$discount = $request->request->getInt('pickupDiscount');
$request->getSession()->set("pickupDiscount", $discount);
$geoLocation = $entityManager->find(GeoLocation::class, $addressID);
$userAddresses = $entityManager->getRepository(UserAddress::class)->findBy(['user' => $this->getUser(), 'geoLocation' => $geoLocation]);
$address = null;
foreach ($userAddresses as $location) {
if ($location->getGeoLocation()->getID() == $addressID) {
$address = $location;
break;
}
}
if (!$address) {
$address = new UserAddress();
$address->setUser($this->getUser());
$address->setGeoLocation($geoLocation);
$address->setOfferID($order->getOffer()->getID());
$entityManager->persist($address);
}
$address->setPickup(true);
} else {
$address = $entityManager->find(UserAddress::class, $request->request->getInt('addressID'));
$geoLocation = null;
}
if ($address) {
$name = $request->request->get('name', '');
$phone = $request->request->get('phone', '');
if (trim($name) == '' || trim($phone) == '') {
return new JsonResponse(['error' => true]);
}
if (\mb_strlen($phone) > 0) {
$phoneNumberObject = $phoneNumberUtil->parse($phone);
if (!$phoneNumberUtil->isValidNumber($phoneNumberObject)) {
return new JsonResponse(['error' => true, 'message' => 'Введен некорректный номер телефона']);
}
}
$address->setPhone($phone);
$address->setName($name);
$address->setIsOnlineGift($isOnlineOrderGift);
if ($isOnlineOrderGift) {
$address->setNameGift($request->request->get('nameGift'));
$address->setPhoneNumberGift(
$phoneNumberHelper->convert($request->request->get('phoneNumberGift'), ''),
);
}
$order->setDeliveryAddress($address);
} else {
return new JsonResponse(['error' => true, 'message' => 'Не выбран адрес']);
}
$result = $iikoUtil->checkOrder($entityManager, $order, $subscriptionService);
if (!$result || $result->resultState > 0) {
$message = null;
if ($result) {
switch ($result->resultState) {
case 1:
if (isset($result->problem)) {
$message = $result->problem;
}
if (isset($result->minSumForFreeDelivery)) {
$message = \sprintf('Минимальная сумма заказа %s руб.', (string) $result->minSumForFreeDelivery);
}
break;
case 2:
$message = 'Извините, в данное время заказ невозможен. Пожалуйста, выберите другое время';
break;
case 3:
$message = 'Извините, на данный адрес доставка не осуществляется';
break;
case 4:
case 5:
$message = 'На данный момент заказ одного из товаров невозможен';
break;
case 9999:
$message = 'Заказы принимаются с 11:00 по 22:20';
break;
}
}
return new JsonResponse(['error' => true, 'message' => $message]);
}
if ($request->request->get('deliveryTime') !== self::NEARLY) {
if ($request->request->get('deliveryTime') === null) {
$checkSchedule = [
'status' => 'error',
'message' => 'Выберите время',
];
} else {
$checkSchedule = $iikoUtil->checkSchedule($shippingSchedulerService, $geoLocation, $pickupDeliveryType, $request->request->get('deliveryTime'));
}
if ($checkSchedule['status'] === 'error') {
return new JsonResponse(['status' => $checkSchedule['status'], 'message' => $checkSchedule['message'], 'error' => true], Response::HTTP_OK);
}
}
if (null !== $order->getOffer()->getOfferDeliveryZone() && $order->getOffer()->getOfferDeliveryZone()->count() > 0) {
if (null === $address->isPickup()) {
$points = $address->getCoordinatesForDeliveryZone() ?? $coordinatesYandex->getGeoCoordinates(
$address->buildFullAddress(),
['offerId' => (int)$order->getOffer()->getID()]
);
$deliveryZone = $deliveryZoneRepository->getPolygonByPoint($order->getOffer(), $points);
if (null !== $deliveryZone) {
$user = $order->getUser();
$codeCost = $this->getOfferRepository()->getCodeCost($order->getOffer(), $order->getCodesCount());
if ($subscriptionService->isSubscriber($user) || $user->isBatchCodesAllowed() || $user->isBalanceAllowed($codeCost * $order->getCodesCount())) {
$codeCost = 0;
}
$total = $order->getAmount() - ($order->getCodesCount() * $codeCost);
if ($total < $deliveryZone->getMinOrderAmount()) {
return new JsonResponse([
'error' => true,
'message' => \sprintf('До минимальной суммы заказа в этой зоне %s р.', (string) ($deliveryZone->getMinOrderAmount() - $total)),
]);
}
$order->setDeliveryZoneLocationId($deliveryZone->getGeoLocationId());
$order->setDeliveryCost($deliveryZone->getPaidDeliveryAmount());
if ($total >= $deliveryZone->getFreeDeliveryAmount()) {
$order->setDeliveryCost(0);
}
if (null === $address->getCoordinatesForDeliveryZone()) {
$coordinates = explode(' ', $points);
$address->setLatitude($coordinates[1]);
$address->setLongitude($coordinates[0]);
}
} else {
return new JsonResponse([
'error' => true,
'message' => 'Данный адрес не входит в зону доставки. Выберите другой адрес.',
]);
}
} else {
$order->setDeliveryZoneLocationId($address->getGeoLocation()->getID());
}
}
$this->reCalcOrder(
$order,
$discount,
$pickupDeliveryType,
$subscriptionService->isSubscriber($this->getUser()),
);
$entityManager->flush();
return new JsonResponse(['error' => false, 'redirectURL' => '/delivery/order/payment/' . $order->getID() ]);
}
/**
* @Route("/delivery/order/pay/{orderID}", name="deliveryOrderPay")
*/
public function payAction(
Request $request,
PartnerBePaidService $partnerBePaidService,
PaymentService $paymentService,
CreditCardRepositoryInterface $creditCardRepository,
SubscriptionService $subscriptionService,
ContainerInterface $container,
$orderID
) {
$paymentMethod = $request->request->getInt('paymentMethod');
$entityManager = $this->getDoctrine()->getManager();
$order = $entityManager->find(FoodOrder::class, $orderID);
if (null === $order) {
return new JsonResponse(['error' => true]);
}
$iikoUtil = IikoUtil::instance($order->getOffer());
$iikoUtil->setContainer($container);
$order->setPaymentType($paymentMethod);
$order->setPaymentMethodID(OfferOrder::METHOD_BEPAID);
$isUsePartnerCashbackBalance = $request->request->getBoolean('usePartnerCashbackBalance');
$order->setUsePartnerCashbackBalance($isUsePartnerCashbackBalance);
if ($isUsePartnerCashbackBalance) {
$allowedCashbackSumToPay = $iikoUtil->getAllowedCashbackSumToPay($order, $entityManager);
$order->setUsedPartnerCashbackSum($allowedCashbackSumToPay);
}
$order->setUseFastDelivery(
$request->request->getBoolean('useFastDelivery')
);
$codeCost = $this->getOfferRepository()->getCodeCost($order->getOffer(), $order->getCodesCount());
$codeCostRegular = $codeCost;
$user = $order->getUser();
$subscriber = false;
if ($subscriptionService->isSubscriber($user)) {
$subscriber = true;
$codeCost = 0;
}
$isBatchCodes = false;
if ($user->isBatchCodesAllowed()) {
$isBatchCodes = true;
$codeCost = 0;
}
if ($paymentMethod === PaymentType::SLIVKI_PAY) {
$codeCostForSlivkiPay = $order->getCodesCount() * $codeCost;
if ($user->isBalanceAllowed($codeCost * $order->getCodesCount())) {
$codeCost = 0;
}
try {
$orderAmount = $order->getAmount() - ($codeCost * $order->getCodesCount());
if ($order->getUsedPartnerCashbackSum() > 0) {
$orderAmount -= $order->getUsedPartnerCashbackSum();
}
$user->payOrder($orderAmount, $codeCostForSlivkiPay);
$paymentService->createCode($order, $order->getCodesCount(), false);
} catch (InsufficientBalanceFundsException $exception) {
return new JsonResponse(['error' => true]);
}
return new JsonResponse(['error' => false]);
}
if ($paymentMethod > PaymentType::ONLINE) {
if ($subscriber || $isBatchCodes) {
$order->setAmount($codeCost);
$paymentService->createCode(
$order,
$order->getCodesCount(),
false,
null,
false,
$isBatchCodes ? UserBalanceActivity::TYPE_REDUCTION_BATCH_CODES : null
);
return new JsonResponse(['error' => false]);
}
$order->setAmount($order->getCodesCount() * $codeCost);
$entityManager->flush();
return new JsonResponse([
'redirectURL' => $this->redirectToRoute('buyCode', [
'offerID' => $order->getOffer()->getID(),
'codesCount' => $order->getCodesCount(),
'orderID' => $order->getID()
]
)->getTargetUrl()
]);
}
if ($user->isBalanceAllowed($codeCost * $order->getCodesCount())) {
$codeCost = 0;
}
$order->setPaymentType(PaymentType::ONLINE);
$deliveryType = $order->getDeliveryAddress()->isPickup() ? FoodOfferExtension::DELIVERY_METHOD_PICKUP : FoodOfferExtension::DELIVERY_METHOD;
$discount = $request->getSession()->get("pickupDiscount") ? $request->getSession()->get("pickupDiscount") : 0;
$this->reCalcOrder(
$order,
$discount,
$deliveryType,
$subscriptionService->isSubscriber($user),
);
$iikoUtil->modifyOrder($order, $entityManager);
$entityManager->flush();
$partnerBePaidService->setOrder($order);
$card = $creditCardRepository->findById($request->request->getInt('creditCardID'));
if (null === $card || !$card->isOwner($this->getUser()->getID())) {
$paymentToken = $partnerBePaidService->getPaymentToken($order, null, $codeCost);
if (!$paymentToken) {
return new JsonResponse(['error' => true]);
}
$partnerBePaidService->createBePaidPaiment($order, $paymentToken['checkout']['token']);
return new JsonResponse([
'token' => $paymentToken['checkout']['token'],
]);
}
$offerSettings = $order->getOffer()->getOnlineOrderSettings();
if (($iikoUtil::SPLIT_PAYMENT || ($offerSettings && $offerSettings->isSplitPayment()))
&& (!$subscriber && !$user->isBatchCodesAllowed() && !$user->isBalanceAllowed($codeCostRegular * $order->getCodesCount()))
) {
$amount = $order->getAmount() - $order->getCodesCount() * $codeCost;
} else {
$amount = $order->getAmount();
}
$result = $partnerBePaidService->checkoutByToken($order, $card->getID(), $amount);
if (!$result) {
return new JsonResponse(['error' => true]);
}
if (is_array($result) && isset($result['token'])) {
return new JsonResponse(['token' => $result['token']]);
}
$partnerBePaidService->createBePaidPaiment($order, $result);
return new JsonResponse(['error' => false]);
}
/** @Route("/delivery/street/suggest/{offerID}") */
public function deliveryStreetSuggest(Request $request, $offerID): JsonResponse
{
/** @var StreetRepository $street */
$street = $this->getDoctrine()->getManager()->getRepository(Street::class);
$streets = $street->getStreets($offerID, $request->query->get('q'));
return new JsonResponse($streets);
}
/** @Route("/delivery/feedback/{offerID}") */
public function feedbackAction(Request $request, Mailer $mailer, $offerID) {
$text = $request->request->get('name') . ', ' . $request->request->get('email') . "\n" . $request->request->get('message') . "\n";
$subj = 'Фидбек с доставки суши';
if ($offerID == 'subscription-landing') {
$subj = 'Фидбек с лендинга подписки';
} else if ($offerID == 'auth') {
$subj = 'Фидбек с попапа авторизации';
} else {
$offerID = (int)$offerID;
$offer = $this->getDoctrine()->getManager()->find(Offer::class, $offerID);
if ($offer) {
$text .= 'Акция: ' . $offer->getTitle();
}
}
$message = $mailer->createMessage($subj, $text);
$message->setFrom('info@slivki.by', 'Slivki.by');
$message->setTo('1@slivki.by')
->addTo('info@slivki.by')
->addTo('yuri@slivki.com')
->addCc('dmitry.kazak@slivki.com');
$mailer->send($message);
return new Response();
}
private function reCalcOrder(
FoodOrder $order,
$discount = 0,
$typePrice = null,
bool $isSubscriber = false
) {
/** @var OfferOrderDetails $details */
$orderSum = 0;
$additionalInfo = $order->getAdditionalInfo();
$additionalDominos = false;
if (isset($additionalInfo['dominosCoupon'])) {
$additionalDominos = true;
}
$iikoUtil = AbstractDelivery::instance($order->getOffer());
$iikoUtil->setContainer($this->kernel->getContainer());
foreach ($order->getOfferOrderDetails() as $details) {
$variant = $details->getOfferExtensionVariant();
if ($variant) {
$extension = $variant->getOfferExtension();
if ($additionalDominos) {
$variantAdditionalDominos = $variant;
} else {
$variantAdditionalDominos = null;
}
$purchasePrice = PriceDeliveryType::calcDeliveryPickupPrice(
$extension,
$typePrice,
$variant->getRegularPrice(),
$variant->getOfferPrice(),
$variantAdditionalDominos
);
} else {
$extension = $details->getOfferExtension();
$product = $iikoUtil->getProduct($extension->getPartnerItemID());
$purchasePrice = PriceDeliveryType::calcDeliveryPickupPrice(
$extension,
$typePrice,
$product->regularPrice,
$extension->getCurrentPrice(null, $typePrice),
);
}
$orderSum += $details->getItemsCount() * $purchasePrice;
$details->setPurchasePrice($purchasePrice);
}
$deliveryCost = $order->getDeliveryCost();
if (
($typePrice !== null && (int) $typePrice === FoodOfferExtension::DELIVERY_METHOD_PICKUP)
|| (null !== $order->getDeliveryAddress() && $order->getDeliveryAddress()->isPickup())
) {
$deliveryCost = 0;
}
$order->setDeliveryCost($deliveryCost);
$regularCodeCost = $this->getOfferRepository()->getCodeCost($order->getOffer());
$codeCost = 0;
if (!$isSubscriber
&& !$order->getUser()->isBatchCodesAllowed()
&& !$order->getUser()->isBalanceAllowed($regularCodeCost * $order->getCodesCount())
) {
$codeCost = $regularCodeCost;
}
$orderSum += $codeCost * $order->getCodesCount() + $deliveryCost;
if ($discount > 0) {
$orderSum -= ($orderSum * ($discount / 100));
}
if ($order->getUsedPartnerCashbackSum() > 0) {
$orderSum -= $order->getUsedPartnerCashbackSum();
}
$order->setAmount($orderSum);
}
/**
* @Route("/delivery/check-address", name="delivery_check_address")
*/
public function checkAddressAction(Request $request, SubscriptionService $subscriptionService): JsonResponse
{
$entityManager = $this->getDoctrine()->getManager();
$orderID = $request->request->getInt('orderID');
$addressID = $request->request->getInt('addressID');
$deliveryTime = $request->request->get('deliveryTime');
$order = $entityManager->find(FoodOrder::class, $orderID);
$order->setDeliveryTime($deliveryTime);
$order->setPaymentType($request->request->getInt('paymentType', 1));
$address = $entityManager->find(UserAddress::class, $addressID);
$order->setDeliveryAddress($address);
$orderInfo = IikoUtil::instance($order->getOffer())->checkOrder($entityManager, $order, $subscriptionService);
if (!$orderInfo) {
return new JsonResponse(['error' => true]);
}
$entityManager->flush();
return new JsonResponse($this->getCheckAddressResponse($orderInfo));
}
/** @Route("/delivery/reload/offer/{offerId}/type/{typePrice}", name="deliveryReloadDish") */
public function reloadDish(
Request $request,
ImageService $imageService,
ProductFastDeliveryService $productFastDeliveryService,
CustomProductOfferSorter $productSorter,
ContainerInterface $container,
FoodFilterCounterRepositoryInterface $foodFilterCounterRepository,
CustomProductOfferSorter $customProductOfferSorter,
OfferOrderPurchaseCountDaoInterface $offerOrderPurchaseCountDao,
OfferCacheService $offerCacheService,
FoodOfferExtensionRepositoryInterface $foodOfferExtensionRepository,
WeightParserHelper $weightParserHelper,
$offerId,
$typePrice
) {
$offerCached = $offerCacheService->getOffer($offerId, true, true);
$data['offer'] = $offerCached;
$orderUtil = AbstractDelivery::instance($offerCached);
$orderUtil->setContainer($container);
$data['filterAction'] = $foodFilterCounterRepository->findByOfferId((int) $offerCached->getID());
$isSushiVesla = $orderUtil instanceof SushiVesla;
$isDominos = $orderUtil instanceof Dominos;
$isSushiHouse = $orderUtil instanceof SushiHouse;
$isSushiChefArts = $orderUtil instanceof SushiChefArts;
$data['isDominos'] = $isDominos;
$data['showSortingIndexOrder'] = $isSushiVesla || $isDominos ? false : true;
$entityManager = $this->getDoctrine()->getManager();
$offerRepository = $entityManager->getRepository(Offer::class);
$allDishes = [];
if ($isSushiVesla) {
$allDishes = $foodOfferExtensionRepository->findActiveByOfferIdAndShippingType($offerId, $typePrice);
}
$shippingType = FoodOfferExtension::LABEL_SHIPPING_TYPE[$typePrice];
if ($isDominos) {
$dishes = $orderUtil->getDishesByShippingType($typePrice);
} else if ($isSushiVesla) {
$dishes = $orderUtil->getProductsDBByShippingType(
\array_filter($allDishes, static fn (OfferExtension $offerExtension): bool => !\is_subclass_of($offerExtension, FoodOfferExtension::class)),
);
} else {
$dishes = $orderUtil->getDishes();
}
/** @var FoodOfferExtension[] $extensions */
$extensions = $offerRepository->getExtensionsByShippingType($offerCached, $shippingType);
$dishPurchaseCount = $offerOrderPurchaseCountDao->getPurchaseCountsForPeriodByOffer((int) $offerId, PurchaseCountPeriod::LAST_MONTH);
$dishPurchaseDayCount = $offerOrderPurchaseCountDao->getPurchaseCountsForPeriodByOffer((int) $offerId, PurchaseCountPeriod::LAST_DAY);
$data['dishes'] = [];
$data['showPricePerKilogram'] = false;
foreach ($dishes as $dish) {
if (isset($extensions[$dish->id])) {
$dish->productsPerCode = $extensions[$dish->id]->getProductsPerCode();
$dish->offerPrice = $extensions[$dish->id]->getCurrentPrice(null, $typePrice);
$dish->sauceNeed = $extensions[$dish->id]->isSauceNeed();
$dish->rating = (float) $offerCached->getRating();
if (isset($dish->regularPrice) && $dish->regularPrice == 0) {
$dish->regularPrice = $extensions[$dish->id]->getPrice();
}
if (!$isDominos) {
$dishSizeFull = $dish->sizeFull;
$dish->sizeFull = '';
$dish->pricePerKilogram = null;
$dish->offerPrice = (float) PriceDeliveryType::calcDeliveryPickupPrice(
$extensions[$dish->id],
$typePrice,
$dish->regularPrice,
$dish->offerPrice,
);
if ($extensions[$dish->id]->getWeight()) {
$dish->sizeFull = $extensions[$dish->id]->getWeight() . ' г';
$dish->pricePerKilogram = $this->calcPricePerKilogram(
$dish->offerPrice,
(float) $extensions[$dish->id]->getWeight(),
);
$data['showPricePerKilogram'] = true;
}
if ($extensions[$dish->id]->getComponentsCount()) {
if ($dish->sizeFull != '') {
$dish->sizeFull .= ', ';
}
$dish->sizeFull .= $extensions[$dish->id]->getComponentsCount() . ' шт';
}
if ($dish->sizeFull === '' || $isSushiChefArts) {
$dish->sizeFull = $dishSizeFull;
}
if (null === $dish->pricePerKilogram && !empty($dish->sizeFull)) {
$dish->pricePerKilogram = $this->calcPricePerKilogram(
$dish->offerPrice,
(float) $weightParserHelper->parse($dish->sizeFull),
);
$data['showPricePerKilogram'] = true;
}
} else {
if ($dish->isPizza) {
$variants = $dishes[$dish->id]->variants;
$offerExtensionVariants = $offerRepository->getExtensionVariants($extensions[$dish->id]);
$changeOfferPrice = false;
foreach ($variants as $keySize => &$valueSize) {
foreach ($valueSize as $keyValueSize => &$valueValueSize) {
if (isset($offerExtensionVariants[$valueValueSize['code']])) {
$offerPriceValue = $valueValueSize['offerPrice']['value'];
$variantAdditionalDominos = null;
$recalculatedOfferPriceValue = PriceDeliveryType::calcDeliveryPickupPrice(
$extensions[$dish->id],
$typePrice,
$valueValueSize['regularPrice']['value'],
$offerPriceValue,
$variantAdditionalDominos
);
if (!$changeOfferPrice) {
$dish->offerPrice = (float)$recalculatedOfferPriceValue;
$dish->pricePerKilogram = $this->calcPricePerKilogram($dish->offerPrice, $valueValueSize['weight']['value']);
$changeOfferPrice = true;
} else {
$changeOfferPrice = true;
}
$valueValueSize['pricePerKilogram'] = $this->calcPricePerKilogram(
$dish->offerPrice,
$valueValueSize['weight']['value']
);
$data['showPricePerKilogram'] = true;
$valueValueSize['id'] = $offerExtensionVariants[$valueValueSize['code']]->getID();
$valueValueSize['offerPrice']['value'] = $recalculatedOfferPriceValue;
$valueValueSize['offerPrice']['formatted'] = str_replace($offerPriceValue, $recalculatedOfferPriceValue, $valueValueSize['offerPrice']['formatted']);
$valueValueSize['size']['text'] = Dominos::TEXT_SIZE_PIZZA[(int) $valueValueSize['size']['value']];
}
}
}
$dish->dataBySize = $variants;
} else {
$dish->offerPrice = (float)PriceDeliveryType::calcDeliveryPickupPrice(
$extensions[$dish->id],
$typePrice,
$dish->regularPrice,
$dish->offerPrice
);
$dishSizeFull = $dish->sizeFull;
$dish->sizeFull = '';
if ($extensions[$dish->id]->getWeight()) {
$dish->sizeFull = $extensions[$dish->id]->getWeight() . ' г';
$dish->pricePerKilogram = $this->calcPricePerKilogram((float)$dish->offerPrice, (float)$extensions[$dish->id]->getWeight());
$data['showPricePerKilogram'] = true;
} else {
$dish->pricePerKilogram = null;
}
if ($extensions[$dish->id]->getComponentsCount()) {
if ($dish->sizeFull != '') {
$dish->sizeFull .= ', ';
}
$dish->sizeFull .= $extensions[$dish->id]->getComponentsCount() . ' шт';
}
if ($dish->sizeFull == '') {
$dish->sizeFull = $dishSizeFull;
}
}
}
$dish->originId = $dish->id;
$dish->position = $extensions[$dish->id]->getPosition() ?: CustomProductOfferSorter::DEFAULT_POSITION;
$dish->id = $extensions[$dish->id]->getID();
$dish->description = str_replace("\n", '<br/>', $dish->description);
$dish->description = str_replace("\n", '<br/>', $dish->description);
$dish->imageURL = null;
if (isset($dish->images[count($dish->images) - 1])) {
if ($dish->images[count($dish->images) - 1] instanceof OfferExtensionMedia) {
$dish->imageURL = $imageService->getImageURLCached($dish->images[count($dish->images) - 1], 540, 0);
} else if ($dish->images[count($dish->images) - 1]) {
$dish->imageURL = $dish->images[count($dish->images) - 1]->imageUrl;
}
}
$key = array_search($dish->id, array_column($dishPurchaseCount, 'id'));
$dish->purchaseCount = isset($dishPurchaseCount[$key]['cnt']) && $key !== false ? $dishPurchaseCount[$key]['cnt'] : 0;
$keyDay = \array_search($dish->id, \array_column($dishPurchaseDayCount, 'id'), true);
$dish->purchaseDayCount = isset($dishPurchaseDayCount[$keyDay]['cnt']) && $keyDay !== false
? $dishPurchaseDayCount[$keyDay]['cnt']
: 0;
$deliveryTime = $productFastDeliveryService->findProductFastDelivery($offerCached, $dish->originId);
$dish->fastDeliveryTime = CustomProductOfferSorter::DEFAULT_POSITION;
if ($deliveryTime) {
$dish->fastDelivery = $deliveryTime;
$dish->fastDeliveryTime = (int) $deliveryTime['time'];
}
$data['dishes'][] = $dish;
}
}
$sortType = $request->query->get('sort', CustomProductOfferSorter::DEFAULT_CUSTOM_PRODUCT_SORT);
$data['dishes'] = $productSorter->sort($data['dishes'], $sortType);
$dishGroup = $orderUtil::DISH_BY_GROUP ? $orderUtil::DISH_GROUPS : [];
$foodDishExtensionId = $request->query->get('extension');
if (null !== $foodDishExtensionId) {
$dishKey = \array_search($foodDishExtensionId, \array_column($data['dishes'], 'id'));
$foodCourtExtensionDish = $data['dishes'][$dishKey];
unset($data['dishes'][$dishKey]);
\array_unshift($data['dishes'], $foodCourtExtensionDish);
if (0 < \count($dishGroup)) {
$category = $isSushiHouse ? $foodCourtExtensionDish->parentGroup : $foodCourtExtensionDish->groupName;
$keyDishGroup = \array_search($category, $dishGroup);
$group = $dishGroup[$keyDishGroup];
unset($dishGroup[$keyDishGroup]);
\array_unshift($dishGroup, $group);
}
}
$data['topDishIDList'] = [];
for ($i = 0; $i < 3; $i++) {
if (isset($dishPurchaseCount[$i]['id'])) {
$data['topDishIDList'][] = $dishPurchaseCount[$i]['id'];
}
}
if ($orderUtil::DISH_BY_GROUP) {
$dishByGroupLabel = [];
$dishByGroupContent = [];
if ($isSushiHouse || $isSushiChefArts) {
foreach ($data['dishes'] as $dish) {
$dishByGroupContent[$dish->groupName][] = $dish;
if (!\in_array($dish->parentGroup, $dishByGroupLabel)) {
$dishByGroupLabel[$dish->groupName] = $dish->parentGroup;
}
}
$dishByGroupContent = $this->customSortDishByGroup($dishByGroupContent, $dishGroup);
}
if ($isDominos) {
foreach ($data['dishes'] as $dish) {
$dish->parentGroup = $dish->groupName;
$dishByGroupContent[$dish->groupName][] = $dish;
if (!\in_array($dish->groupName, $dishByGroupLabel)) {
$dishByGroupLabel[$dish->groupName] = Dominos::LABEL_CATEGORIES[$dish->groupName];
}
}
$dishByGroupContent = $this->customSortDishByGroup($dishByGroupContent, $dishGroup);
}
$data['dishByGroup'] = [
'content' => $dishByGroupContent,
'label' => $dishByGroupLabel,
];
}
$options = $isSushiVesla
? $orderUtil->getOptionsDBByShippingType(
$imageService,
\array_filter($allDishes, static fn (OfferExtension $offerExtension): bool => $offerExtension instanceof FoodOfferOptionExtension)
)
: $this->getOptions($imageService, $offerCached, $orderUtil, 0, $isDominos ? $shippingType : null);
$data['options'] = $customProductOfferSorter->sort($options, CustomProductOfferSorter::DEFAULT_CUSTOM_PRODUCT_SORT);
$data['sortList'] = CustomProductOfferSorter::SORT_LIST;
$data['isAvailableOnFood'] = $offerCached->isAvailableOnFood();
if ($isDominos) {
$view = CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/delivery_teaser_reload_pickup.html.twig' : 'Slivki/delivery/delivery_teaser_reload_pickup.html.twig';
} else {
$view = CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/delivery/delivery_teaser_reload.html.twig' : 'Slivki/delivery/delivery_teaser_reload.html.twig';
}
return $this->render($view, $data);
}
private function calcPricePerKilogram(float $offerPrice, int $weight): ?float
{
if (!$weight) {
return null;
}
return \round(self::KILOGRAM * $offerPrice / $weight, 2);
}
/** @Route("/expresspizza-orders") */
public function expressPizzaOrdersAction(Request $request) {
$offerID = 282278;
$pass = '67380b434f';
$objectCode = '0017-4-009';
if ($pass != $request->query->get('pass')) {
return new Response('ERROR: Wrong password!');
}
$date = \DateTime::createFromFormat('U', $request->query->get('date'));
if (!$date) {
return new Response('ERROR: Wrong date format!');
}
$entityManager = $this->getDoctrine()->getManager();
/** @var Connection $connection */
$connection = $entityManager->getConnection();
$sql = "select"
. " offer_order.id as order_id,"
. " offer_order.paid_at as order_datetime,"
. " offer_order.delivery_time as delivery_datetime,"
. " user_address.name as client_name,"
. " user_address.phone as client_phone,"
. " user_address.pickup as pickup,"
. " street.name as street_name,"
. " user_address.house as house,"
. " user_address.block as block,"
. " user_address.entrance as entrance,"
. " user_address.floor as floor,"
. " user_address.doorphone as doorphone,"
. " user_address.appartment as appartment,"
. " offer_extension.partner_item_id as product_code,"
. " offer_extension.name as product_name,"
. " offer_order_details.items_count as items_count,"
. " offer_extension.dish_delivery_price as delivery_price,"
. " offer_extension.pickup_price as pickup_price,"
. " offer_order.parameter_int_0 as payment_type,"
. " offer_order.comment as comment,"
. " coalesce(geo_location.pickup_point_partner_id, '$objectCode') as object_code"
. " from offer_order_details"
. " inner join offer_order on offer_order.id = offer_order_details.offer_order_id"
. " inner join user_address on offer_order.delivery_address_id = user_address.id"
. " left join street on user_address.street_id = street.id"
. " left join geo_location on user_address.geo_location_id = geo_location.id"
. " inner join offer_extension on offer_extension.id = offer_order_details.offer_extension_id"
. " where offer_order.offer_id = $offerID and offer_order.status > 0 and"
. " offer_order.paid_at >= '" . $date->format('Y-m-d H:i') . "'"
. " order by offer_order.id";
$orderDetails = $connection->executeQuery($sql)->fetchAll(\PDO::FETCH_ASSOC);
$result = [];
foreach ($orderDetails as $orderDetail) {
$orderDateTime = new \DateTime($orderDetail['order_datetime']);
$deliveryDateTime = new \DateTime();
if ($orderDetail['delivery_datetime'] != 'Ближайшее') {
$deliveryDateTime = new \DateTime($orderDetail['delivery_datetime']);
}
$comment = '';
if (trim($orderDetail['entrance'])) {
$comment .= 'П' . trim($orderDetail['entrance']) . ' ';
}
if (trim($orderDetail['floor'])) {
$comment .= 'Э' . trim($orderDetail['floor']) . ' ';
}
if (trim($orderDetail['doorphone'])) {
$comment .= 'Д' . trim($orderDetail['doorphone']) . ' ';
}
$paymentType = '';
switch ($orderDetail['payment_type']) {
case 1:
$paymentType = 'Оплата: онлайн, ';
break;
case 2:
$paymentType = 'Оплата: наличные, ';
break;
case 3:
$paymentType = 'Оплата: терминал, ';
}
$comment .= $paymentType;
$comment .= trim($orderDetail['comment']);
$result[] = join(chr(9), [
$orderDetail['object_code'], // Код объекта
$orderDetail['order_id'], // Номер заказа
$orderDateTime->format('d.m.Y'), // Дата заказа
$orderDateTime->format('H:i'), // Время заказа
$deliveryDateTime->format('H:i'), // Изготовить к какому времени
$orderDetail['client_name'], // Имя клиента – Контакт
str_replace('+375', '+375 ', $orderDetail['client_phone']), // Контактный телефон.
$orderDetail['pickup'] ? 0 : 1, // Тип получения: на месте (0) или доставка (1).
trim($orderDetail['street_name']) ?: ' ', // Улица доставки
trim($orderDetail['house']) ?: ' ', // Номер дома
trim($orderDetail['block']) ?: ' ', // Корпус
trim($orderDetail['appartment']) ?: ' ', // Квартира
' ', // Код группы
$orderDetail['product_code'], // Код товара
' ', // IDNT Номер выгрузки (оставляйте пустым)
$orderDetail['product_name'], // Название товара
$orderDetail['items_count'], // Количество
$orderDetail['pickup'] ? $orderDetail['pickup_price'] : $orderDetail['delivery_price'], // Цена
str_replace(["\r\n", "\n"],' ', $comment), // Примечание
]);
}
$result[] = chr(9) . 'OK';
return new Response(join("\r\n", $result));
}
private function customSortDishByGroup(array $dishByGroupContent, array $sort): array
{
uasort($dishByGroupContent, function ($dishGroup1, $dishGroup2) use ($sort) {
if (!count($dishGroup1)) {
return 1;
}
if (!count($dishGroup2)) {
return -1;
}
$dishGroup1Key = array_search($dishGroup1[0]->parentGroup, $sort);
$dishGroup2Key = array_search($dishGroup2[0]->parentGroup, $sort);
return $dishGroup1Key < $dishGroup2Key ? -1 : 1;
});
return $dishByGroupContent;
}
}