<?php
/**
* Created by PhpStorm.
* User: serhii.patsai
* Date: 11.09.2019
* Time: 12:27
*/
namespace CoreBundle\Model;
use DateTime;
use CoreBundle\Entity\User;
use CoreBundle\Entity\Dealer;
use CoreBundle\Entity\VehicleEstimate;
use CoreBundle\Factory\Vehicle;
use CoreBundle\Model\Api\AutoRia\AutoRia;
use CoreBundle\Model\Vehicles\Repository;
use DcSiteBundle\Entity\Markdown;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\OptimisticLockException;
class OnlineEstimateModel
{
/**
* @var Rate
*/
private $rateModel;
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var AutoRia
*/
private $AutoRia;
/**
* OnlineEstimateModel constructor.
* @param Rate $rate
* @param EntityManagerInterface $em
* @param Vehicle $VehicleFactory
* @param Repository $repository
*/
public function __construct(Rate $rate, EntityManagerInterface $em, AutoRia $AutoRia)
{
$this->rateModel = $rate;
$this->em = $em;
$this->AutoRia = $AutoRia;
}
private function isSelect($params, $dealer = null, $isCRM = false) {
$old = (new DateTime())->format('Y')-$params['year'];
$mileage = explode('-', $params['mileage']);
if (count($mileage) == 2) {
$mileageTo = $mileage[1];
} else {
$mileage = $params['mileage'] < 1000 ? $params['mileage'] : ceil($params['mileage']/1000);
$mileageTo = $mileage + ($mileage*0.60);
}
$dealerInProgram = !$dealer || in_array($dealer->getId(), [8,27,35,34,3,29,28,32,33,37,38,15,30,9,31,39]);
$isOurBrand = in_array($params['brand']['id'], [55,47,58,75,24,15,76,31,37,28,128,85,56,5456,49]);
$inOld = $old <=5;
$inMileage = $mileageTo <= 100;
return $dealerInProgram && $isOurBrand && $inOld && $inMileage;
}
public function getPrices($estimate, $params)
{
$itemIds = [];
foreach ($estimate->result->search_result_common->data as $row) {
if($row->type == 'UsedAuto') {
$itemIds[] = $row->id;
}
}
$fullItems = [];
$fuelId = $params['fuel'];
foreach ($itemIds as $id) {
$data = $this->AutoRia->getFullInfo($id);
if(!$data) {
continue;
}
if(in_array($fuelId,[1,2,3,4]) && !in_array($data->autoData->fuelId,[1,2,3,4])) {
continue;
}
$item['price'] = $data->UAH;
$item['year'] = $data->autoData->year;
$item['raceInt'] = $data->autoData->raceInt;
$item['fuelId'] = $data->autoData->fuelId;
$item['gearBoxId'] = $data->autoData->gearBoxId ?? null;
$fullItems[$id] = $item;
}
$yCof = [
'+' => [
2022 => 0.85,
2021 => 0.9,
2020 => 0.93,
2019 => 0.94,
2018 => 0.94,
2017 => 0.95,
2016 => 0.95,
2015 => 0.96,
2014 => 0.96,
2013 => 0.97,
2012 => 0.97,
2011 => 0.98,
2010 => 0.98,
2009 => 0.99,
2008 => 0.99,
],
'-' => [
2021 => 1.15,
2020 => 1.1,
2019 => 1.07,
2018 => 1.06,
2017 => 1.06,
2016 => 1.05,
2015 => 1.05,
2014 => 1.04,
2013 => 1.04,
2012 => 1.03,
2011 => 1.03,
2010 => 1.02,
2009 => 1.02,
2008 => 1.01,
2007 => 1.01,
]
];
foreach($fullItems as $id => $item) {
$Cyear = $params['year'];
$mYear = $params['year']-1;
$pYear = $params['year']+1;
$uCoh = false;
if($item['year'] == $Cyear) {
$uCoh = 1;
}
if($item['year'] == $mYear) {
if(isset($yCof['-'][$mYear])) {
$uCoh = $yCof['-'][$mYear];
}
}
if($item['year'] == $pYear) {
if(isset($yCof['+'][$pYear])) {
$uCoh = $yCof['+'][$pYear];
}
}
if(!$uCoh) {
unset($fullItems[$id]);
continue;
}
$fullItems[$id]['newPrice'] = $fullItems[$id]['price']*$uCoh;
if($fuelId == 2 && in_array($item['fuelId'],[1,3,4])) {
$fullItems[$id]['newPrice'] *= 1.07;
}
if($item['fuelId'] == 2 && in_array($fuelId,[1,3,4])) {
$fullItems[$id]['newPrice'] /= 1.07;
}
}
$raceC = [
'+' => [
'0-50' => false,
'51-100' => 1.1,
'101-150' => 1.05,
'151-200' => 1.05,
'201-500' => 1.1,
],
'-' => [
'0-50' => 0.9,
'51-100' => 0.95,
'101-150' => 0.95,
'151-200' => 0.95,
],
];
$mileage = explode('-', $params['mileage']);
$mileageFrom = $mileage[0];
$mileageTo = $mileage[1];
$pKeys = array_keys($raceC['+']);
$mKeys = array_keys($raceC['-']);
$currentPIndex = array_search($params['mileage'],$pKeys);
$currentMIndex = array_search($params['mileage'],$mKeys);
$pCofIndex = false;
$mCofIndex = false;
if($currentPIndex !== false && $currentPIndex > 0 && isset($pKeys[$currentPIndex-1])) {
$pCofIndex = $pKeys[$currentPIndex-1];
}
if($currentMIndex !== false && isset($mKeys[$currentMIndex+1])) {
$mCofIndex = $mKeys[$currentMIndex+1];
}
foreach($fullItems as $id => $item) {
$race = $item['raceInt'];
$rCof = false;
if($race >= $mileageFrom && $race <= $mileageTo) {
$rCof = 1;
}
if($pCofIndex) {
$arr = explode('-',$pCofIndex);
if($race >= $arr[0] && $race <= $arr[1]) {
$rCof = $raceC['+'][$pKeys[$currentPIndex]];
}
}
if($mCofIndex) {
$arr = explode('-',$mCofIndex);
if($race >= $arr[0] && $race <= $arr[1]) {
$rCof = $raceC['-'][$mKeys[$currentMIndex]];
}
}
if(!$rCof) {
unset($fullItems[$id]);
continue;
}
$fullItems[$id]['newPrice'] *= $rCof;
}
return $fullItems;
}
public function updateByNew($params,$result)
{
$ageCar = (date('Y') - $params['year']) * 12;
$ageCar = $ageCar == 0 ? 6 : $ageCar;
if ($ageCar <= 60) {
$apiParams = [
'markaId' => [$params['brand']['id']],
'modelId' => [$params['model']['id']]
];
if (isset($params['fuel']) && $params['fuel']) {
$fuelId = $this->AutoRia->getFuelApi($params['fuel']);
$apiParams = array_merge($apiParams, ['fuelId' => $fuelId]);
}
if (isset($params['transmission']) && $params['transmission']) {
$gearId = $this->AutoRia->getGearApi($params['transmission']);
$apiParams = array_merge($apiParams, ['gearId' => $gearId]);
}
$cars = $this->AutoRia->getCars($apiParams);
/** @var Markdown $markdown */
$markdown = $this->em->getRepository(Markdown::class)->findOneBy(['ria_model_id' => $params['model']['id']]);
if(!$markdown) {
$markdown = $this->em->getRepository(Markdown::class)->findOneBy(['ria_brand_id' => $params['brand']['id']]);
}
if ($cars && count($cars->autos) > 1 && $markdown) {
$avgPrice = 0;
foreach ($cars->autos as $item) {
$avgPrice += $item->price;
}
$avgPrice /= count($cars->autos);
//$avgPrice = array_sum(array_column($cars->autos, 'price')) / count($cars->autos);
$getRetail = 'getRetail' . $ageCar;
$markdownValue = $markdown->$getRetail();
$markdownPrice = round($avgPrice - ($avgPrice * $markdownValue / 100));
if ($result['isSelect']) {
$newPrices = $this->calcPricesUAH(0, $markdownPrice);
} else {
$newPrices = $this->calcPricesUAH($markdownPrice, 0);
}
$result['success'] = true;
if($result['price']) {
$result['price'] = ($markdownPrice + $result['price']) /2;
$result['priceTI'] = ($newPrices['priceTradeIn'] + $result['priceTI']) /2;
$result['priceBuy'] = ($newPrices['priceBuy'] + $result['priceBuy']) /2;
$result['priceSelect'] = ($newPrices['priceSelect'] + $result['priceSelect']) /2;
$result['priceSelectBuy'] = ($newPrices['priceSelectBuy'] + $result['priceSelectBuy']) /2;
} else {
$result['price'] = $markdownPrice;
$result['priceTI'] = $newPrices['priceTradeIn'];
$result['priceBuy'] = $newPrices['priceBuy'];
$result['priceSelect'] = $newPrices['priceSelect'];
$result['priceSelectBuy'] = $newPrices['priceSelectBuy'];
}
}
}
return $result;
}
public function processEstimateResultNew($result, $params, $dealer = null, $isCRM = false)
{
$rate = (float) $this->rateModel->getRate();
$fullItems = $this->getPrices($result, $params);
$pricesArr = [];
foreach ($fullItems as $row) {
$pricesArr[] = ceil($row['newPrice']);
}
$price = 0;
$priceSelect = 0;
if (count($pricesArr) > 3 || ($dealer && $dealer->getId() == 16) ) {
$priceSelect = $this->averagePriceItems(40, $pricesArr, true);
$price = $this->averagePriceItems(10, $pricesArr);
}
$prices = $this->calcPricesNew($price, $priceSelect, $this->isSelect($params,$dealer,$isCRM));
$vehicle = ($params['brand']['title'] ?? '').' '.($params['model']['title'] ?? '');
$year = $params['year'];
$hash = md5(time().$price.'salt-retds4346FE#R42');
$data = [
'isSelect' => $this->isSelect($params,$dealer),
'vehicle' => $vehicle,
'hash' => $hash,
'fullItems' => $fullItems,
'countItems' => is_array($fullItems) ? count($fullItems) : 0,
'year' => $year,
'odometer' => $params['mileage'],
'success' => $price > 0,
'price' => $price,
'rate' => $rate,
'priceSelectBase' => $priceSelect,
'priceTI' => $prices['priceTradeIn'],
'priceBuy' => $prices['priceBuy'],
'priceSelect' => $prices['priceSelect'],
'priceSelectBuy' => $prices['priceSelectBuy'],
];
return $this->updateByNew($params,$data);
}
/**
* @param $result
* @param $params
* @param null $dealer
* @return array
* @throws OptimisticLockException
*/
public function processEstimateResult($result, $params, $dealer = null)
{
$rate = (float) $this->rateModel->getRate();
$price = 0;
$priceSelect = 0;
if (count($result->prices) > 3 || ($dealer && $dealer->getId() == 16) ) {
$priceSelect = $this->averagePriceItems(50, $result->prices, true);
$price = $this->averagePriceItems(30, $result->prices, false);
}
$odd = null;
$prices = $this->calcPrices($price, $priceSelect, $odd, $this->isSelect($params,$dealer));
$vehicle = $params['brand']['title'].' '.$params['model']['title'];
$year = $params['year'];
$hash = md5(time().$price.'salt-retds4346FE#R42');
$data = [
'isSelect' => $this->isSelect($params,$dealer),
'vehicle' => $vehicle,
'hash' => $hash,
'year' => $year,
'odometer' => $params['mileage'],
'success' => $price > 0,
'rate' => $rate,
'price' => $price,
'priceSelectBase' => $priceSelect,
'priceTI' => $prices['priceTradeIn'],
'priceBuy' => $prices['priceBuy'],
'priceSelect' => $prices['priceSelect'],
'priceSelectBuy' => $prices['priceSelectBuy'],
];
return $data;
}
public function saveEstimateResult($params, $data, Dealer $dealer = null, User $User = null, $userCar = null, $fromCrm = false) {
$estimate = new VehicleEstimate();
$estimateResultData = [
'request' => $params,
'result' => $data,
];
$estimate->setDateCreate(new DateTime());
$estimate->setDealer($dealer ?? null);
$estimate->setIsFinish(0);
$estimate->setIsSelect($data['isSelect']);
$estimate->setPhone($params['phone'] ?? null);
$estimate->setEmail($params['email'] ?? 'CRM');
$estimate->setUtm($params['utm']);
$estimate->setHref($params['href']);
$estimate->setReferrer($params['referrer']);
$estimate->setGclId($params['gcl_id']);
$estimate->setName($params['name'] ?? null);
$estimate->setUser($User ?? null);
$estimate->setUserCar($userCar);
$estimate->setCrmState(0);
$estimate->setHash($data['hash']);
$estimate->setIsSend(0);
$estimate->setCrmState($fromCrm ? 3 : 0);
$estimate->setData(json_encode($estimateResultData));
$this->em->persist($estimate);
$this->em->flush();
return $estimate->getId();
}
/**
* @param VehicleEstimate $estimate
* @return array
* @throws OptimisticLockException
*/
public function processEstimateEntity(VehicleEstimate $estimate)
{
$estimateData = json_decode($estimate->getData());
return (array) $estimateData->result;
}
/**
* @param $price
* @param $priceSelect
* @param $odd
* @return array
* @throws OptimisticLockException
*/
public function calcPricesNew($price, $priceSelect, $isSelect)
{
$odd = 10;
$priceBuyInUSD = round($price * ((100 - $odd) / 100));
$priceBuySelectInUSD = round($priceSelect * ((100 - $odd) / 100));
$priceTradeInUSD = round($priceBuyInUSD * 1.02);
$priceSelectUSD = round($priceBuySelectInUSD);
$priceBuy = (float) round($priceBuyInUSD);
$priceTradeIn = (float) round($priceTradeInUSD);
$priceSelect = (float) round($priceSelectUSD);
if($isSelect) {
$priceBuy = round($priceSelect / (1 + 0.04));
}
$prices = [
'priceBuyInUSD' => $priceBuyInUSD,
'priceBuy' => $priceBuy,
'priceTradeIn' => $priceTradeIn,
'priceTradeInUSD' => $priceTradeInUSD,
'priceSelectUSD' => $priceSelectUSD,
'priceSelect' => $priceSelect,
'priceSelectBuy' => $priceSelect*0.98,
'priceUSD' => $price,
];
return $prices;
}
/**
* @param $price
* @param $priceSelect
* @param $odd
* @return array
* @throws OptimisticLockException
*/
public function calcPrices($price, $priceSelect, $odd = null, $isSelect)
{
if (is_null($odd)) {
$odd = 10;
}
$rate = $this->rateModel->getRate();
$priceBuyInUSD = round($price * ((100 - $odd) / 100));
$priceBuySelectInUSD = round($priceSelect * ((100 - $odd) / 100));
$priceTradeInUSD = round($priceBuyInUSD * 1.02);
$priceSelectUSD = round($priceBuySelectInUSD);
$priceBuy = (float) round($priceBuyInUSD * $rate);
$priceTradeIn = (float) round($priceTradeInUSD * $rate);
$priceSelect = (float) round($priceSelectUSD * $rate);
if($isSelect) {
$priceBuy = round($priceSelect / (1 + 0.04));
}
$prices = [
'priceBuyInUSD' => $priceBuyInUSD,
'rate' => $rate,
'priceBuy' => $priceBuy,
'priceTradeIn' => $priceTradeIn,
'priceTradeInUSD' => $priceTradeInUSD,
'priceSelectUSD' => $priceSelectUSD,
'priceSelect' => $priceSelect,
'priceSelectBuy' => $priceSelect*0.98,
'priceUSD' => $price,
];
return $prices;
}
public function calcPricesUAH($price, $priceSelect, $odd = null)
{
if (is_null($odd)) {
$odd = 10;
}
$priceBuy = round($price * ((100 - $odd) / 100));
$priceBuySelect = round($priceSelect * ((100 - $odd) / 100));
$priceBuyTradeIn = round(($priceSelect ? $priceBuySelect : $priceBuy) * 1.02);
if($priceSelect) {
$priceBuy = $priceBuySelect * 0.98;
}
return [
'priceBuy' => $priceBuy,
'priceTradeIn' => $priceBuyTradeIn,
'priceSelect' => $priceBuySelect,
'priceSelectBuy' => $priceBuySelect*0.98,
];
}
private function averagePriceItems($percent, $priceItems , $isReverse = false)
{
if(count($priceItems) > 3) {
$isReverse ? rsort($priceItems) : sort($priceItems);
$offset = floor(count($priceItems) * 10 / 100);
$offset = $offset < 1 ? 1 : $offset;
$limit = floor(count($priceItems) * $percent / 100);
$limit = $limit < 1 ? 1 : $limit;
$length = count($priceItems) - $offset - $limit;
$priceItems = array_slice($priceItems, $offset, $length);
return round(array_sum($priceItems) / count($priceItems));
}
else
{
return null;
}
}
}