src/Controller/CarController.php line 378

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