<?php
namespace AutomarketBundle\Services;
use CoreBundle\Entity\Brand;
use CoreBundle\Entity\Dealer;
use CoreBundle\Entity\Featured;
use CoreBundle\Entity\Model;
use CoreBundle\Entity\Vehicles\RecommendGroup;
use CoreBundle\Entity\Vehicles\VariationCharacteristic;
use CoreBundle\Entity\Vehicles\Vehicle;
use CoreBundle\Entity\Vehicles\VehicleItem;
use CoreBundle\Model\Vehicles\VehicleType;
use CoreBundle\Services\ImageProviderVidi;
use CoreBundle\Services\MediaExtensionVidi;
use CoreBundle\Factory\Vehicle as VehicleFactory;
use DateTime;
use DcSiteBundle\Model\CreditModel;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\Expr\Join;
use Exception;
use PortalBundle\Model\Catalog;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class CatalogService
{
private RouterInterface $router;
private MediaExtensionVidi $media;
private TranslatorInterface $translator;
private EntityManagerInterface $em;
private RequestStack $requestStack;
private VehicleFactory $coreFactoryVehicle;
private CreditModel $creditModel;
public function __construct( MediaExtensionVidi $media, RouterInterface $router, TranslatorInterface $translator,
EntityManagerInterface $em, RequestStack $requestStack, VehicleFactory $coreFactoryVehicle,
CreditModel $creditModel)
{
$this->media = $media;
$this->router = $router;
$this->translator = $translator;
$this->em = $em;
$this->requestStack = $requestStack;
$this->coreFactoryVehicle = $coreFactoryVehicle;
$this->creditModel = $creditModel;
}
/**
* Фільтр
*
* @return array
*/
public function initSearch ()
{
$request = $this->requestStack->getCurrentRequest();
}
public function getVehicleType()
{
$request = $this->requestStack->getCurrentRequest();
$vehicleTypeData = VehicleType::getTypeDataByUrl($request->get('type') ?? 'car');
return $vehicleTypeData;
}
/**
* Отримати параметри для фільтра на головній
*
* @return array
*/
public function getOnShowFilter()
{
$request = $this->requestStack->getCurrentRequest();
$router = $this->router;
/** @var Dealer $dealer */
$dealer = $this->em->getRepository(Dealer::class)->find(6);
$brandId = $request->get('brandId');
$modelId = $request->get('modelId');
$minYear = $request->get('minYear');
$maxYear = $request->get('maxYear');
$minPrice = $request->get('minPrice');
$maxPrice = $request->get('maxPrice');
$paramRoute = [];
$responseData = [
'brands' => [],
'models' => [],
'years' => [],
'maxPrice' => null,
'countVehicle' => 0,
];
$queryBuilder = $this->em->getRepository(\CoreBundle\Entity\Vehicles\VehicleItem::class)
->createQueryBuilder('vi')
->addSelect('vi')
->addSelect('CASE WHEN ( d.id in (32,33)) THEN (CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE (CASE WHEN vi.alt_rate > 0 THEN vi.alt_rate * vi.price ELSE vi.price * d.rate END) END) ELSE ( CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE vi.price END) END AS price')
->addSelect('vi.year AS year')
->join('vi.vehicle','ve')
->join('ve.model', 'm')
->join('m.brand','b')
->join('ve.dealer', 'd')
->where('ve.vehicle_type = :type')->setParameter('type', 1)
// TODO Навіщо ми перевіряємо vehicleItem state на вживаних авто? У вживаного авто є всього 1 vehicleItem, і ми маємо відображати авто по vehicle state. Якщо все буде ок, повидаляти з усіх запитів
// ->andWhere('vi.state = 1')
->andWhere('vi.sold = :sold')->setParameter('sold', false)
->andWhere('ve.state = 1')
->andWhere('ve.is_not_filled = 0')
->andWhere('ve.is_delete != 1')
->andWhere('ve.is_used = :isUsed')->setParameter('isUsed', true);
if ($brandId) {
$queryBuilder->andWhere('b.id = :brandId')->setParameter('brandId', $brandId);
}
if ($modelId) {
$queryBuilder->andWhere('m.id = :modelId')->setParameter('modelId', $modelId);
}
if ($minPrice) {
$queryBuilder->andHaving('price >= :minPrice')->setParameter('minPrice', $minPrice * $dealer->getRate());
$paramRoute['minPrice'] = $minPrice * $dealer->getRate();
}
if ($maxPrice) {
$queryBuilder->andHaving('price <= :maxPrice')->setParameter('maxPrice', $maxPrice * $dealer->getRate());
$paramRoute['maxPrice'] = $maxPrice * $dealer->getRate();
}
if ($minYear) {
$queryBuilder->andHaving('vi.year >= :minYear')->setParameter('minYear', $minYear);
$paramRoute['minYear'] = $minYear;
}
if ($maxYear) {
$queryBuilder->andHaving('vi.year <= :maxYear')->setParameter('maxYear', $maxYear);
$paramRoute['maxYear'] = $maxYear;
}
$result = $queryBuilder->getQuery()->getResult();
// /** @var VehicleItem $item */
// foreach ($result as $item){
// dump($item[0]->getVehicle()->getDealer());
// dump($item[]->getPrice());
// dump('----------');
// }
//
// dump($result);exit;
if($result) {
$responseData['years'] = range(min(array_column($result, 'year')), max(array_column($result, 'year'))) ;
$responseData['countVehicle'] = count($result);
foreach ($result as $item) {
/** @var Vehicle $vehicle */
$vehicle = $item[0]->getVehicle();
$vBrand = $vehicle->getModel()->getBrand();
$vModel = $vehicle->getModel();
if (!isset($responseData['brands'][$vBrand->getId()])) {
$responseData['brands'][$vBrand->getId()] = [
'id' => $vBrand->getId(),
'title' => $vBrand->getName(),
'url' => $vBrand->getUrl()
];
}
if (!isset($responseData['models'][$vModel->getId()])) {
$responseData['models'][$vModel->getId()] = [
'id' => $vModel->getId(),
'brandId' => $vBrand->getId(),
'title' => $vModel->getTitle(),
'url' => $vModel->getUrl()
];
}
}
$maxPrice = max(array_column($result, 'price'));
if($maxPrice > 10) {
$price = intval(ceil($maxPrice));
$shorNum = intval('1' . str_repeat('0', floor(log10($price))));
$remainder = $price % $shorNum;
$responseData['maxPrice'] = $price + ($shorNum - $remainder);
}
}
if($brandId && isset($responseData['brands'][$brandId]['url'])) {
$brandUrl = $responseData['brands'][$brandId]['url'];
$paramRoute['brand'][$brandUrl] = 'true';
}
if($modelId && isset($responseData['models'][$modelId]['url'])) {
$modelUrl = $responseData['models'][$modelId]['url'];
$paramRoute['model'][$modelUrl] = 'true';
}
if($result && $responseData['countVehicle'] > 0 && !empty($paramRoute)) {
$responseData['link'] = $router->generate('automarket_catalog_search', $paramRoute);
}else{
$responseData['link'] = $router->generate('automarket_catalog', ['state' => 'used', 'type' => 'car']);
}
return $responseData;
}
public function getBrands($vehicleType)
{
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\Vehicle::class)
->createQueryBuilder('v')
->select('b.id', 'b.name', 'b.url')
->join('v.model', 'm')
->join('m.brand', 'b')
->andWhere('v.state = :state')->setParameter('state', true)
->andWhere('v.is_delete = :isDelete')->setParameter('isDelete', false)
->andWhere('v.is_used = :isUsed')->setParameter('isUsed', true)
->andWhere('v.vehicle_type = :type')->setParameter('type', $vehicleType);
$query->orderBy('b.name');
$query->groupBy('b.id');
return $query->getQuery()->getResult();
}
public function getModels($vehicleType, Brand $brand = null)
{
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\Vehicle::class)
->createQueryBuilder('v')
->select('m.id', 'm.title', 'm.url')
->innerJoin('v.model', 'm')
->innerJoin('m.brand', 'b')
->andWhere('v.state = :state')->setParameter('state', true)
->andWhere('v.is_delete = :isDelete')->setParameter('isDelete', false)
->andWhere('v.is_used = :isUsed')->setParameter('isUsed', true)
->andWhere('v.vehicle_type = :type')->setParameter('type', $vehicleType);
if ($brand) {
$query->andWhere('b.id = :brand')->setParameter('brand', $brand);
}
$query->orderBy('m.title');
$query->groupBy('m.id');
return $query->getQuery()->getResult();
}
public function getRecommendGroupByParams($vehicleType)
{
$request = $this->requestStack->getCurrentRequest();
$locale = $request->getLocale();
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\RecommendGroup::class)
->createQueryBuilder('rg')
->select('rg')
->andWhere('rg.state = :rgState')
->setParameter('rgState', true)
->andWhere('rg.state_slider = :rgStateSlider')
->setParameter('rgStateSlider', true);
$recommendGroup = $query->getQuery()->getResult();
$result = [];
/** @var RecommendGroup $item */
foreach ($recommendGroup as $item) {
$result[$item->getUrl()] = $item->getTitle($locale);
}
return $result;
}
public function getCharacteristicsByParams($vehicleType, $brand = null, $model = null, $vehicleIds = [])
{
$request = $this->requestStack->getCurrentRequest();
$locale = $request->getLocale();
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\VariationCharacteristic::class)
->createQueryBuilder('vc');
if ($locale == 'ru') {
$query->select('cv.id', 'c.url AS cUrl', 'cv.url', 'cv.value_ru AS value');
} else {
$query->select('cv.id', 'c.url AS cUrl', 'cv.url', 'cv.value_ua AS value');
}
$query->join('vc.characteristic_value', 'cv')
->join('vc.characteristic', 'c', Join::WITH, 'c.vehicle_type = :type')->setParameter('type', $vehicleType)
->join('vc.variation', 'v', Join::WITH, 'v.state = 1')
->join('v.vehicle', 've', Join::WITH, 've.state = 1 AND ve.is_delete <> 1 AND ve.is_used = :is_used')->setParameter('is_used', true)
->join('ve.model', 'm')
->join('m.brand', 'b');
if ($brand) {
$query->andWhere('b.url = :bUrl')->setParameter('bUrl', $brand->getUrl());
}
if ($model) {
$query->andWhere('m.url = :mUrl')->setParameter('mUrl', $model->getUrl());
}
if (!empty($vehicleIds)) {
$query->andWhere('ve.id IN (:vehicleIds)')
->setParameter('vehicleIds', $vehicleIds);
}
$query->groupBy('cv', 'c');
$characteristics = $query->getQuery()->getResult();
$result = [];
foreach ($characteristics as $row) {
$result[$row['cUrl']][$row['url']] = $row['value'];
}
return $result;
}
public function getVehicleByCatalog(Dealer $dealer, $findVehicles, $user, $lang): array
{
$rows = array_column($findVehicles, 0);
return $this->getVehicleCatalogItem($dealer, $rows, $user, $lang);
}
public function getVehicleCatalogItem(Dealer $dealer, $vehicleItems, $user, $lang): array
{
$request = $this->requestStack->getCurrentRequest();
$features = $this->em->getRepository(\CoreBundle\Entity\Featured::class)->findBy(['type' => 'vehicle', 'user' => $user]);
$featuresIds = [];
/** @var Featured $feature */
foreach ($features as $feature) {
$favData = json_decode($feature->getData());
if(!isset($favData->vehicleItemId)){
continue;
}
$featuresIds[$favData->vehicleItemId] = $feature->getId();
}
$compareCookie = $request->cookies->get('compare');
$vehicleComparison = explode(',', $compareCookie);
return array_reduce($vehicleItems, function($rows, $row) use ($dealer, $featuresIds, $vehicleComparison, $lang, $request) {
try {
$row = $this->coreFactoryVehicle->createByVehicleItem($row);
if (empty($row)) {
return $rows;
}
$dollar = $dealer->getRate();
$price = $row->price();
$priceAlt = $row->getPriceAlt();
$priceDollar = 0;
$sale = 0;
if ($priceAlt > 0 && $priceAlt < $row->getPrice()) {
$priceAlt = $row->getPrice();
$sale = ($row->getPriceAlt() / $row->getPrice()) * 100;
}
if ($dollar > 0) {
$priceDollar = ceil($price / $dollar);
}
$vehicleTypeData = VehicleType::getTypeDataById($row->getVehicleType());
$vehicleUrl = $this->router->generate('automarket_vehicle', ['state' => 'used', 'type' => $vehicleTypeData['url'], 'brand' => $row->getBrand()->getUrl(), 'model' => $row->getModel()->getUrl(),'id' => $row->getVehicleId()]);
$engineVolume = (int)$row->getEngineVolume($request->getLocale());
$engineVolumeFormat = $engineVolume > 10 ? number_format( $engineVolume/1000, 1, '.', '') : number_format( $engineVolume, 1, '.', '');
$rows[] = [
'id' => $row->getVehicleId(),
'itemId' => $row->getVehicleItemId(),
'title' => $row->getModelName(),
'fullName' => $row->getFullName(),
'year' => $row->getYear(),
'price' => intval($price),
'price_alt' => intval($priceAlt),
'price_dollar' => intval($priceDollar),
'deposit' => $row->getDeposit(),
'sold' => $row->getSold(),
'sale' => ($sale)? 100 - intval($sale) : null,
'engine_volume' => $engineVolumeFormat,
'mileage' => $row->getMileage(),
'mileageThousand' => floor($row->getMileage() / 1000),
'url' => $vehicleUrl,
'bodyType' => $row->getBodyTypeName($lang),
'engine_type' => $row->getFuelTypeName($lang),
'transmission' => $row->getTransmissionTypeName($lang),
'creditPayment' => $this->creditModel->getMinPayment($row),
'featuredId' => $featuresIds[$row->getVehicleItemId()] ?? null,
'featuredLink' => $request->getSchemeAndHttpHost().$vehicleUrl,
'comparedId' => in_array($row->getVehicleItemId(),$vehicleComparison)? $row->getVehicleItemId() : null,
'media' => [
'image' => $this->media->getPath($row->getPreview(), 'reference')
],
'riaPublicationDate' => $row->getRiaPublicationDate(),
'isElectric' => $row->isElectric(),
'batteryCapacity' => $row->getBatteryCapacity($lang),
];
return $rows;
} catch (Exception $e) {
return $rows;
}
}, []);
}
private function roundMaxData($num){
if($num > 10) {
$shorNum = intval('1' . str_repeat('0', floor(log10($num))));
$remainder = $num % $shorNum;
$num += $shorNum - $remainder;
}
return $num;
}
public function buildFilter($typeFilter = null){
$request = $this->requestStack->getCurrentRequest();
$locale = $request->getLocale();
$vehicleTypeData = $this->getVehicleType();
$brand = isset($routeParams['brand']) ? $this->em->getRepository(\CoreBundle\Entity\Brand::class)->findOneBy(['url' => $routeParams['brand']]) : null;
$model = isset($routeParams['model']) && $brand ? $this->em->getRepository(\CoreBundle\Entity\Model::class)->findOneBy(['url' => $routeParams['model'], 'brand' => $brand]) : null;
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\VariationCharacteristic::class)
->createQueryBuilder('vc')
->join('vc.characteristic', 'c', Join::WITH, 'c.vehicle_type = :type')->setParameter('type', $vehicleTypeData['id'])
->join('vc.characteristic_value','cv')
->join('vc.variation', 'v', Join::WITH, 'v.state = 1')
->join('v.vehicle', 've', Join::WITH, 've.state = 1 AND ve.is_delete <> 1 AND ve.is_used = :is_used')->setParameter('is_used', 1)
->join('v.vehicle_items','vi', Join::WITH, 'vi.state = 1')
->andWhere('ve.is_not_filled = 0')
->andWhere('ve.is_delete != 1');
if($typeFilter){
$query->andWhere('c.model_unique IN (:modelUniques)')->setParameter('modelUniques', $typeFilter);
}
if ($model) {
$query->join('ve.model', 'm')
->andWhere('m.id = :model')
->setParameter('model', $model->getId());
}
if ($brand && !$model) {
$query->join('ve.model', 'm')
->join('m.brand', 'b')
->andWhere('b.id = :brand')
->setParameter('brand', $brand->getId());
}
if ($locale == 'ru') {
$query->orderBy('cv.position')->addOrderBy('cv.value_ru');
}else{
$query->orderBy('cv.position')->addOrderBy('cv.value_ua');
}
$vCharacteristics = $query->getQuery()->getResult();
$query->addSelect('vi.price')
->addSelect('vi.mileage')
->addSelect('vi.year');
$maxVehicleResult = $query->getQuery()->getResult();
$filters['limitationData'] = [
'minPrice' => 0,
'maxPrice' => $this->roundMaxData(max(array_column($maxVehicleResult, 'price'))),
'minYear' => 0,
'maxYear' => max(array_column($maxVehicleResult, 'year')),
'minMileage' => 0,
'maxMileage' => $this->roundMaxData(max(array_column($maxVehicleResult, 'mileage'))),
];
/** @var VariationCharacteristic $vCharacteristic */
foreach ($vCharacteristics as $vCharacteristic){
$characteristic = $vCharacteristic->getCharacteristic();
$characteristicValue = $vCharacteristic->getCharacteristicValue();
if(!$characteristic->getUrl() || $characteristic->getUrl() == ''){
continue;
}
// Тільки автомат та механіка у типі КПП
if($characteristic->getUrl() == "kpp" &&
($characteristicValue->getUrl() != "avtomat" && $characteristicValue->getUrl() != "mehanika")){
continue;
}
if (!isset($filters['characteristic'][$characteristic->getUrl()])) {
$filters['characteristic'][$characteristic->getUrl()] = [
'id' => $characteristic->getId(),
'title' => $characteristic->getTitle($locale),
'url' => $characteristic->getUrl(),
'values' => [],
];
}
if(isset($filters['characteristic'][$characteristic->getUrl()]['values'][$characteristicValue->getId()])){
continue;
}
if ($characteristic->getUrl()) {
$filters['characteristic'][$characteristic->getUrl()]['values'][$characteristicValue->getId()] = [
'id' => $characteristicValue->getId(),
'title' => $characteristicValue->getValue($locale),
'url' => $characteristicValue->getUrl(),
];
} else {
$filters['characteristic'][$characteristic->getUrl()]['values'] = null;
}
}
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\RecommendGroup::class)
->createQueryBuilder('rg')
->select('rg')
->join('rg.vehicles', 've')
->where('ve.vehicle_type = :type')
->andWhere('ve.state = 1')
->andWhere('ve.is_delete != 1')
->setParameter('type', $vehicleTypeData['id'])
->andWhere('rg.state = :rgState')
->setParameter('rgState', true)
->andWhere('rg.state_slider = :rgStateSlider')
->setParameter('rgStateSlider', true)
->andWhere('ve.is_used = :is_used')->setParameter('is_used', 1);
$recommendGroup = $query->getQuery()->getResult();
$filters['recommendGroup'] = [
'url' => 'recommendGroup',
'values' => [],
];
/** @var RecommendGroup $item */
foreach ($recommendGroup as $item) {
$filters['recommendGroup']['values'][$item->getId()] = [
'id' => $item->getId(),
'title' => $item->getTitle($locale),
'url' => $item->getUrl(),
];
}
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\Vehicle::class)
->createQueryBuilder('v')
->select('b.id as bid', 'b.url as burl', 'b.name', 'm.id', 'm.url', 'm.title')
->join('v.model', 'm')
->join('m.brand', 'b')
->leftJoin('b.logo', 'logo')
->where('v.vehicle_type = :type')
->andWhere('v.state = 1')
->andWhere('v.is_delete != 1')
->setParameter('type', $vehicleTypeData['id'])
->andWhere('v.is_used = :is_used')->setParameter('is_used', 1);
$brands = $query->getQuery()->getResult();
foreach ($brands as $line) {
if (!isset($filters['brand'][$line['burl']])) {
$filters['brand'][$line['burl']] = [
'id' => $line['bid'],
'title' => $line['name'],
'url' => $line['burl'],
'count' => 1,
'models' => [],
];
}
$filters['brand'][$line['burl']]['models'][$line['id']] = [
'id' => $line['id'],
'url' => $line['url'],
'title' => $line['title'],
];
}
usort($filters['brand'], function ($a, $b) {
if ($a['title'] == $b['title']) {
return 1;
}
return $a['title'] > $b['title'] ? 1 : -1;
});
return $filters;
}
public function getFilterHeader(){
$request = $this->requestStack->getCurrentRequest();
$requestParams = $request->query->all();
$vehicleTypeData = $this->getVehicleType();
$catalogCharacteristic = $this->getCharacteristicsByParams($vehicleTypeData['id']);
$catalogRecommendGroup = $this->getRecommendGroupByParams($vehicleTypeData['id']);
$filters = [];
foreach ($requestParams as $type => $params) {
if (!is_array($params)) {
$from = $this->translator->trans('new_catalog.from', [], 'portal_base') . ' ' . $params;
$to = ' '.$this->translator->trans('new_catalog.to', [], 'portal_base') . ' ' . $params;
$year = $this->translator->trans('new_catalog.year', [], 'portal_base') . ' ';
$price = $this->translator->trans('new_catalog.price', [], 'portal_base') . ' ';
$mileage = $this->translator->trans('cars.used.mileage', [], 'portal_base') . ' ';
switch ($type) {
case $type == 'minYear' && $params > 0:
$filters['range']['year'] = $year . $from;
break;
case $type == 'maxYear' && $params > 0:
$filters['range']['year'] =
isset($filters['range']['year']) ? $filters['range']['year'] . $to : $year . $to;
break;
case $type == 'minPrice' && $params > 0:
$filters['range']['price'] = $price . $from. ' грн';
break;
case $type == 'maxPrice' && $params > 0:
$filters['range']['price'] =
isset($filters['range']['price']) ? $filters['range']['price'] . $to. ' грн' : $price . $to . ' грн';
break;
case $type == 'minMileage' && $params > 0:
$filters['range']['mileage'] = $mileage . $from. ' тис.';
break;
case $type == 'maxMileage' && $params > 0:
$filters['range']['mileage'] =
isset($filters['range']['mileage']) ? $filters['range']['mileage'] . $to. ' тис.' : $mileage . $to . ' тис.';
break;
}
continue;
}
if(empty($params)){
continue;
}
if($type == 'recommendGroup'){
$filters[$type] = array_intersect_key($catalogRecommendGroup, $params);
continue;
}
if($type == 'characteristic'){
foreach ($params as $paramType => $param){
$result = array_intersect_key($catalogCharacteristic, $params);
if(count($result)) {
$filters['characteristic'][$paramType] = array_intersect_key($catalogCharacteristic[$paramType], $param);
}
}
continue;
}
$filters[$type] = $params;
}
return $filters;
}
public function getRouteFilterParams(Dealer $dealer)
{
$request = $this->requestStack->getCurrentRequest();
$routeParams = $request->attributes->get('_route_params');
$params = [];
$typeParams = ['state', 'type', 'brand', 'model', 'param', 'price', 'recommendGroup'];
foreach ($typeParams as $type){
switch ($type) {
case 'price':
if(isset($routeParams['price'])) {
$params['maxPrice'] = floor($routeParams[$type] * $dealer->getRate());
}
break;
case 'param':
foreach ($routeParams as $key => $value) {
if (preg_match('/^param(\d*)$/', $key, $matches)) {
$index = $matches[1];
$valueKey = $index ? 'value' . $index : 'value';
if (isset($routeParams[$valueKey])) {
$params['characteristic'][$value][$routeParams[$valueKey]] = true;
}
}
}
// if(isset($routeParams['param']) && isset($routeParams['value'])) {
// $params['characteristic'][$routeParams['param']][$routeParams['value']] = true;
// }
break;
case 'model':
case 'brand':
case 'recommendGroup':
if(isset($routeParams[$type])) {
$params[$type][$routeParams[$type]] = true;
}
break;
default:
if(isset($routeParams[$type])){
$params[$type] = $routeParams[$type];
}
break;
}
}
return $params;
}
public function showMoreCatalog($countVehicle, $countVehicleByPage)
{
$request = $this->requestStack->getCurrentRequest();
$currentPage = $request->query->get('page') ?: 1;
return (($countVehicle - $countVehicleByPage*$currentPage) > 0);
}
public function buildSearchUrl()
{
$request = $this->requestStack->getCurrentRequest();
$searchParams = $request->query->all();
$searchParams = array_filter($searchParams, fn($value) => $value !== "");
return $this->router->generate('automarket_catalog_search', $searchParams);
}
public function findModelByParams($urlBrands = null, $urlModels = null)
{
$filterBrands = $this->em->getRepository(\CoreBundle\Entity\Brand::class)->getBrandsByUrl($urlBrands);
$filterModelIds = [];
/** @var Brand $brand */
foreach ($filterBrands as $brand) {
$models = [];
$modelSearch = [];
/** @var Model $model */
foreach ($brand->getModels() as $model) {
if (!$model->getUrl()) {
continue;
}
if (in_array($model->getUrl(), $urlModels)) {
$modelSearch[] = $model->getId();
}
$models[] = $model->getId();
}
$filterModelIds = (empty($modelSearch)) ? array_merge($filterModelIds, $models) : array_merge($filterModelIds, $modelSearch);
}
return $filterModelIds;
}
public function findVehicleByParams($pageLimit = null)
{
$request = $this->requestStack->getCurrentRequest();
$routeParams = $request->attributes->get('_route_params');
$routeSearch = ($request->attributes->get('_route') == 'automarket_catalog_search');
$searchParams = $request->query->all();
$brand = $routeParams['brand'] ?? null;
$model = $routeParams['model'] ?? null;
$price = $routeParams['price'] ?? null;
$year = $routeParams['year'] ?? null;
$param = $routeParams['param'] ?? null;
$param_value = $routeParams['value'] ?? null;
$param2 = $routeParams['param2'] ?? null;
$param_value2 = $routeParams['value2'] ?? null;
$recommendGroup = $routeParams['recommendGroup'] ?? null;
$vehicleTypeData = $this->getVehicleType();
$mounthAgo = (new DateTime())->modify('-30 days')->format('Y-m-d H:i:s');;
$query = $this->em->getRepository(\CoreBundle\Entity\Vehicles\VehicleItem::class)
->createQueryBuilder('vi')
->addSelect('vi')
->addSelect('CASE WHEN ( d.id in (32,33)) THEN (CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE (CASE WHEN vi.alt_rate > 0 THEN vi.alt_rate * vi.price ELSE vi.price * d.rate END) END) ELSE ( CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE vi.price END) END AS price')
->addSelect('CASE WHEN ( d.id in (32,33)) THEN (CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE (CASE WHEN vi.alt_rate > 0 THEN vi.price ELSE vi.price END) END) ELSE ( CASE WHEN vi.alt_price > 0 THEN vi.alt_price / d.rate ELSE vi.price / d.rate END)END AS priceUsd')
->addSelect('CASE WHEN (CASE WHEN ( d.id in (32,33)) THEN ( CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE ( CASE WHEN vi.alt_rate > 0 THEN vi.alt_rate * vi.price ELSE vi.price * d.rate END) END) ELSE (CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE vi.price END) END) = 0 THEN 9999999999 ELSE (CASE WHEN ( d.id in (32,33)) THEN (CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE ( CASE WHEN vi.alt_rate > 0 THEN vi.alt_rate * vi.price ELSE vi.price * d.rate END ) END ) ELSE ( CASE WHEN vi.alt_price > 0 THEN vi.alt_price ELSE vi.price END) END) END AS orderPrice')
->join('vi.variation', 'v')
->join('v.vehicle', 've')
->join('v.characteristics', 'vch')
->join('vch.characteristic', 'ch')
->join('vch.characteristic_value', 'chv')
->join('ve.dealer', 'd')
->join('ve.model', 'm')
->join('m.brand', 'b')
->leftJoin('ve.recommend_group', 'rg')
->where('ve.vehicle_type = :type')
// TODO Навіщо ми перевіряємо vehicleItem state на вживаних авто? У вживаного авто є всього 1 vehicleItem, і ми маємо відображати авто по vehicle state. Якщо все буде ок, повидаляти з усіх запитів
// ->andWhere('vi.state = 1')
->andWhere('ve.state = 1')
->andWhere('ve.is_not_filled = 0')
->andWhere('ve.is_delete != 1')
->setParameter('type', $vehicleTypeData['id'])
->andWhere('ve.is_used = :isUsed')->setParameter('isUsed', true)
->andWhere('vi.date_of_sale > :mounthAgo OR vi.date_of_sale IS NULL')
->orderBy('vi.sold', 'ASC')
->addOrderBy('vi.deposit', 'ASC')
->setParameter('mounthAgo', $mounthAgo);
if(!$routeSearch) {
if ($brand) {
$query->andWhere('b.url = :brand')->setParameter('brand', $brand);
}
if ($brand && $model) {
$query->andWhere('m.url = :model')->setParameter('model', $model);
}
if (isset($routeParams['param']) && $routeParams['param'] && isset($routeParams['value']) && $routeParams['value']) {
$query->andWhere('ch.url = :param AND chv.url = :paramValue')
->setParameter('param', $routeParams['param'])
->setParameter('paramValue', $routeParams['value']);
}
if (isset($routeParams['param2']) && isset($routeParams['value2'])) {
$cvIds = [];
$cType = $this->em->getRepository(\CoreBundle\Entity\Vehicles\Characteristic::class)->findOneBy(['url' => $routeParams['param2']]);
$alias = 'vc' . $cType->getId();
$fKey = 'charId' . $cType->getId();
$tKey = 'cids' . $cType->getId();
$query->join('v.characteristics', $alias);
$cValue = $this->em->getRepository(\CoreBundle\Entity\Vehicles\CharacteristicValue::class)->findOneBy(['url' => $routeParams['value2'], 'characteristic' => $cType]);
if ($cValue) {
$cvIds[] = $cValue->getId();
}
if (!empty($cvIds)) {
$query->andWhere($alias . '.characteristic = :' . $fKey)->setParameter($fKey, $cType->getId());
$query->andWhere($alias . '.characteristic_value IN (:' . $tKey . ')')->setParameter($tKey, $cvIds);
}
}
if ($price) {
$query->andHaving('priceUsd <= :price')->setParameter('price', $price);
}
if ($year) {
$query->andHaving('vi.year <= :year')->setParameter('yearMax', $year);
}
if ($recommendGroup) {
$query->andWhere('rg.url = :recommendGroup')->setParameter('recommendGroup', $recommendGroup);
}
}
if (count($searchParams)) {
foreach ($searchParams as $key => $item) {
switch ($key) {
case 'brand':
if (!isset($searchParams['model'])) {
$query->andWhere('b.url IN (:brand)')->setParameter('brand', array_keys($item));
} else {
$filterModelIds = $this->findModelByParams(array_keys($item), array_keys($searchParams['model']));
$query->andWhere('m.id IN (:modelIds)')->setParameter('modelIds', $filterModelIds);
}
break;
case 'model':
if (!isset($searchParams['brand']) || count($searchParams['brand']) == 1) {
$query->andWhere('m.url IN (:model)')->setParameter('model', array_keys($item));
}
break;
case 'recommendGroup':
$query->andWhere('rg.url IN (:recommendGroup)')->setParameter('recommendGroup', array_keys($item));
break;
case 'minPrice':
if ($item > 0) {
$query->andHaving('price >= :minPrice')->setParameter('minPrice', $item);
}
break;
case 'maxPrice':
if ($item > 0) {
$query->andHaving('price <= :maxPrice')->setParameter('maxPrice', $item);
}
break;
case 'minYear':
if ($item > 0) {
$query->andHaving('vi.year >= :minYear')->setParameter('minYear', $item);
}
break;
case 'maxYear':
if ($item > 0) {
$query->andHaving('vi.year <= :maxYear')->setParameter('maxYear', $item);
}
break;
case 'minMileage':
if ($item > 0) {
$query->andHaving('vi.mileage >= :minMileage')->setParameter('minMileage', $item * 1000);
}
break;
case 'maxMileage':
if ($item > 0) {
$query->andHaving('vi.mileage <= :maxMileage')->setParameter('maxMileage', $item * 1000);
}
break;
case 'hasNDS':
if ($item == 'true') {
$query->andWhere('vi.has_nds = 1');
}
break;
case 'sale':
if ($item == 'true') {
$query->andWhere('vi.alt_price > 0');
}
break;
case 'isSelect':
if ($item == 'true') {
$query->andWhere($query->expr()->notIn('ve.dealer', Catalog::NOT_VIDI_SELECT_DEALERS));
}
break;
}
}
}
if (isset($searchParams['characteristic']) && $searchParams['characteristic']) {
foreach ($searchParams['characteristic'] as $type => $params) {
$cvIds = [];
$cType = $this->em->getRepository(\CoreBundle\Entity\Vehicles\Characteristic::class)->findOneBy(['url' => $type]);
$alias = 'vc' . $cType->getId();
$fKey = 'charId' . $cType->getId();
$tKey = 'cids' . $cType->getId();
$query->join('v.characteristics', $alias);
foreach (array_keys($params) as $vchUrl) {
$cValue = $this->em->getRepository(\CoreBundle\Entity\Vehicles\CharacteristicValue::class)->findOneBy(['url' => $vchUrl, 'characteristic' => $cType]);
if ($cValue) {
$cvIds[] = $cValue->getId();
}
}
if (!empty($cvIds)) {
$query->andWhere($alias . '.characteristic = :' . $fKey)->setParameter($fKey, $cType->getId());
$query->andWhere($alias . '.characteristic_value IN (:' . $tKey . ')')->setParameter($tKey, $cvIds);
}
}
}
$allResult = $query->getQuery()->getResult();
$totalCount = count($allResult);
$prices = [];
$pricesUsd = [];
$dollar = $this->em->getRepository(Dealer::class)->find(6)->getRate();
if($totalCount){
foreach ($allResult as $oneResult) {
$prices[] = ceil($oneResult['price']);
$pricesUsd[] = ceil($oneResult['price'] / $dollar);
}
}
$dataPrice = [
'minPrice' => $totalCount ? min($prices) : 0,
'maxPrice' => $totalCount ? max($prices) : 0,
'minPriceUsd' => $totalCount ? min($pricesUsd) : 0,
'maxPriceUsd' => $totalCount ? max($pricesUsd) : 0,
];
unset($allResult);
if($pageLimit) {
$limit = $pageLimit;
$page = isset($searchParams['page']) && $searchParams['page'] != '' ? $searchParams['page'] : 1;
$start = ($page - 1) * $limit;
}
$query->groupBy('vi');
if (isset($searchParams['sortOrder'])) {
$sortData = explode('-', $searchParams['sortOrder']);
$sortField = $sortData[0] ?? 'price';
$sortAD = isset($sortData[1]) && in_array($sortData[1], ['ASC', 'DESC']) ? $sortData[1] : 'ASC';
switch ($sortField) {
case 'price':
$field = $sortAD == 'DESC' ? 'price' : 'orderPrice';
$query->addOrderBy($field, $sortAD);
$query->addOrderBy('b.name', 'ASC');
$query->addOrderBy('m.title', 'ASC');
break;
case 'year':
$query->addOrderBy('vi.year', $sortAD);
$query->addOrderBy('b.name', 'ASC');
$query->addOrderBy('m.title', 'ASC');
break;
case 'mileage':
$query->addOrderBy('vi.mileage', $sortAD);
$query->addOrderBy('b.name', 'ASC');
$query->addOrderBy('m.title', 'ASC');
break;
case 'addVehicle':
$query->addOrderBy('ve.date_create', $sortAD);
$query->addOrderBy('b.name', 'ASC');
$query->addOrderBy('m.title', 'ASC');
break;
default:
$query->addOrderBy('orderPrice', 'ASC');
$query->addOrderBy('b.name', 'ASC');
$query->addOrderBy('m.title', 'ASC');
break;
}
} else {
$query->addOrderBy('orderPrice', 'ASC');
}
if($pageLimit) {
$query->setFirstResult($start)->setMaxResults($limit);
}
$data = $query->getQuery()->getResult();
return [
'count' => $totalCount,
'dataPrice' => $dataPrice,
'data' => $data
];
}
public function noFindVehicleByParams($pageLimit = 21)
{
$vehicleTypeData = $this->getVehicleType();
$query = $this->em->getRepository(VehicleItem::class)
->createQueryBuilder('vi')
->addSelect('vi')
->addSelect('CASE WHEN (d.id != 6) THEN CASE WHEN vi.alt_price > 0 THEN vi.alt_price / d.rate ELSE CASE WHEN vi.alt_rate > 0 THEN vi.alt_rate ELSE vi.price * d.rate END END ELSE CASE WHEN vi.alt_price > 0 THEN vi.alt_price / d.rate ELSE vi.price / d.rate END END AS price')
->addSelect('case when (case when (ve.is_used = 0 OR d.id != 6) then (case when vi.alt_price > 0 then vi.alt_price else (case when vi.alt_rate > 0 then vi.alt_rate * vi.price else vi.price * d.rate end) end) else (case when vi.alt_price > 0 then vi.alt_price else vi.price end) end) = 0 then 9999999999 else (case when (ve.is_used = 0 OR d.id != 6) then (case when vi.alt_price > 0 then vi.alt_price else (case when vi.alt_rate > 0 then vi.alt_rate * vi.price else vi.price * d.rate end) end) else (case when vi.alt_price > 0 then vi.alt_price else vi.price end) end) end as orderPrice')
->join('vi.variation', 'v')
->join('v.vehicle', 've', Join::WITH, 've.is_used = :isUsed')->setParameter('isUsed', true)
->join('ve.dealer', 'd')
->andWhere('ve.vehicle_type = :type')
// TODO Навіщо ми перевіряємо vehicleItem state на вживаних авто? У вживаного авто є всього 1 vehicleItem, і ми маємо відображати авто по vehicle state. Якщо все буде ок, повидаляти з усіх запитів
// ->andWhere('vi.state = 1')
->andWhere('ve.state = 1')
->andWhere('ve.is_not_filled = 0')
->andWhere('ve.is_delete != 1')
->setParameter('type', $vehicleTypeData['id'])
->orderBy('v.id', 'DESC')
->setMaxResults($pageLimit);
return [
'count' => 0,
'dataPrice' => ['minPrice' => 0,'maxPrice' => 0,'minPriceUsd' => 0,'maxPriceUsd' => 0],
'data' => $query->getQuery()->getResult(),
];
}
public function getBreadcrumbs()
{
$translator = $this->translator;
$router = $this->router;
$request = $this->requestStack->getCurrentRequest();
$routeParams = $request->attributes->get('_route_params');
$vehicleTypeData = $this->getVehicleType();
$catalogCharacteristic = $this->getCharacteristicsByParams($vehicleTypeData['id']);
$catalogRecommendGroup = $this->getRecommendGroupByParams($vehicleTypeData['id']);
$breadcrumbs = [];
$state = $routeParams['state'] ?? null;
$type = $routeParams['type'] ?? null;
$brand = $routeParams['brand'] ?? null;
$model = $routeParams['model'] ?? null;
$param = $routeParams['param'] ?? null;
$value = $routeParams['value'] ?? null;
$param2 = $routeParams['param2'] ?? null;
$value2 = $routeParams['value2'] ?? null;
$price = $routeParams['price'] ?? null;
$recommendGroup = $routeParams['recommendGroup'] ?? null;
$CharacteristicValue = $catalogCharacteristic[$param][$value] ?? null;
$CharacteristicValue2 = $catalogCharacteristic[$param2][$value2] ?? null;
$recommendGroupValue = $catalogRecommendGroup[$recommendGroup] ?? null;
if($state && $type){
$breadcrumbs[] = [
'title' => $translator->trans('catalog.' . $state . '_' . $type, [], 'automarket_base'),
'url' => $router->generate('automarket_catalog', ['state' => $state, 'type' => $type]),
];
}
if($brand){
$breadcrumbs[] = [
'title' => $brand,
'url' => $router->generate('automarket_catalog_brand', ['state' => $state, 'type' => $type, 'brand' => $brand]),
];
}
if($brand && $model){
$breadcrumbs[] = [
'title' => $model,
'url' => $router->generate('automarket_catalog_brand_model', ['state' => $state, 'type' => $type, 'brand' => $brand, 'model' => $model]),
];
}
if($recommendGroup){
$breadcrumbs[] = [
'title' => $recommendGroupValue,
'url' => $router->generate('automarket_catalog_vehicle_collections', ['state' => $state, 'type' => $type, 'recommendGroup' => $recommendGroup]),
];
}
if($param && $value && !$brand && !$model){
$breadcrumbs[] = [
'title' => $CharacteristicValue,
'url' => $router->generate('automarket_catalog_characteristic', ['state' => $state, 'type' => $type, 'brand' => $brand, 'model' => $model, 'param' => $param, 'value' => $value]),
];
}
if($param && $value && $param2 && $value2 && !$brand && !$model){
$breadcrumbs[] = [
'title' => $CharacteristicValue2,
'url' => $router->generate('automarket_catalog_characteristic_by_body', ['state' => $state, 'type' => $type, 'brand' => $brand, 'model' => $model, 'param' => $param, 'value' => $value, 'param2' => $param2, 'value2' => $value2]),
];
}
if ($param && $value && $brand && !$model) {
$breadcrumbs[] = [
'title' => $CharacteristicValue,
'url' => $router->generate('automarket_catalog_brand_characteristic', ['state' => $state, 'type' => $type, 'brand' => $brand, 'param' => $param, 'value' => $value]),
];
}
if($param && $value && $brand && $model){
$breadcrumbs[] = [
'title' => $CharacteristicValue,
'url' => $router->generate('automarket_catalog_brand_model_characteristic', ['state' => $state, 'type' => $type, 'brand' => $brand, 'model' => $model, 'param' => $param, 'value' => $value]),
];
}
if($price && $param && $value && $brand && $model){
$breadcrumbs[] = [
'title' => 'до ' . $price . ' $',
'url' => $router->generate('automarket_catalog_brand_model_characteristic_price', ['state' => $state, 'type' => $type, 'brand' => $brand, 'model' => $model, 'param' => $param, 'value' => $value, 'price' => $price]),
];
}elseif($price && $brand && $model){
$breadcrumbs[] = [
'title' => 'до ' . $price . ' $',
'url' => $router->generate('automarket_catalog_brand_model_price', ['state' => $state, 'type' => $type, 'brand' => $brand, 'model' => $model, 'price' => $price]),
];
}
return $breadcrumbs;
}
public function getSchemaCatalog()
{
}
}