<?php
namespace CoreBundle\Model\Vehicles;
use CoreBundle\Entity\Vehicles\Variation;
use CoreBundle\Entity\Vehicles\VariationCharacteristic;
use CoreBundle\Entity\Vehicles\VehicleItem;
use DateTime;
use CoreBundle\Repository\Vehicles\VehicleRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use CoreBundle\Repository\Vehicles\VehicleItemRepository;
use CoreBundle\Repository\Vehicles\VariationRepository;
use Application\Sonata\MediaBundle\Entity\Media;
use CoreBundle\Entity\Brand;
use CoreBundle\Entity\Dealer;
use CoreBundle\Entity\Model;
use CoreBundle\Entity\Vehicles\Category;
use CoreBundle\Entity\Vehicles\CharacteristicValue;
use CoreBundle\Entity\Vehicles\Group;
use CoreBundle\Entity\Vehicles\Vehicle;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\Query\Expr\Join;
class Repository
{
/**
* @var EntityManagerInterface
*/
private $em;
/**
* Vehicle constructor.
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* @return VehicleRepository|EntityRepository
*/
private function getVehicleRepository()
{
return $this->em->getRepository(Vehicle::class);
}
/**
* @return VehicleItemRepository|EntityRepository
*/
private function getVehicleItemRepository()
{
return $this->em->getRepository(VehicleItem::class);
}
/**
* @return VariationRepository|EntityRepository
*/
private function getVariationRepository()
{
return $this->em->getRepository(Variation::class);
}
/**
* @return VariationCharacteristic|EntityRepository
*/
private function getVariationCharacteristicRepository()
{
return $this->em->getRepository(VariationCharacteristic::class);
}
/**
* @return EntityRepository
*/
private function getCharacteristicRepository()
{
return $this->em->getRepository(Characteristic::class);
}
/**
* @param $id
* @return Vehicle|null
*/
public function findById($id)
{
return $this->getVehicleRepository()->find($id);
}
/**
* @param $url
* @param Dealer $Dealer
* @return null|Vehicle
*/
public function findByUrl($url, Dealer $Dealer)
{
return $this->getVehicleRepository()->findOneBy(['dealer' => $Dealer, 'url' => $url]);
}
public function findByUrlWithoutDealer($url)
{
return $this->getVehicleRepository()->findOneBy(['url' => $url]);
}
public function findByGroup($groupId, Dealer $Dealer)
{
$params = [
'state' => 1,
'is_used' => 0,
'group' => $groupId,
'dealer' => $Dealer,
'is_delete' => [0, null]
];
return $this->getVehicleRepository()->findBy($params);
}
public function getCarsToTestDrive(Dealer $dealer = null, $is_used = 0)
{
$queryBuilder = $this->getVehicleRepository()->createQueryBuilder('v')
->join('v.model', 'm')
->join('m.testdrive', 't')
->where('v.state = 1')
->andWhere('t.state = 1')
->andWhere('v.is_used = :is_used')
->andWhere('v.is_delete is null OR v.is_delete = 0')
->groupBy('v.id')
->setParameter('is_used', $is_used);
if ($dealer) {
$queryBuilder->andWhere('v.dealer = :dealer')
->setParameter('dealer', $dealer);
}
return $queryBuilder->getQuery()->getResult();
}
public function getOurCarsToTestDrive(Dealer $dealer = null, $is_used = 0)
{
$params = [
'state' => 1,
'is_used' => $is_used,
'test_drive' => 1,
'is_delete' => [0, null]
];
if ($dealer) {
$params['dealer'] = $dealer;
}
return $this->getVehicleRepository()->findBy($params);
}
/**
* @param $id
* @return Vehicle|null
*/
public function findUsedById($id)
{
return $this->getVehicleRepository()->findOneBy(['id' => $id, 'is_used' => 1, 'is_delete' => [0, null]]);
}
/**
* @param $url
* @return Vehicle|null
*/
public function findUsedByUrl($url)
{
return $this->getVehicleRepository()->findOneBy(['url' => $url, 'is_used' => 1]);
}
public function getSimilarVehicles(AbstractVehicle $vehicle, $used = false, $byDealer = false, $byBrand = false)
{
//todo remove
return [];
//todo remove magic numbers
$similarPricePercent = 20;
$maxPrice = $vehicle->price() * (($similarPricePercent + 100) / 100);
$minPrice = $vehicle->price() * ((100 - $similarPricePercent) / 100);
$query = $this->getVehicleItemRepository()->createQueryBuilder('v')
->join('v.variation', 'var')
->join('var.vehicle', 'vehicle')
->join('vehicle.model', 'm')
->where('vehicle.state = 1')
->andWhere('vehicle.is_used = :used')
->andWhere('vehicle.vehicle_type = :type')
->andWhere('(v.price <= :max and v.price >= :min and (v.alt_price = 0 OR v.alt_price is null)) OR (v.alt_price <= :max and v.alt_price >= :min)')
->andWhere('vehicle.id != :id')
->setParameter('used', (int)$used)
->setParameter('id', $vehicle->getVehicleId())
->setParameter('max', $maxPrice)
->setParameter('min', $minPrice)
->setParameter('type', $vehicle->getVehicleType());
if ($vehicle->getBodyType()) {
$query->join('var.characteristics', 'vc', Join::WITH, 'vc.characteristic = :characteristic AND vc.characteristic_value = :chValue')
->setParameter('characteristic', $vehicle->getBodyType()->getCharacteristic())
->setParameter('chValue', $vehicle->getBodyType()->getId());
}
if ($byDealer) {
$query->andWhere('vehicle.dealer = :dealer')
->setParameter('dealer', $vehicle->getDealer());
}
if ($byBrand) {
$query->andWhere('m.brand = :brand')
->setParameter('brand', $vehicle->getModel()->getBrand());
}
return $query->getQuery()->getResult();
}
public function getUsedByDealer(Dealer $dealer)
{
//todo remove magic numbers
return $this->getVehicleRepository()->findBy(['dealer' => $dealer, 'state' => 1, 'is_used' => 1]);
}
public function getUsedVehicle(Dealer $dealer, Brand $brand, $url, $vehicleType = false)
{
return $this->getVehicleRepository()->getUsedVehicle($dealer, $brand, $url);
}
public function getUsed(Dealer $dealer, $byBrand = false, $vehicleType = false, DateTime $date = null)
{
$brand = [];
if (is_array($byBrand)) {
$brand = $byBrand;
} elseif ($byBrand) {
$brand[] = $dealer->getBrand()->getId();
}
return $this->getVehicleRepository()->getUsedVehicles($dealer, $brand, $vehicleType, $date);
}
public function getUsedVehicleByDealerModel(Dealer $dealer, Model $model, $limit)
{
return $this->getVehicleRepository()->getUsedVehicleByDealerModel($dealer, $model, $limit);
}
public function getDisabled(Dealer $dealer)
{
//todo remove magic numbers
return $this->getVehicleRepository()->findBy(['dealer' => $dealer, 'show_disabled' => 1, 'state' => 0, 'is_used' => 0]);
}
public function getAllDisabled()
{
return $this->getVehicleRepository()->findBy(['show_disabled' => 1, 'state' => 0, 'is_used' => 0]);
}
public function getNewByDealer(Dealer $dealer = null, $vehicleTypes = [], bool $sortByPosition = null)
{
return $this->getVehicleRepository()->getNewByDealer($dealer, $vehicleTypes, $sortByPosition ?? null);
}
public function getByRecommendGroup(Dealer $dealer = null, $recomendGroupId)
{
$params = [
'state' => 1,
'is_used' => 0,
'is_delete' => [0, null],
'recommend_group' => $recomendGroupId,
];
if ($dealer) {
$params['dealer'] = $dealer;
}
return $this->getVehicleRepository()->findBy($params, ['position' => 'ASC']);
}
public function getVehicleByType(Dealer $dealer = null, $type, $isUsed = 0)
{
$params = [
'state' => 1,
'is_used' => $isUsed,
//todo remove magic numbers
'is_delete' => [0, null],
'vehicle_type' => $type,
];
if ($dealer) {
$params['dealer'] = $dealer;
}
return $this->getVehicleRepository()->findBy($params, ['position' => 'ASC']);
}
public function getHybridVehiclesByDealer(Dealer $dealer)
{
$fuelTypeChar = $this->em->getRepository(Characteristic::class)->findOneBy(['model_unique' => Characteristic::FUEL_TYPE_UNIQUE_ID, 'vehicle_type' => VehicleType::PASSENGER_TYPE]);
//todo remove magic numbers
return $this->getVehicleRepository()->getVehiclesByCharacteristic($dealer, $fuelTypeChar, 16);
}
public function getHybridVehiclesQueryBuilder(Dealer $dealer)
{
$fuelTypeChar = $this->em->getRepository(Characteristic::class)->findOneBy(['model_unique' => Characteristic::FUEL_TYPE_UNIQUE_ID, 'vehicle_type' => VehicleType::PASSENGER_TYPE]);
//todo remove magic numbers
return $this->getVehicleRepository()->getVehiclesQueryByCharacteristic($dealer, $fuelTypeChar, 16);
}
public function getActionVehicleItems(Dealer $dealer = null)
{
return $this->getVehicleItemRepository()->getActions($dealer);
}
public function getByCategory(Category $category, Dealer $dealer)
{
return $this->getVehicleRepository()->findBy(['category' => $category, 'dealer' => $dealer, 'state' => 1, 'is_used' => 0]);
}
public function getByCategoryWithPagination(Dealer $dealer, $category, $page, $limit = 4)
{
$query = $this->getVehicleRepository()->createQueryBuilder('ve')
->where('ve.is_used = 0')
->andWhere('ve.state = 1')
->andWhere('ve.dealer = :dealer')->setParameter('dealer', $dealer)
->orderBy('ve.date_create', 'ASC');
if ($category) {
$query->andWhere('ve.category = :category')->setParameter('category', $category);
}
if($page > 0){
$offset = ($page - 1) * $limit;
$query->setFirstResult($offset)
->setMaxResults($limit);
}
return $query->getQuery()->getResult();
}
public function getByCategoryGroup(Category $category, Group $group, Dealer $dealer)
{
return $this->getVehicleRepository()->findBy(['category' => $category, 'group' => $group, 'dealer' => $dealer, 'state' => 1, 'is_used' => 0]);
}
public function getRentalByDealer(Dealer $dealer)
{
return $this->getVehicleItemRepository()->getRentVehicles($dealer);
}
public function getUsedVehicles($vehicleType = null)
{
$params = [
'is_used' => 1,
'state' => 1,
];
if ($vehicleType) {
$params['vehicle_type'] = $vehicleType;
}
return $this->getVehicleRepository()->findBy($params);
}
/**
* @param $type
* @param Dealer|null $dealer
* @return array|Vehicle[]
*/
public function getVehiclesByType($type, Dealer $dealer = null)
{
$params = [
'vehicle_type' => $type,
'is_used' => '0',
];
if ($dealer) {
$params['dealer'] = $dealer;
}
return $this->getVehicleRepository()->findBy($params);
}
public function getAvailUsedBodyTypes($vehicleType, $locale)
{
$characteristics = $this->getVariationCharacteristicRepository()->createQueryBuilder('vc')
->join('vc.variation', 'variation')
->join('vc.characteristic', 'c', Join::WITH, 'c.model_unique = :CUID')
->join('variation.vehicle', 'vehicle')
->where('vehicle.is_used = 1')
->where('vehicle.vehicle_type = :vehicle_type')
->setParameter('CUID', Characteristic::BODY_TYPE_UNIQUE_ID)
->setParameter('vehicle_type', $vehicleType)
->getQuery()
->getResult();
$result = [];
foreach ($characteristics as $c) {
$cv = $c->getCharacteristicValue();
if (!$cv) {
continue;
}
$result[$cv->getId()] = $cv->getValue($locale);
}
return $result;
}
/**
* @param $interestType
* @param int $is_used
* @return array
*/
public function getMainInterest($interestType, $is_used = 0)
{
$sort = '';
$order = '';
switch ($interestType) {
case 1:
$sort = 'vi.price';
$order = 'ASC';
break;
case 2:
$sort = 'vi.price';
$order = 'ASC';
break;
case 3:
$sort = 'v.id';
$order = 'DESC';
break;
}
$crafted = [];
$query = $this->getVehicleRepository()->createQueryBuilder('v')
->innerJoin('v.vehicle_items', 'vi')
->andWhere('v.is_used = 1')
->andWhere('v.state = 1')
->andWhere('vi.sold = 0')
->andWhere('vi.deposit = 0')
->orderBy($sort, $order)
->setMaxResults(4);
if ($interestType == 1) {
$query->andWhere('v.recommend = 1');
}
return $query->getQuery()->getResult();
}
public function getNewAddVehicleItem($isUsed = false, $limit = 5, Dealer $dealer = null)
{
$query = $this->getVehicleItemRepository()->createQueryBuilder('vi')
->innerJoin('vi.vehicle', 've')
->where('vi.deposit = :deposit')->setParameter('deposit', false)
->andWhere('ve.is_used = :isUsed')->setParameter('isUsed',$isUsed)
->andWhere('ve.state = :vehicleState')->setParameter('vehicleState',true)
->andWhere('ve.is_not_filled = :isNotFilled')->setParameter('isNotFilled',false)
->andWhere('ve.is_delete = :isDelete')->setParameter('isDelete',false)
->andWhere('vi.sold != 1')
->orderBy('ve.id', 'DESC')
->setMaxResults($limit);
if ($dealer) {
$query->andWhere('ve.dealer = :dealer')->setParameter('dealer', $dealer);
}
return $query->getQuery()->getResult();
}
public function getProposeVehicleItem($isUsed = false, $brand = null, $model = null, $bodyType = null, $withDiscount = false)
{
$query = $this->getVehicleItemRepository()->createQueryBuilder('vi')
->innerJoin('vi.vehicle', 've')
->innerJoin('ve.model', 'model')
->where('vi.deposit = :deposit')->setParameter('deposit', false)
->andWhere('ve.is_used = :isUsed')->setParameter('isUsed',$isUsed)
->andWhere('ve.state = :vehicleState')->setParameter('vehicleState',true)
->andWhere('ve.is_not_filled = :isNotFilled')->setParameter('isNotFilled',false)
->andWhere('ve.is_delete = :isDelete')->setParameter('isDelete',false)
->andWhere('vi.sold != 1')
->orderBy('(vi.alt_price / vi.price) * 100', 'ASC');
if($brand && $model){
$query->andWhere('model.brand = :brand')->setParameter('brand', $brand)
->andWhere('model = :model')->setParameter('model', $model);
}
if($brand && !$model){
$query->andWhere('model.brand = :brand')->setParameter('brand', $brand);
}
if($withDiscount){
$query->andWhere('vi.alt_price > 0');
}
if($bodyType){
$query->join('vi.variation', 'var')
->join('var.characteristics', 'vc', Join::WITH,
'vc.characteristic = :characteristic AND vc.characteristic_value = :chValue')
->setParameter('characteristic', $bodyType->getCharacteristic())
->setParameter('chValue', $bodyType->getId());
}
return $query->getQuery()->getResult();
}
public function getMinUsedYear($vehicleType)
{
return $this->getVehicleItemRepository()->createQueryBuilder('vi')
->innerJoin('vi.vehicle', 'v', Join::WITH, 'v.is_used = 1')
->where('v.state = 1')
->andWhere('v.vehicle_type = :vehicle_type')
->setParameter('vehicle_type', $vehicleType)
->select('MIN(vi.year)')
->getQuery()
->getSingleScalarResult();
}
/**
* @param $vehicleType
* @return Brand[]
*/
public function getUsedVehicleBrands($vehicleType)
{
return $this->em->getRepository(Brand::class)->getUsedVehicleBrands($vehicleType);
}
public function getSortedByPositionVehicle($vehicles)
{
usort($vehicles, fn($a, $b) => $a->getPosition() <=> $b->getPosition());
return $vehicles;
}
public function getCatalogFilters($vehicleType, $locale)
{
$characteristics = $this->getCharacteristicRepository()->findBy(['characteristic_type' => Characteristic::REFERENCE_TYPE, 'vehicle_type' => $vehicleType, 'in_filter' => 1]);
$dynamicCharacteristic = [];
/** @var \CoreBundle\Entity\Vehicles\Characteristic $characteristic */
foreach ($characteristics as $characteristic) {
$chracteristicItem = [
'id' => $characteristic->getId(),
'title' => $characteristic->getTitle($locale),
'values' => []
];
/** @var CharacteristicValue $cValue */
foreach ($characteristic->getCharacteristicValue() as $cValue) {
$chracteristicItem['values'][] = [
'title' => $cValue->getValue($locale),
'value' => $cValue->getId(),
];
}
$dynamicCharacteristic[] = $chracteristicItem;
}
$brands = $this->getUsedVehicleBrands(VehicleType::PASSENGER_TYPE);
$brResult = [];
foreach ($brands as $brand) {
$brResult[] = [
'title' => $brand->getName(),
'value' => $brand->getId(),
];
}
return [
'brand' => $brResult,
'dynamic' => $dynamicCharacteristic,
];
}
/**
* @param $params
* @param $step
* @param $limit
* @param bool $withNotFilled
* @return array
*/
public function findUsedByParams($params, $step, $limit, $withNotFilled = false)
{
$params['state'] = ['used'];
$params['filled'] = $withNotFilled;
$vehicleItems = $this->getVehicleItemRepository()->findByParams($params, $step, $limit);
return [
'vehicleItems' => $vehicleItems,
'count' => count($vehicleItems)
];
}
/**
* @param $params
* @param $step
* @param $limit
* @return array
* @throws OptimisticLockException
*/
public function findByParams($params, $step, $limit)
{
$totalCount = $this->getVehicleItemRepository()->getCountByParams($params);
$vehicleItems = $this->getVehicleItemRepository()->findByParams($params, $step, $limit);
return [
'vehicleItems' => $vehicleItems,
'count' => $totalCount
];
}
public function getAvailBrandsInstance($locale, bool $filterPalmira = false)
{
$brands = $this->em->getRepository(Brand::class)->getAvailBrandsInstance(true, false, $filterPalmira);
$result = [];
/**
* @var int $key
* @var Brand $brand
*/
foreach ($brands as $key => $brand) {
$result[$key] = [
'id' => $brand->getId(),
'name' => $brand->getName(),
'image' => $brand->getLogo(),
];
if (count($brand->getDealer()) == 1) {
$result[$key]['dealerId'] = $brand->getDealer()->first()->getId();
$result[$key]['dealerUrl'] = $brand->getDealer()->first()->getUrl();
$result[$key]['dealerTitle'] = $brand->getDealer()->first()->getName();
$result[$key]['dealerAddress'] = $brand->getDealer()->first()->getAddressByLocale($locale);
} else {
/** @var Dealer $dealer */
foreach ($brand->getDealer() as $dealer) {
$result[$key]['dealers'][] = [
'id' => $dealer->getId(),
'title' => $dealer->getNameByLocale($locale),
'adres' => $dealer->getAddressByLocale($locale),
'url' => $dealer->getUrl()
];
}
}
}
return $result;
}
/**
* @param bool $withoutImage
* @param null $state
* @param null $vehicleType
* @param null $hasNDS
* @return mixed
*/
public function getAvailBrands($withoutImage = false, $state = null, $vehicleType = null, $hasNDS = null)
{
$brands = $this->em->getRepository(Brand::class)->getAvailBrands($withoutImage, $state, $vehicleType, $hasNDS);
$result = [];
foreach ($brands as $key => $brand) {
/** @var Brand $brandObject */
$brandObject = $brand[0];
$logo = $brandObject->getLogo();
$result[$key] = [
'id' => $brandObject->getId(),
'count' => $brand['cnt'],
'name' => $brandObject->getName(),
'url' => $brandObject->getUrl(),
'image' => $brand['image'],
'logo' => $logo ? $logo->getId() : null,
'logoObj' => $logo
];
}
return $result;
}
public function getSchoolVehicles(Dealer $dealer)
{
return $this->em->getRepository(Vehicle::class)->findBy(['school_available' => 1, 'dealer' => $dealer]);
}
public function searchCar($string)
{
return $this->getVehicleRepository()->searchCar($string);
}
public function getUsedByBrand(Brand $brand)
{
return $this->getVehicleRepository()->createQueryBuilder('v')
->join('v.model', 'm')
->where('v.is_used = 1')
->andWhere('v.state = 1')
->andWhere('m.brand = :brand')
->setParameter('brand', $brand)
->getQuery()->getResult();
}
}