<?php
namespace App\Controller;
use App\Repository\CarRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\CarSaleRepository;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
class HomeController extends AbstractController
{
/**
* @Route("/", name="homepage")
*/
public function index(ManagerRegistry $doctrine, CarSaleRepository $carSaleRepository, CarRepository $carRepository): Response
{
//dump( $this->getStatistics($doctrine, 7) ) ; exit();
/*
$currentDate = new \DateTime();
$query = "
SELECT c.name, c.status, cs.car_sale_id, cs.is_done_date, cs.signaled_date, cs.price, cs.currency, cs.is_done
FROM car_sale cs
LEFT JOIN car c ON c.id = cs.car_sale_id
WHERE c.status IN ('sold', 'signaled')
AND MONTH(is_done_date) = MONTH(:date)
AND YEAR(is_done_date) = YEAR(:date)
";
$conn = $doctrine->getConnection();
$params = [ 'date' => $currentDate->format('Y:m:d') ];
$result = $conn->executeQuery($query, $params);
$dataCurrentMonth = $result->fetchAll();
$aStatisticsCurrentMonth = [
'delivered' => 0,
'signaled' => 0,
'deliveredPrice' => 0,
'signaledPrice' => 0
];
foreach ($dataCurrentMonth as $item) {
$isDone = $item['is_done'];
$currency = $item['currency'];
$price = $item['price'];
$signaledDate = new \DateTime($item['signaled_date']);
if ($isDone) {
$aStatisticsCurrentMonth['delivered'] ++;
$aStatisticsCurrentMonth['deliveredPrice'] = $aStatisticsCurrentMonth['deliveredPrice'] + $price;
//$nDelivered ++;
//$nDeliveredPrice = $nDeliveredPrice + $price;
}
if (!$isDone && $signaledDate != null && $signaledDate->format('Y-m') === $currentDate->format('Y-m')) {
$aStatisticsCurrentMonth['signaled'] ++;
$aStatisticsCurrentMonth['signaledPrice'] = $aStatisticsCurrentMonth['signaledPrice'] + $price;
//$nSignaled ++;
//$nSignaledPrice = $nSignaledPrice + $price;
}
}
*
dump($aStatisticsCurrentMonth);
exit();
$data = $carSaleRepository->createQueryBuilder('cs')
->leftJoin('cs.carSale', 'c')
->leftJoin('cs.carPayment', 'cscp')
->leftJoin('cs.bankCheckId', 'csb')
->leftJoin('cscp.car', 'cp')
->leftJoin('cs.user', 'u')
->leftJoin('cs.client', 'cl')
->addSelect('c')
->addSelect('cscp')
->addSelect('csb')
->addSelect('cp')
->addSelect('u')
->addSelect('cl')
->where('cs.id > :id')
->setParameter('id', '0');
$data = $data->leftJoin('App:Agency', 'ag', 'WITH', 'cs.id = ag.saleId')
->addSelect('ag.enabledNotification, ag.status');
$dataCurrent = clone $data->having('MONTH(cs.isDoneDate) = MONTH(CURRENT_DATE())')
->andHaving('YEAR(cs.isDoneDate) = YEAR(CURRENT_DATE())')
->orHaving('cs.isDone = 0');
/*$monthPrev = new \DateTime();
$monthPrev->modify('-1 month');
$monthPrev = $monthPrev->format('Y-m-d');
exit($monthPrev);
* /
$monthPrev = (new \DateTime('first day of this month'))->modify('-1 months')->setTime(0, 0);
$dataPrev1 = clone $data->having('MONTH(cs.isDoneDate) = MONTH(:monthPrev)')
->andHaving('YEAR(cs.isDoneDate) = YEAR(:monthPrev)')
->orHaving('cs.isDone = 0')
->setParameter('monthPrev', $monthPrev);
$monthPrev = (new \DateTime('first day of this month'))->modify('-2 months')->setTime(0, 0);
$dataPrev2 = clone $data->having('MONTH(cs.isDoneDate) = MONTH(:monthPrev)')
->andHaving('YEAR(cs.isDoneDate) = YEAR(:monthPrev)')
->orHaving('cs.isDone = 0')
->setParameter('monthPrev', $monthPrev);
$monthPrev = (new \DateTime('first day of this month'))->modify('-3 months')->setTime(0, 0);
$dataPrev3 = clone $data->having('MONTH(cs.isDoneDate) = MONTH(:monthPrev)')
->andHaving('YEAR(cs.isDoneDate) = YEAR(:monthPrev)')
->orHaving('cs.isDone = 0')
->setParameter('monthPrev', $monthPrev);
$monthPrev = (new \DateTime('first day of this month'))->modify('-4 months')->setTime(0, 0);
$dataPrev4 = clone $data->having('MONTH(cs.isDoneDate) = MONTH(:monthPrev)')
->andHaving('YEAR(cs.isDoneDate) = YEAR(:monthPrev)')
->orHaving('cs.isDone = 0')
->setParameter('monthPrev', $monthPrev);
$monthPrev = (new \DateTime('first day of this month'))->modify('-5 months')->setTime(0, 0);
$dataPrev5 = clone $data->having('MONTH(cs.isDoneDate) = MONTH(:monthPrev)')
->andHaving('YEAR(cs.isDoneDate) = YEAR(:monthPrev)')
->orHaving('cs.isDone = 0')
->setParameter('monthPrev', $monthPrev);
$monthPrev = (new \DateTime('first day of this month'))->modify('-6 months')->setTime(0, 0);
$dataPrev6 = clone $data->having('MONTH(cs.isDoneDate) = MONTH(:monthPrev)')
->andHaving('YEAR(cs.isDoneDate) = YEAR(:monthPrev)')
->orHaving('cs.isDone = 0')
->setParameter('monthPrev', $monthPrev);
$total = $dataCurrent->getQuery()
->getArrayResult();
$totalPrev1 = $dataPrev1->getQuery()
->getArrayResult();
$totalPrev2 = $dataPrev2->getQuery()
->getArrayResult();
$totalPrev3 = $dataPrev3->getQuery()
->getArrayResult();
$totalPrev4 = $dataPrev4->getQuery()
->getArrayResult();
$totalPrev5 = $dataPrev5->getQuery()
->getArrayResult();
$totalPrev6 = $dataPrev6->getQuery()
->getArrayResult();
/*dump($total);
dump($totalPrev);
exit();* /
$currentDate = new \DateTime();
$nDelivered = 0;
$nSignaled = 0;
$nDeliveredPrice = 0;
$nSignaledPrice = 0;
foreach ($total as $item) {
$isDone = $item[0]['isDone'];
$price = $item[0]['price'];
$signaledDate = $item[0]['signaledDate'];
if ($isDone) {
$nDelivered ++;
$nDeliveredPrice = $nDeliveredPrice + $price;
}
if (!$isDone && $signaledDate != null && $signaledDate->format('Y-m') === $currentDate->format('Y-m')) {
//dump($signaledDate, $signaledDate->format('Y-m'));
//echo ($item[0]['id']).'<br>';
$nSignaled ++;
$nSignaledPrice = $nSignaledPrice + $price;
}
}
$totalPrice = $nDeliveredPrice + $nSignaledPrice;
/*
$nDeliveredPrev = 0;
$nSignaledPrev = 0;
$nDeliveredPricePrev = 0;
$nSignaledPricePrev = 0;
foreach ($totalPrev as $item) {
$isDone = $item[0]['isDone'];
$price = $item[0]['price'];
$signaledDate = $item[0]['signaledDate'];
if ($isDone) {
$nDeliveredPrev ++;
$nDeliveredPricePrev = $nDeliveredPricePrev + $price;
}
if (!$isDone && $signaledDate != null && $signaledDate->format('Y-m') === $currentDate->format('Y-m')) {
//echo ($item[0]['id']).'<br>';
$nSignaledPrev ++;
$nSignaledPricePrev = $nSignaledPricePrev + $price;
}
}
$totalPricePrev = $nDeliveredPricePrev + $nSignaledPricePrev;
//exit();
$nDeliveredVar = $this->getVariation($nDelivered,$nDeliveredPrev);
$nSignaledVar = $this->getVariation($nSignaled, $nSignaledPrev);
$nDeliveredPriceVar = $this->getVariation($nDeliveredPrice, $nDeliveredPricePrev);
$nSignaledPriceVar = $this->getVariation($nSignaledPrice, $nSignaledPricePrev);
$totalPriceVar = $this->getVariation($totalPrice, $totalPricePrev);
* /
$statisticsPrev1 = $this->getStatistics($totalPrev1, $nDelivered, $nSignaled, $nDeliveredPrice, $nSignaledPrice);
//dump($statisticsPrev1); exit();
$statisticsPrev2 = $this->getStatistics($totalPrev2, $statisticsPrev1['nDelivered'], $statisticsPrev1['nSignaled'], $statisticsPrev1['nDeliveredPrice'], $statisticsPrev1['nSignaledPrice']);
$statisticsPrev3 = $this->getStatistics($totalPrev3, $statisticsPrev2['nDelivered'], $statisticsPrev2['nSignaled'], $statisticsPrev2['nDeliveredPrice'], $statisticsPrev2['nSignaledPrice']);
$statisticsPrev4 = $this->getStatistics($totalPrev4, $statisticsPrev3['nDelivered'], $statisticsPrev3['nSignaled'], $statisticsPrev3['nDeliveredPrice'], $statisticsPrev3['nSignaledPrice']);
$statisticsPrev5 = $this->getStatistics($totalPrev5, $statisticsPrev4['nDelivered'], $statisticsPrev4['nSignaled'], $statisticsPrev4['nDeliveredPrice'], $statisticsPrev4['nSignaledPrice']);
$statisticsPrev6 = $this->getStatistics($totalPrev6, $statisticsPrev5['nDelivered'], $statisticsPrev5['nSignaled'], $statisticsPrev5['nDeliveredPrice'], $statisticsPrev5['nSignaledPrice']);
dump($statisticsPrev1);
dump($statisticsPrev2);
dump($statisticsPrev3);
dump($statisticsPrev4);
dump($statisticsPrev5);
dump($statisticsPrev6); exit(); //*/
/*---- [BEGIN] ----*/
$availableVehicles = $carRepository->createQueryBuilder('c')
//->select('COUNT(c.id)') // ← campo a sumar
->select('c') // ← campo a sumar
->where('c.id > :id')
->setParameter('id', '0')
->andWhere('c.status like :status')
->setParameter(':status', "%entered%")
->andWhere('c.status != \'sold\'')
->getQuery()
//->getSingleScalarResult();
->getArrayResult();
$availableVehiclesPrice = [];
foreach ($availableVehicles as $item) {
$currency = $item['priceCurrencySale'];
$price = is_numeric($item['priceSale']) ? (int)$item['priceSale'] : 0;
if (!empty($price)) {
if (isset($availableVehiclesPrice[$currency])) {
$availableVehiclesPrice[$currency] = (int)$availableVehiclesPrice[$currency] + $price;
} else {
$availableVehiclesPrice[$currency] = $price;
}
}
}
/*---- [END] ----*/
return $this->render('home/index.html.twig', [
'controller_name' => 'HomeController',
/*'delivered' => $nDelivered,
'signaled' => $nSignaled,
'deliveredPrice' => $nDeliveredPrice,
'signaledPrice' => $nSignaledPrice,
'totalPrice' => $totalPrice,
'deliveredPrev' => $nDeliveredPrev,
'signaledPrev' => $nSignaledPrev,
'deliveredPricePrev' => $nDeliveredPricePrev,
'signaledPricePrev' => $nSignaledPricePrev,
'totalPricePrev' => $totalPricePrev,
'deliveredVar' => $nDeliveredVar,
'signaledVar' => $nSignaledVar,
'deliveredPriceVar' => $nDeliveredPriceVar,
'signaledPriceVar' => $nSignaledPriceVar,
'totalPriceVar' => $totalPriceVar,
*/
'availableVehicles' => count($availableVehicles),
'availableVehiclesPrice' => $availableVehiclesPrice,
'currentMenu' => 'homepage',
]);
}
/**
* @Route("/getToDeliver", name="get_to_deliver", methods={"GET", "POST"})
*/
public function getToDeliver(CarSaleRepository $carSaleRepository): jsonResponse
{
/*
$data = $carSaleRepository->createQueryBuilder('cs')
->leftJoin('cs.carSale', 'c')
->leftJoin('cs.carSaleId', 'c')
->addSelect('c')
->where('cs.id > :id')
->setParameter('id', '0')
->andWhere('MONTH(cs.isDoneDate) = MONTH(CURRENT_DATE())')
->andWhere('YEAR(cs.isDoneDate) = YEAR(CURRENT_DATE())')
->andWhere('cs.isDone = 0')
->getQuery()
->getArrayResult();
*/
/*
$data = $carSaleRepository->createQueryBuilder('cs')
->leftJoin('cs.carSale', 'c')
->leftJoin('cs.carPayment', 'cscp')
->leftJoin('cs.bankCheckId', 'csb')
->leftJoin('cscp.car', 'cp')
->leftJoin('cs.user', 'u')
->leftJoin('cs.client', 'cl')
->addSelect('c')
->addSelect('cscp')
->addSelect('csb')
->addSelect('cp')
->addSelect('u')
->addSelect('cl')
->where('cs.id > :id')
->setParameter('id', '0');
*/
$data = $carSaleRepository->createQueryBuilder('cs')
->leftJoin('cs.carSale', 'c')
->addSelect('c')
->where('cs.id > :id')
->setParameter('id', '0')
->andWhere('MONTH(cs.isDoneDate) = MONTH(CURRENT_DATE())')
->andWhere('YEAR(cs.isDoneDate) = YEAR(CURRENT_DATE())')
->andWhere('cs.isDone = 0')
->getQuery()
->getArrayResult();
//dump($data); exit();
$aColors = ['#FF5733', '#33C1FF', '#75FF33', '#FF33D4'];
$colorIndex = 0;
$totalColors = count($aColors);
$aRecords = [];
foreach ($data as $item) {
$aRecords[] = [
'title' => $item['carSale']['patent'],
'start' => $item['isDoneDate']->format('Y-m-d'),
'color' => $aColors[$colorIndex],
'description' => $item['carSale']['name']
];
$colorIndex = ($colorIndex + 1) % $totalColors;
}
//dump($aRecords); exit();
/*$data = [
[
'title' => 'Etiqueta A1',
'start' => '2025-05-05',
'color' => '#28a745' // verde
]
];*/
return new JsonResponse($aRecords, JsonResponse::HTTP_OK);
}
public function getVariation($current, $prev)
{
if ($prev == 0) {
return $current == 0 ? 0 : INF; // o "N/A"
}
$variation = (($current - $prev) / $prev) * 100;
return round($variation, 2);
}
public function convertMonth($month)
{
$monthLabels = [
'01' => 'Enero',
'02' => 'Febrero',
'03' => 'Marzo',
'04' => 'Abril',
'05' => 'Mayo',
'06' => 'Junio',
'07' => 'Julio',
'08' => 'Agosto',
'09' => 'Septiembre',
'10' => 'Octubre',
'11' => 'Noviembre',
'12' => 'Diciembre',
];
return $monthLabels[$month];
}
public function getStatisticsOld($totalPrev, $nDelivered, $nSignaled, $nDeliveredPrice, $nSignaledPrice)
{
$currentDate = new \DateTime();
$nDeliveredPrev = 0;
$nSignaledPrev = 0;
$nDeliveredPricePrev = 0;
$nSignaledPricePrev = 0;
foreach ($totalPrev as $item) {
$isDone = $item[0]['isDone'];
$price = $item[0]['price'];
$signaledDate = $item[0]['signaledDate'];
if ($isDone) {
$nDeliveredPrev ++;
$nDeliveredPricePrev = $nDeliveredPricePrev + $price;
}
if (!$isDone && $signaledDate != null && $signaledDate->format('Y-m') === $currentDate->format('Y-m')) {
//echo ($item[0]['id']).'<br>';
$nSignaledPrev ++;
$nSignaledPricePrev = $nSignaledPricePrev + $price;
}
}
return [
'nDelivered' => $nDeliveredPrev,
'nSignaled' => $nSignaledPrev,
'nDeliveredPrice' => $nDeliveredPricePrev,
'nSignaledPrice' => $nSignaledPricePrev,
'nDeliveredVar' => $this->getVariation($nDelivered,$nDeliveredPrev),
'nSignaledVar' => $this->getVariation($nSignaled, $nSignaledPrev),
'nDeliveredPriceVar' => $this->getVariation($nDeliveredPrice, $nDeliveredPricePrev),
'nSignaledPriceVar' => $this->getVariation($nSignaledPrice, $nSignaledPricePrev),
'totalPriceVar' => $this->getVariation($nDeliveredPrice + $nSignaledPrice, $nDeliveredPricePrev + $nSignaledPricePrev)
];
}
/*
* Si no se específica $numberMonths toma por defecto el valor "1" (mes actual)
* Si el valor de $numberMonths es mayor a 1 se busca el mes actual y los meses anteriores especificados
*/
public function getSalesStatistics($doctrine, $numberMonths = 1)
{
$numberMonths = $numberMonths - 1;
$currentDate = (new \DateTime('last day of this month'))->setTime(0, 0);
$prevDate = (new \DateTime('first day of this month'))->modify('-'.$numberMonths.' months')->setTime(0, 0);
$query = "
SELECT c.name, c.status, cs.car_sale_id, cs.is_done_date, cs.signaled_date, cs.price, cs.currency, cs.is_done
FROM car_sale cs
LEFT JOIN car c ON c.id = cs.car_sale_id
WHERE c.status IN ('sold', 'signaled')
AND is_done_date >= :prevDate AND is_done_date <= :currentDate
"; //exit($query);
$conn = $doctrine->getConnection();
$params = [ 'currentDate' => $currentDate->format('Y-m-d'), 'prevDate' => $prevDate->format('Y-m-d') ];
$result = $conn->executeQuery($query, $params);
$dataCurrentMonth = $result->fetchAll();
$aStatisticsByMonth = [];
$aStatisticsRef = [
'delivered' => 0,
'signaled' => 0,
'deliveredPrice' => [],
'signaledPrice' => []
];
foreach ($dataCurrentMonth as $item) {
$month = (new \DateTime($item['is_done_date']))->format('Y-m');
$isDone = $item['is_done'];
$currency = $item['currency'];
$price = is_numeric($item['price']) ? (int)$item['price'] : 0;
$signaledDate = new \DateTime($item['signaled_date']);
if (!array_key_exists($month, $aStatisticsByMonth)) {
$aStatisticsByMonth[$month] = $aStatisticsRef;
}
if ($isDone) {
$aStatisticsByMonth[$month]['delivered'] ++;
if (!empty($price)) {
if (isset($aStatisticsByMonth[$month]['deliveredPrice'][$currency])) {
$aStatisticsByMonth[$month]['deliveredPrice'][$currency] = (int) $aStatisticsByMonth[$month]['deliveredPrice'][$currency] + $price;
} else {
$aStatisticsByMonth[$month]['deliveredPrice'][$currency] = $price;
}
}
}
if (!$isDone && $signaledDate != null && $signaledDate->format('Y-m') === $currentDate->format('Y-m')) {
$aStatisticsByMonth[$month]['signaled'] ++;
if (!empty($price)) {
if (isset($aStatisticsByMonth[$month]['signaledPrice'][$currency])) {
$aStatisticsByMonth[$month]['signaledPrice'][$currency] = (int) $aStatisticsByMonth[$month]['signaledPrice'][$currency] + $price;
} else {
$aStatisticsByMonth[$month]['signaledPrice'][$currency] = $price;
}
}
}
}
$this->formatPriceFields($aStatisticsByMonth, ['deliveredPrice', 'signaledPrice']);
ksort($aStatisticsByMonth);
$this->addDeliveredChange($aStatisticsByMonth);
krsort($aStatisticsByMonth);
return $aStatisticsByMonth;
}
function formatPriceFields(array &$data, array $priceFields, int $decimals = 0, string $decPoint = ',', string $thousandsSep = '.') {
foreach ($data as &$item) {
$totals = [];
foreach ($priceFields as $field) {
if (isset($item[$field]) && is_array($item[$field])) {
foreach ($item[$field] as $currency => $amount) {
if (is_numeric($amount)) {
if (!isset($totals[$currency])) {
$totals[$currency] = 0;
}
$totals[$currency] += $amount;
$item[$field][$currency] = number_format($amount, $decimals, $decPoint, $thousandsSep);
}
}
}
}
// Formatear y asignar totalPrice
foreach ($totals as $currency => $sum) {
$totals[$currency] = number_format($sum, $decimals, $decPoint, $thousandsSep);
}
$item['totalPrice'] = $totals;
}
unset($item); // importante para evitar referencias colgantes
}
function addDeliveredChange(array &$data) {
// Ordenar por clave (suponiendo formato YYYY-MM)
//ksort($data);
$prevDelivered = null;
foreach ($data as $month => &$monthData) {
if ($prevDelivered !== null && is_numeric($prevDelivered) && $prevDelivered > 0) {
$change = (($monthData['delivered'] - $prevDelivered) / $prevDelivered) * 100;
$monthData['deliveredChange'] = round($change, 2); // Ej: +21.43%
} else {
$monthData['deliveredChange'] = null;
}
$prevDelivered = $monthData['delivered'];
}
unset($monthData); // liberar referencia
}
/**
* @Route("/salesStatistics", name="sales_statistics", methods={"GET", "POST"})
*/
public function salesStatistics(ManagerRegistry $doctrine, Request $request): jsonResponse
{
return $this->json( $this->getSalesStatistics($doctrine, $request->get('m')) );
}
}