src/Controller/CarController.php line 35

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Car;
  4. use App\Entity\CarImages;
  5. use App\Entity\CarResale;
  6. use App\Entity\CarSaleBankCheck;
  7. use App\Entity\InfoautoTokens;
  8. use App\Form\CarImagesType;
  9. use App\Form\CarType;
  10. use App\Repository\BranchesRepository;
  11. use App\Repository\CarRepository;
  12. use App\Repository\InfoautoTokensRepository;
  13. use Doctrine\Persistence\ManagerRegistry;
  14. use Symfony\Component\Filesystem\Filesystem;
  15. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  16. use Symfony\Component\HttpFoundation\File\UploadedFile;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\Response;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  21. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  22. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  23. /**
  24.  * @Route("/car")
  25.  */
  26. class CarController extends AbstractController
  27. {
  28.     /**
  29.      * @Route("/indexJson", name="car_index_json", methods={"GET", "POST"})
  30.      */
  31.     public function indexJson(Request $requestCarRepository $entityRepository): Response
  32.     {
  33.         $totalR 0;
  34.         $curPage   $request->get('current');
  35.         $sizePage  $request->get('rowCount');
  36.         $startPage $curPage == : (($curPage 1) * $sizePage) + 1;
  37.         $startPage $curPage == : (($curPage 1) * $sizePage);
  38.         $data $entityRepository->createQueryBuilder('c')
  39.             ->leftJoin('c.brand''b')
  40.             //->leftJoin('c.imageId', 'i')
  41.             ->addSelect('b')
  42.             //->addSelect('b.name AS brand_name')
  43.             //->addSelect('i')
  44.             ->where('c.id > :id')
  45.             ->setParameter('id''0');
  46.         /*---- Filters [START] ----*/
  47.         $search $request->get('searchPhrase');
  48.         $status $request->get('status');
  49.         $destination $request->get('destination');
  50.         if (!empty($search)) {
  51.             $data $data->andWhere('c.name like :search')
  52.                 ->orWhere('c.year like :search')
  53.                 ->orWhere('c.km like :search')
  54.                 ->orWhere('c.patent like :search')
  55.                 ->orWhere('c.pricePurchase like :search')
  56.                 ->orWhere('c.priceSale like :search')
  57.                 ->orWhere('b.name like :search')
  58.                 ->setParameter(':search'"%$search%");
  59.         }
  60.         if (!empty($status)) {
  61.             if (is_array($status)) {
  62.                 $status array_filter($status, fn($v) => $v !== '');
  63.             }
  64.             if (!empty($status)) {
  65.                 if (is_array($status)) {
  66.                     $data $data->andWhere('c.status IN (:statuses)')
  67.                         ->setParameter('statuses'$status);
  68.                 } else {
  69.                     $data $data->andWhere('c.status = :status')
  70.                         ->setParameter('status'$status);
  71.                 }
  72.             }
  73.         }
  74.         if ($destination != '') {
  75.             $data $data->andWhere('c.destination = :destination')
  76.                 ->setParameter(':destination'$destination);
  77.         }
  78.         /*---- Filters [END] ----*/
  79.         $data $data->orderBy('b.name''ASC')
  80.             ->addOrderBy('c.name''ASC');
  81.         $total $data->getQuery()
  82.             ->getArrayResult();
  83.         $data $data->setFirstResult($startPage)
  84.             ->setMaxResults($sizePage)
  85.             ->getQuery()
  86.             //->getSQL();
  87.             ->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNStrue)
  88.             ->getArrayResult();
  89.         //dump($data); exit();
  90.         $json_data = array(
  91.             "current" => intval($curPage),
  92.             "rowCount" => $sizePage,
  93.             "total" => count($total),
  94.             "rows" => $data,
  95.         );
  96.         return $this->json($json_data);
  97.     }
  98.     /**
  99.      * @Route("/excel", name="car_excel", methods={"GET"})
  100.      */
  101.     public function excel(Request $requestCarRepository $entityRepository): Response
  102.     {
  103.         $qb $entityRepository->createQueryBuilder('c')
  104.             ->leftJoin('c.brand''b')
  105.             ->addSelect('b')
  106.             ->where('c.id > 0');
  107.         /*---- Filters [START] ----*/
  108.         $search $request->get('searchPhrase');
  109.         $status $request->get('status'); 
  110.         $destination $request->get('destination');
  111.         if (!empty($search)) {
  112.             $expr $qb->expr()->orX(
  113.                 $qb->expr()->like('c.name'':search'),
  114.                 $qb->expr()->like('c.year'':search'),
  115.                 $qb->expr()->like('c.km'':search'),
  116.                 $qb->expr()->like('c.patent'':search'),
  117.                 $qb->expr()->like('c.pricePurchase'':search'),
  118.                 $qb->expr()->like('c.priceSale'':search'),
  119.                 $qb->expr()->like('b.name'':search')
  120.             );
  121.             $qb->andWhere($expr)
  122.             ->setParameter('search'"%$search%");
  123.         }
  124.         if (!empty($status)) {
  125.             if (!is_array($status)) {
  126.                 $status explode(','$status);
  127.             }
  128.             $status array_values(array_filter($status, static fn ($value) => $value !== ''));
  129.             if (!empty($status)) {
  130.                 if (count($status) > 1) {
  131.                     $qb->andWhere('c.status IN (:statuses)')
  132.                         ->setParameter('statuses'$status);
  133.                 } else {
  134.                     $qb->andWhere('c.status = :status')
  135.                         ->setParameter('status'$status[0]);
  136.                 }
  137.             }
  138.         }
  139.         if (!empty($destination)) {
  140.             $qb->andWhere('c.destination = :destination')
  141.             ->setParameter('destination'$destination);
  142.         }
  143.         /*---- Filters [END] ----*/
  144.         $qb->orderBy('b.name''ASC')
  145.         ->addOrderBy('c.name''ASC');
  146.         $data $qb->getQuery()
  147.             ->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNStrue)
  148.             ->getArrayResult();
  149.         // Crear Excel
  150.         $spreadsheet = new Spreadsheet();
  151.         $sheet $spreadsheet->getActiveSheet();
  152.         $sheet->setTitle('Vehículos');
  153.         // Cabeceras
  154.         $headers = ['Vehículo','Marca','Año','Kilómetros','Patente','Precio Compra','Precio Venta','Estado','Ubicación'];
  155.         foreach ($headers as $col => $header) {
  156.             $sheet->setCellValueByColumnAndRow($col+11$header);
  157.             $sheet->getColumnDimensionByColumn($col+1)->setAutoSize(true);
  158.         }
  159.         $sheet->getStyle('A1:I1')
  160.             ->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
  161.             ->getStartColor()->setRGB('dedede');
  162.         // Datos
  163.         $row 2;
  164.         foreach ($data as $item) {
  165.             $statusLabel = match ($item['status']) {
  166.                 'entered'  => 'Ingresados',
  167.                 'to enter' => 'Por Ingresar',
  168.                 'signaled' => 'Señados',
  169.                 default    => '',
  170.             };
  171.             $sheet->setCellValue("A$row"$item['name']);
  172.             $sheet->setCellValue("B$row"$item['brand']['name']);
  173.             $sheet->setCellValue("C$row"$item['year']);
  174.             $sheet->setCellValue("D$row"$item['km']);
  175.             $sheet->setCellValue("E$row"$item['patent']);
  176.             $sheet->setCellValue("F$row"$item['priceCurrencyPurchase'].$item['pricePurchase']);
  177.             $sheet->setCellValue("G$row"$item['priceCurrencySale'].$item['priceSale']);
  178.             $sheet->setCellValue("H$row"$statusLabel);
  179.             $sheet->setCellValue("I$row"$item['destination'] ?? '');
  180.             $row++;
  181.         }
  182.         // Descargar
  183.         $writer = new Xlsx($spreadsheet);
  184.         $fileName 'Vehículos.xlsx';
  185.         $temp_file tempnam(sys_get_temp_dir(), $fileName);
  186.         $writer->save($temp_file);
  187.         return $this->file($temp_file$fileNameResponseHeaderBag::DISPOSITION_INLINE);
  188.     }
  189.     /**
  190.      * @Route("/excel-admin", name="car_excel_admin", methods={"GET"})
  191.      */
  192.     public function excelAdmin(Request $requestCarRepository $entityRepository): Response
  193.     {
  194.         $qb $entityRepository->createQueryBuilder('c')
  195.             ->leftJoin('c.brand''b')
  196.             ->addSelect('b')
  197.             ->leftJoin('c.destination''d')
  198.             ->addSelect('d')
  199.             ->where('c.id > 0');
  200.         /*---- Filters [START] ----*/
  201.         $search $request->get('searchPhrase');
  202.         $status $request->get('status');
  203.         $destination $request->get('destination');
  204.         if (!empty($search)) {
  205.             $expr $qb->expr()->orX(
  206.                 $qb->expr()->like('c.name'':search'),
  207.                 $qb->expr()->like('c.year'':search'),
  208.                 $qb->expr()->like('c.km'':search'),
  209.                 $qb->expr()->like('c.patent'':search'),
  210.                 $qb->expr()->like('c.pricePurchase'':search'),
  211.                 $qb->expr()->like('c.priceSale'':search'),
  212.                 $qb->expr()->like('b.name'':search'),
  213.             );
  214.             $qb->andWhere($expr)
  215.             ->setParameter('search'"%$search%");
  216.         }
  217.         if (!empty($status)) {
  218.             if (!is_array($status)) {
  219.                 $status explode(','$status);
  220.             }
  221.             $status array_values(array_filter($status, static fn ($value) => $value !== ''));
  222.             if (!empty($status)) {
  223.                 if (count($status) > 1) {
  224.                     $qb->andWhere('c.status IN (:statuses)')
  225.                         ->setParameter('statuses'$status);
  226.                 } else {
  227.                     $qb->andWhere('c.status = :status')
  228.                         ->setParameter('status'$status[0]);
  229.                 }
  230.             }
  231.         }
  232.         if (!empty($destination)) {
  233.             $qb->andWhere('c.destination = :destination')
  234.             ->setParameter('destination'$destination);
  235.         }
  236.         /*---- Filters [END] ----*/
  237.         $qb->orderBy('b.name''ASC')
  238.         ->addOrderBy('c.name''ASC');
  239.         $data $qb->getQuery()
  240.             ->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNStrue)
  241.             ->getArrayResult();
  242.         // Crear Excel
  243.         $spreadsheet = new Spreadsheet();
  244.         $sheet $spreadsheet->getActiveSheet();
  245.         $sheet->setTitle('Vehículos (Admin)');
  246.         // Cabeceras (agregamos Chasis, N° Motor, Fecha ingreso, Estado)
  247.         $headers = [
  248.             'Fecha ingreso','Vehículo','Marca','Año','Kilómetros','Patente','Chasis','N° Motor','Estado',
  249.             'Precio Compra','Precio Venta','Ubicación'
  250.         ];
  251.         foreach ($headers as $col => $header) {
  252.             $sheet->setCellValueByColumnAndRow($col 11$header);
  253.             $sheet->getColumnDimensionByColumn($col 1)->setAutoSize(true);
  254.         }
  255.         $sheet->getStyle('A1:L1')
  256.             ->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
  257.             ->getStartColor()->setRGB('dedede');
  258.         // Datos
  259.         $row 2;
  260.         foreach ($data as $item) {
  261.             $statusLabel = match ($item['status'] ?? null) {
  262.                 'entered'  => 'Ingresados',
  263.                 'to enter' => 'Por Ingresar',
  264.                 'signaled' => 'Señados',
  265.                 default    => '',
  266.             };
  267.             $createdAt '';
  268.             if (!empty($item['createdAt'])) {
  269.                 if ($item['createdAt'] instanceof \DateTimeInterface) {
  270.                     $createdAt $item['createdAt']->format('d/m/Y H:i');
  271.                 } elseif (is_string($item['createdAt'])) {
  272.                     $createdAt \DateTime::createFromFormat('Y-m-d H:i:s'$item['createdAt']);
  273.                     if ($createdAt !== false) {
  274.                         $createdAt $createdAt->format('d/m/Y H:i');
  275.                     } else {
  276.                         $createdAt $item['createdAt'];
  277.                     }
  278.                 }
  279.             }
  280.             $sheet->setCellValue("A$row",  $createdAt);
  281.             $sheet->setCellValue("B$row",  $item['name'] ?? '');
  282.             $sheet->setCellValue("C$row",  $item['brand']['name'] ?? '');
  283.             $sheet->setCellValue("D$row",  $item['year'] ?? '');
  284.             $sheet->setCellValue("E$row",  $item['km'] ?? '');
  285.             $sheet->setCellValue("F$row",  $item['patent'] ?? '');
  286.             $sheet->setCellValue("G$row",  $item['chassisNumber'] ?? '');
  287.             $sheet->setCellValue("H$row",  $item['engineNumber'] ?? '');
  288.             $sheet->setCellValue("I$row",  $statusLabel);
  289.             $sheet->setCellValue("J$row",  $item['pricePurchase'] ?? '');
  290.             $sheet->setCellValue("K$row",  $item['priceSale'] ?? '');
  291.             $sheet->setCellValue("L$row",  $item['destination']['name'] ?? '');
  292.             $row++;
  293.         }
  294.         $writer = new Xlsx($spreadsheet);
  295.         $fileName 'Vehiculos-Administracion.xlsx';
  296.         $temp_file tempnam(sys_get_temp_dir(), $fileName);
  297.         $writer->save($temp_file);
  298.         return $this->file($temp_file$fileNameResponseHeaderBag::DISPOSITION_INLINE);
  299.     }
  300.     /**
  301.      * @Route("/carList", name="car_list", methods={"GET", "POST"})
  302.      */
  303.     public function carList(Request $requestCarRepository $entityRepository): Response
  304.     {
  305.         $list '<option value=""></option>';
  306.         $data $entityRepository->findAll();
  307.         foreach ($data as $item) {
  308.             $list .= '<option value="'.$item->getId().'">'.$item->getName().' ('.$item->getPatent().')</option>';
  309.         }
  310.         return new Response($list);
  311.     }
  312.     /**
  313.      * @Route("/carSavePrices", name="car_save_prices", methods={"GET", "POST"})
  314.      */
  315.     public function carSavePrices(Request $requestCarRepository $entityRepository): Response
  316.     {
  317.         $type $request->get('type');
  318.         $data $request->get('data');
  319.         $percent = ($request->get('percent') / 100) + 1;
  320.         $user $this->getUser();
  321.         $userId $user instanceof \App\Entity\User $user->getId() : null;
  322.         //dump($data); exit();
  323.         /*if ($percent == 100) {
  324.             $percent = 2;
  325.         } else {
  326.             $percent = '1.'.$percent/100;
  327.         }*/
  328.         $db $this->getDoctrine()->getManager()->getConnection();
  329.         $db->connect();
  330.         if ($type == 'all') {
  331.             try {
  332.                 $query "
  333.                     UPDATE car 
  334.                     SET price_sale = price_sale * $percent,
  335.                         updated_at = NOW(),
  336.                         updated_by_id = :userId
  337.                     WHERE status = 'entered'
  338.                 "//exit($query);
  339.                 $stmt $db->prepare($query);
  340.                 $stmt->bindValue('userId'$userId);
  341.                 $stmt->execute();
  342.                 $status 'success';
  343.                 $message 'Updated price all vehicles';
  344.             } catch (\Exception $e) {
  345.                 $status 'error';
  346.                 $message $e->getMessage();
  347.             }
  348.         } else if ($type == 'selected') {
  349.             try {
  350.                 $data implode(','$data);
  351.                 $query "
  352.                     UPDATE car 
  353.                     SET price_sale = price_sale * $percent,
  354.                         updated_at = NOW(),
  355.                         updated_by_id = :userId
  356.                     WHERE status = 'entered'
  357.                     AND id in ($data)
  358.                 ";
  359.                 $stmt $db->prepare($query);
  360.                 $stmt->bindValue('userId'$userId);
  361.                 $stmt->execute();
  362.                 $status 'success';
  363.                 $message 'Updated price selected vehicles';
  364.             } catch (\Exception $e) {
  365.                 $status 'error';
  366.                 $message $e->getMessage();
  367.             }
  368.         } else {
  369.             foreach ($data as $key => $value) {
  370.                 try {
  371.                     $vehicle $entityRepository->find($key);
  372.                     $vehicle->setPriceSale($value);
  373.                     if ($vehicle->getPriceCurrencySale() == null){
  374.                         $vehicle->setPriceCurrencySale('$');
  375.                     }
  376.                     $user $this->getUser();
  377.                     if ($user instanceof \App\Entity\User) {
  378.                         $vehicle->setUpdatedBy($user);
  379.                     }
  380.                     $this->getDoctrine()->getManager()->persist($vehicle);
  381.                     $this->getDoctrine()->getManager()->flush();
  382.                     $status 'success';
  383.                     $message 'Updated manual price of selected vehicles';
  384.                 } catch (\Exception $e) {
  385.                     $status 'error';
  386.                     $message $e->getMessage();
  387.                 }
  388.             }
  389.         }
  390.         $response = array(
  391.             'status' => $status,
  392.             'message' => $message,
  393.         );
  394.         return $this->json($response);
  395.     }
  396.     /**
  397.      * @Route("/", name="car_index", methods={"GET"})
  398.      */
  399.     public function index(ManagerRegistry $doctrine): Response
  400.     {
  401.         $query "
  402.             SELECT id, name
  403.             FROM branches
  404.             ORDER BY name ASC
  405.         ";
  406.         $conn $doctrine->getConnection();
  407.         $result $conn->executeQuery($query);
  408.         $branches  $result->fetchAllKeyValue();
  409.         $query "
  410.             SELECT id, name
  411.             FROM destinations
  412.             ORDER BY name ASC
  413.         ";
  414.         $conn $doctrine->getConnection();
  415.         $result $conn->executeQuery($query);
  416.         $destinations  $result->fetchAllKeyValue();
  417.         return $this->render('car/index.html.twig', [
  418.             'currentMenu' => 'car',
  419.             'branches' => $branches,
  420.             'destinations' => $destinations,
  421.         ]);
  422.     }
  423.     /**
  424.      * @Route("/indexSetPrices", name="car_index_set_prices", methods={"GET"})
  425.      */
  426.     public function indexSetPrices(): Response
  427.     {
  428.         return $this->render('car/index_set_prices.html.twig', [
  429.             'currentMenu' => 'car',
  430.         ]);
  431.     }
  432.     /**
  433.      * @Route("/new/modal", name="car_new_modal", methods={"GET","POST"})
  434.      */
  435.     public function newModal(Request $request): Response
  436.     {
  437.         $car = new Car();
  438.         $car->setStatus('to enter');
  439.         $form $this->createForm(CarType::class, $car);
  440.         $form->handleRequest($request);
  441.         if ($form->isSubmitted() && $form->isValid()) {
  442.             $this->attachUploadedImages($request$car);
  443.             $this->syncImagesCollection($car);
  444.             $entityManager $this->getDoctrine()->getManager();
  445.             $entityManager->persist($car);
  446.             try {
  447.                 $entityManager->flush();
  448.                 $status  'success';
  449.                 $message 'New car created';
  450.                 $carId   $car->getId();
  451.                 $carName $car->getName();
  452.                 $carPatent     $car->getPatent();
  453.                 $carPricePur   $car->getPricePurchase();
  454.                 $carPriceCuPur $car->getPriceCurrencyPurchase();
  455.             } catch (\Exception $e) {
  456.                 $status  'error';
  457.                 $message $e->getMessage();
  458.                 $carId   0;
  459.                 $carName 0;
  460.                 $carPatent     '';
  461.                 $carPricePur   0;
  462.                 $carPriceCuPur '$';
  463.             }
  464.             $response = array(
  465.                 'status' => $status,
  466.                 'message' => $message,
  467.                 'carId' => $carId,
  468.                 'carName' => $carName,
  469.                 'carPatent' => $carPatent,
  470.                 'carPricePur' => $carPricePur,
  471.                 'carPriceCuPur' => $carPriceCuPur,
  472.             );
  473.             return $this->json($response);
  474.         }
  475.         return $this->render('car/new_modal.html.twig', [
  476.             'car' => $car,
  477.             'form' => $form->createView(),
  478.             'm' => $request->get('m'),
  479.             'currentMenu' => 'car_new_modal',
  480.         ]);
  481.     }
  482.     /**
  483.      * @Route("/new", name="car_new", methods={"GET","POST"})
  484.      */
  485.     public function new(Request $request): Response
  486.     {
  487.         $car = new Car();
  488.         $form $this->createForm(CarType::class, $car);
  489.         $form->handleRequest($request);
  490.         if ($form->isSubmitted() && $form->isValid()) {
  491.             $this->attachUploadedImages($request$car);
  492.             $this->syncImagesCollection($car);
  493.             $entityManager $this->getDoctrine()->getManager();
  494.             $entityManager->persist($car);
  495.             $entityManager->flush();
  496.             return $this->redirectToRoute('car_index', [], Response::HTTP_SEE_OTHER);
  497.         }
  498.         return $this->render('car/new.html.twig', [
  499.             'car' => $car,
  500.             'form' => $form->createView(),
  501.             'currentMenu' => 'car',
  502.         ]);
  503.     }
  504.     /**
  505.      * @Route("/{id}", name="car_show", methods={"GET"})
  506.      */
  507.     public function show(Car $car): Response
  508.     {
  509.         //dump($car->getImageId());
  510.         //exit();
  511.         return $this->render('car/show.html.twig', [
  512.             'car' => $car,
  513.             'currentMenu' => 'car',
  514.         ]);
  515.     }
  516.     /**
  517.      * @Route("/{id}/modal", name="car_show_modal", methods={"GET"})
  518.      */
  519.     public function showModal(Car $car): Response
  520.     {
  521.          return $this->render('car/show_modal.html.twig', [
  522.             'car' => $car,
  523.             'currentMenu' => 'car',
  524.         ]);
  525.     }
  526.     /**
  527.      * @Route("/{id}/modal/getPrice", name="car_get_price_modal", methods={"GET"})
  528.      */
  529.     public function getPriceModal(ManagerRegistry $doctrineCar $carInfoautoTokensRepository $infoautoTokens): Response
  530.     {
  531.         $modelName 'no_model_found';
  532.         $data['brand'] = $car->getBrand()->getName();
  533.         $data['brandId'] = $car->getBrand()->getInfoautoId();
  534.         $data['modelName'] = explode(' '$car->getName());
  535.         $data['modelYear'] = $car->getYear();
  536.         $dataJson json_decode(file_get_contents$this->getParameter('kernel.project_dir').'/public/brands-groups.json' ), true);
  537.         /*---- Buscar grupo del vehículo [BEGIN] ----*/
  538.         // Buscar por marca
  539.         $foundBrand null;
  540.         foreach ($dataJson as $brand) {
  541.             if ($brand['id'] == $data['brandId']) {
  542.                 $foundBrand $brand;
  543.                 break; // Terminamos la búsqueda cuando lo encontramos
  544.             }
  545.         }
  546.         if ($foundBrand) {
  547.             $modelName $data['modelName'][0];
  548.             // Buscar dentro de "groups" por modelo
  549.             $foundGroup null;
  550.             foreach ($foundBrand['groups'] as $group) {
  551.                 if ($group['name'] == $modelName) {
  552.                     $foundGroup $group;
  553.                     break;
  554.                 }
  555.             }
  556.             // Mostrar resultados
  557.             if ($foundGroup) {
  558.                 $data['status'] = 'ok';
  559.                 $data['type'] = 'model';
  560.                 $data['message'] = 'Modelo encontrado';
  561.                 $data['data'] = $foundGroup;
  562.             } else {
  563.                 $data['status'] = 'error';
  564.                 $data['type'] = 'model';
  565.                 $data['message'] = 'No se encontró el modelo';
  566.             }
  567.         } else {
  568.             $data['status'] = 'error';
  569.             $data['type'] = 'brand';
  570.             $data['message'] = 'No se encontró la marca';
  571.         }
  572.         /*---- Buscar grupo del vehículo [END] ----*/
  573.         if ($data['status'] == 'error' && $data['type'] == 'brand') {
  574.             echo '<h3>'.$data['message'].'</h3>';
  575.             exit();
  576.         }
  577.         if ($data['status'] == 'error' && $data['type'] == 'model' && $data['brandId'] == '118') {
  578.             if ($foundBrand) {
  579.                 if ( str_starts_with(strtolower($data['modelName'][0]), 'd') || str_starts_with(strtolower($data['modelName'][0]), 'x') ) {
  580.                     $modelName substr($data['modelName'][0], 01).' '.substr($data['modelName'][0], 1);
  581.                 }
  582.                 // Buscar dentro de "groups" por modelo
  583.                 $foundGroup null;
  584.                 foreach ($foundBrand['groups'] as $group) {
  585.                     //echo $group['name'].' ; '.$modelName.'<br>';
  586.                     if ( $group['name'] == $modelName ) {
  587.                         $foundGroup $group;
  588.                         break;
  589.                     }
  590.                 }
  591.                 // Mostrar resultados
  592.                 if ($foundGroup) {
  593.                     $data['status'] = 'ok';
  594.                     $data['type'] = 'model';
  595.                     $data['message'] = 'Modelo encontrado';
  596.                     $data['data'] = $foundGroup;
  597.                 } else {
  598.                     $data['status'] = 'error';
  599.                     $data['type'] = 'model';
  600.                     $data['message'] = 'No se encontró el modelo (code 2)';
  601.                 }
  602.             }
  603.             //echo '<h3>'.$data['message'].'</h3>';
  604.             //exit();
  605.         }
  606.         if ($data['status'] == 'error' && $data['type'] == 'model') {
  607.             echo '<h3>'.$data['message'].'</h3>';
  608.             exit();
  609.         }
  610.         $token $this->getInfoautoToken($doctrine$infoautoTokens);
  611.         // Define los encabezados necesarios
  612.         $headers = [
  613.             'Authorization: Bearer '.$token,
  614.         ];
  615.         /*---- Buscar modelos por año [BEGIN] ----*/
  616.         $curl curl_init();
  617.         curl_setopt_array($curl, array(
  618.             //CURLOPT_URL => 'https://api.infoauto.com.ar/cars/pub/search?query_string=Audi',
  619.             CURLOPT_URL => 'https://api.infoauto.com.ar/cars/pub//brands/'.$data['brandId'].'/groups/'.$data['data']['id'].'/models?query_string='.$data['modelName'][1].'&prices=true&prices_from='.$data['modelYear'].'&prices_to='.$data['modelYear'],
  620.             CURLOPT_RETURNTRANSFER => true,
  621.             CURLOPT_ENCODING => '',
  622.             CURLOPT_MAXREDIRS => 10,
  623.             CURLOPT_TIMEOUT => 0,
  624.             CURLOPT_FOLLOWLOCATION => true,
  625.             CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  626.             CURLOPT_CUSTOMREQUEST => 'GET',
  627.             CURLOPT_HTTPHEADER => $headers,   // Encabezados de la petición
  628.             CURLOPT_SSL_VERIFYPEER => false,
  629.             CURLOPT_SSL_VERIFYHOST => false,
  630.         ));
  631.         $response curl_exec($curl);
  632.         curl_close($curl);
  633.         // Verifica si ocurrió un error de cURL
  634.         if ($response === false) {
  635.             $error curl_error($curl);
  636.             curl_close($curl);
  637.             die("Error en cURL: $error");
  638.         }
  639.         // Obtiene el código HTTP de la respuesta
  640.         $httpCode curl_getinfo($curlCURLINFO_HTTP_CODE);
  641.         $modelsJson json_decode($responsetrue);
  642.         /*---- Buscar modelos por año [END] ----*/
  643.         //dump($modelsJson); exit();
  644.         /*---- Buscar precios [BEGIN] ----*/
  645.         // Recopilar CODIA
  646.         $aCodia null;
  647.         foreach ($modelsJson as $item) {
  648.             $aCodia[] = ['name' => $item['description'], 'codia' => $item['codia']];
  649.         }
  650.         if ($aCodia) {
  651.             // Buscar precios por CODIA
  652.             foreach ($aCodia as $key => $item) {
  653.                 curl_setopt_array($curl, array(
  654.                     //CURLOPT_URL => 'https://api.infoauto.com.ar/cars/pub/search?query_string=Audi',
  655.                     CURLOPT_URL => 'https://api.infoauto.com.ar/cars/pub/models/'.$item['codia'].'/prices',
  656.                     CURLOPT_RETURNTRANSFER => true,
  657.                     CURLOPT_ENCODING => '',
  658.                     CURLOPT_MAXREDIRS => 10,
  659.                     CURLOPT_TIMEOUT => 0,
  660.                     CURLOPT_FOLLOWLOCATION => true,
  661.                     CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  662.                     CURLOPT_CUSTOMREQUEST => 'GET',
  663.                     CURLOPT_HTTPHEADER => $headers,   // Encabezados de la petición
  664.                     CURLOPT_SSL_VERIFYPEER => false,
  665.                     CURLOPT_SSL_VERIFYHOST => false,
  666.                 ));
  667.                 $response curl_exec($curl);
  668.                 curl_close($curl);
  669.                 $aPrices json_decode($responsetrue);
  670.                 $price 0;
  671.                 foreach ($aPrices as $item2) {
  672.                     if ($item2['year'] == $data['modelYear']) {
  673.                         $price number_format($item2['price'], 0'''.');
  674.                         break;
  675.                     }
  676.                 }
  677.                 $aCodia[$key]['price'] = $price;
  678.             }
  679.             /*---- Buscar precios [END] ----*/
  680.         } else {
  681.             $data['status'] = 'error';
  682.             $data['type'] = 'version';
  683.             $data['message'] = 'No se encontró versión para el modelo';
  684.             echo '<h3>'.$data['message'].'</h3>';
  685.             exit();
  686.         }
  687.         return $this->render('car/get_price_modal.html.twig', [
  688.             'car' => $car,
  689.             'codia' => $aCodia,
  690.             'infoFound' => [ $data['modelName'][0], $data['modelName'][1] ],
  691.             'currentMenu' => 'car',
  692.         ]);
  693.     }
  694.     private function getInfoautoToken(ManagerRegistry $doctrineInfoautoTokensRepository $infoautoTokens)
  695.     {
  696.         $tokenTmp $infoautoTokens->findOneBy([], ['id' => 'DESC'], 1);
  697.         if ($tokenTmp) {
  698.             $hourMore = clone $tokenTmp->getCreatedAt();
  699.             $hourMore = ($hourMore)->add(new \DateInterval('PT1H'));
  700.             if (new \DateTime() > $hourMore) {
  701.                 $tokenOk false;
  702.             } else {
  703.                 $tokenOk true;
  704.             }
  705.         } else {
  706.             $tokenOk false;
  707.         }
  708.         if ($tokenOk) {
  709.             return $tokenTmp->getAccessToken();
  710.         } else {
  711.             $headers = [
  712.                 'Content-Type: application/json',
  713.                 'Authorization: Basic 'base64_encode('rwaybar@yahoo.com.ar:NQlv38cCxODlq42f'),
  714.                 'Content-Length: 0'
  715.             ];
  716.             $curl curl_init();
  717.             curl_setopt_array($curl, array(
  718.                 CURLOPT_URL => 'https://api.infoauto.com.ar/cars/auth/login',
  719.                 CURLOPT_RETURNTRANSFER => true,
  720.                 CURLOPT_ENCODING => '',
  721.                 CURLOPT_MAXREDIRS => 10,
  722.                 CURLOPT_TIMEOUT => 0,
  723.                 CURLOPT_FOLLOWLOCATION => true,
  724.                 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  725.                 CURLOPT_CUSTOMREQUEST => 'POST',
  726.                 CURLOPT_HTTPHEADER => $headers,   // Encabezados de la petición
  727.                 CURLOPT_SSL_VERIFYPEER => false,
  728.                 CURLOPT_SSL_VERIFYHOST => false,
  729.             ));
  730.             $response curl_exec($curl);
  731.             curl_close($curl);
  732.             // Verifica si ocurrió un error de cURL
  733.             if ($response === false) {
  734.                 $error curl_error($curl);
  735.                 curl_close($curl);
  736.                 die("Error en cURL: $error");
  737.             }
  738.             $json json_decode($response);
  739.             $tokens = new InfoautoTokens();
  740.             $tokens->setAccessToken($json->access_token);
  741.             $tokens->setRefreshToken($json->refresh_token);
  742.             $tokens->setCreatedAt(new \DateTime);
  743.             $doctrine->getManager()->persist($tokens);
  744.             $doctrine->getManager()->flush();
  745.             return $json->access_token;
  746.         }
  747.     }
  748.     /**
  749.      * @Route("/{id}/modalNotificationDeleteVehicle", name="car_modal_notification_delete_vehicle", methods={"GET"})
  750.      */
  751.     public function showModalNotificationDeleteVehicle(Car $car): Response
  752.     {
  753.         $entityManager $this->getDoctrine()->getManager();
  754.         $sales $entityManager->getRepository(\App\Entity\CarSale::class)->createQueryBuilder('cs')
  755.             ->where('cs.carSale = :id')
  756.             ->orWhere('cs.carSalePayment = :id')
  757.             ->setParameter('id'$car->getId())
  758.             ->getQuery()
  759.             ->getArrayResult();
  760.         $purchases $entityManager->getRepository(\App\Entity\CarBuy::class)->createQueryBuilder('cb')
  761.             ->where('cb.car = :id')
  762.             ->orWhere('cb.carSwap = :id')
  763.             ->setParameter('id'$car->getId())
  764.             ->getQuery()
  765.             ->getArrayResult();
  766.         return $this->render('car/modal_notification_delete_vehicle.html.twig', [
  767.             'car' => $car,
  768.             'sales' => $sales,
  769.             'purchases' => $purchases,
  770.             'currentMenu' => 'car',
  771.         ]);
  772.     }
  773.     /**
  774.      * @Route("/{id}/edit", name="car_edit", requirements={"id"="\d+"}, methods={"GET","POST"})
  775.      */
  776.     public function edit(Request $requestCar $car): Response
  777.     {
  778.         $form $this->createForm(CarType::class, $car);
  779.         //$form = $this->createForm(CarType::class, $car, []);
  780.         $form->handleRequest($request);
  781.         /*dump($form);
  782.         exit('here'); //*/
  783.         if ($form->isSubmitted() && $form->isValid()) {
  784.             $this->attachUploadedImages($request$car);
  785.             $this->syncImagesCollection($car);
  786.             /*if ($car->getStatus() == 'resale') {
  787.                 $user = $this->getDoctrine()->getRepository('App\Entity\User')->find( $form->get('reseller')->getData() );
  788.                 $carResaleCheck = $this->getDoctrine()->getRepository('App\Entity\CarResale')->findBy(['car' => $car->getId()]);
  789.                 if ($carResaleCheck) {
  790.                     $carResaleCheck[0]->setUser($user);
  791.                     $carResaleCheck[0]->setUpdatedAt(new \DateTime());
  792.                     $this->getDoctrine()->getManager()->persist($carResaleCheck[0]);
  793.                 } else {
  794.                     $carResale = new CarResale();
  795.                     $carResale->setCurrency('$');
  796.                     $carResale->setPrice(0);
  797.                     $carResale->setIsDone(0);
  798.                     $carResale->setCar($car);
  799.                     $carResale->setUser($user);
  800.                     $carResale->setCreatedAt(new \DateTime());
  801.                     $this->getDoctrine()->getManager()->persist($carResale);
  802.                 }
  803.                 $this->getDoctrine()->getManager()->flush();
  804.             }*/
  805.             $user $this->getUser();
  806.             if ($user instanceof \App\Entity\User) {
  807.                 $car->setUpdatedBy($user);
  808.             }
  809.             $this->getDoctrine()->getManager()->flush();
  810.             //exit('success');
  811.             return $this->redirectToRoute('car_index', [], Response::HTTP_SEE_OTHER);
  812.         }
  813.         $form2 $this->createForm(CarImagesType::class, new CarImages());
  814.         return $this->render('car/edit.html.twig', [
  815.             'car' => $car,
  816.             'form' => $form->createView(),
  817.             //'form2' => $form2->createView(),
  818.             'currentMenu' => 'car',
  819.         ]);
  820.     }
  821.     private function attachUploadedImages(Request $requestCar $car): void
  822.     {
  823.         $orderRaw $request->request->get('newImagesOrder''');
  824.         $serverIds = [];
  825.         if (!empty($orderRaw)) {
  826.             $decoded json_decode($orderRawtrue);
  827.             if (is_array($decoded)) {
  828.                 $serverIds $decoded;
  829.             }
  830.         }
  831.         if (empty($serverIds)) {
  832.             $serverIds $request->request->all('newImages');
  833.         }
  834.         if (!is_array($serverIds) || empty($serverIds)) {
  835.             return;
  836.         }
  837.         $serverIds array_values(array_unique(array_filter($serverIds, static function ($value) {
  838.             return is_string($value) && $value !== '';
  839.         })));
  840.         if (empty($serverIds)) {
  841.             return;
  842.         }
  843.         $projectDir $this->getParameter('kernel.project_dir');
  844.         $tmpDir     $projectDir '/var/tmp_uploads';
  845.         $fs         = new Filesystem();
  846.         $fs->mkdir($projectDir '/public/uploads/car');
  847.         $positionOffset 0;
  848.         foreach ($car->getImageId() as $existing) {
  849.             $positionOffset max($positionOffset$existing->getPosition() + 1);
  850.         }
  851.         foreach ($serverIds as $position => $serverId) {
  852.             $filename basename($serverId);
  853.             if ($filename === '') {
  854.                 continue;
  855.             }
  856.             $tmpPath $tmpDir '/' $filename;
  857.             if (!$fs->exists($tmpPath)) {
  858.                 continue;
  859.             }
  860.             $uploadedFile = new UploadedFile($tmpPath$filenamenullnulltrue);
  861.             $image = new CarImages();
  862.             $image->setPosition($positionOffset $position);
  863.             $image->setCar($car);
  864.             $image->setImageFile($uploadedFile);
  865.             $car->addImageId($image);
  866.         }
  867.     }
  868.     private function syncImagesCollection(Car $car): void
  869.     {
  870.         $images $car->getImageId();
  871.         foreach ($images as $key => $item) {
  872.             $item->setCar($car);
  873.             $images->set($key$item);
  874.             if ($item->getImageFile() === null && $item->getImage() === null) {
  875.                 $images->removeElement($item);
  876.             }
  877.         }
  878.         $ordered $images->toArray();
  879.         usort($ordered, static fn(CarImages $aCarImages $b) => $a->getPosition() <=> $b->getPosition());
  880.         foreach ($ordered as $index => $image) {
  881.             $image->setPosition($index);
  882.         }
  883.     }
  884.     /**
  885.      * @Route("/{id}", name="car_delete",requirements={"id"="\d+"}, methods={"POST"})
  886.      */
  887.     public function delete(Request $requestCar $car): Response
  888.     {
  889.         if ($this->isCsrfTokenValid('delete'.$car->getId(), $request->request->get('_token'))) {
  890.             $entityManager $this->getDoctrine()->getManager();
  891.             $entityManager->remove($car);
  892.             $entityManager->flush();
  893.         }
  894.         return $this->redirectToRoute('car_index', [], Response::HTTP_SEE_OTHER);
  895.     }
  896.     /**
  897.      * @Route("/{id}/delete", name="car_delete_ra", requirements={"id"="\d+"}, methods={"GET"})
  898.      */
  899.     public function deleteRa(Request $request): Response
  900.     {
  901.         $entityManager $this->getDoctrine()->getManager();
  902.         $sales $entityManager->getRepository(\App\Entity\CarSale::class)->createQueryBuilder('cs')
  903.             ->where('cs.carSale = :id')
  904.             ->orWhere('cs.carSalePayment = :id')
  905.             ->setParameter('id'$request->get('id'))
  906.             ->getQuery()
  907.             ->getArrayResult();
  908.         $purchases $entityManager->getRepository(\App\Entity\CarBuy::class)->createQueryBuilder('cb')
  909.             ->where('cb.car = :id')
  910.             ->orWhere('cb.carSwap = :id')
  911.             ->setParameter('id'$request->get('id'))
  912.             ->getQuery()
  913.             ->getArrayResult();
  914.         //dump($purchases); exit();
  915.         if ( count($sales) == &&  count($purchases) == 0) {
  916.             $vehicle $entityManager->getReference(\App\Entity\Car::class, $request->get('id'));
  917.             $entityManager->remove($vehicle);
  918.             $entityManager->flush();
  919.         } else {
  920.             $this->addFlash(
  921.                 'notice',
  922.                 $request->get('id')
  923.             );
  924.         }
  925.         return $this->redirectToRoute('car_index', [], Response::HTTP_SEE_OTHER);
  926.     }
  927. }