src/Controller/ProduitsController.php line 661

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Produits;
  4. use App\Form\ProduitsType;
  5. use App\Repository\AccessoireRepository;
  6. use App\Repository\FamilleAccessoireRepository;
  7. use App\Repository\ProduitsRepository;
  8. use Cocur\Slugify\Slugify;
  9. use Doctrine\ORM\EntityManagerInterface;
  10. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  11. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\HttpFoundation\JsonResponse;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. use Doctrine\ORM\Tools\Pagination\Paginator;
  17. use Symfony\Component\Security\Core\Security;
  18. use DateTime;
  19. use DateTimeZone;
  20. use App\Entity\Trace;
  21. use Symfony\Component\PropertyAccess\PropertyAccess;
  22. use Psr\Log\LoggerInterface;
  23. use Doctrine\DBAL\Connection;
  24. #[Route('/produits')]
  25. class ProduitsController extends AbstractController
  26. {
  27.     private $security;
  28.     public function __construct(Security $security)
  29.     {
  30.         $this->security $security;
  31.     }
  32.     #[Route('/filter_produits'name'app_produits_filter')]
  33.     public function filter(Request $requestProduitsRepository $produitsRepository): Response
  34.     {
  35.         $nomprenom preg_replace('/\s+/'' 'trim($request->query->get('nomprenom')));
  36.         // Build the query
  37.         $queryBuilder $produitsRepository->createQueryBuilder('p')
  38.             ->where('p.IsArchive = :isArchive')
  39.             ->setParameter('isArchive'false);
  40.         if (!empty($nomprenom)) {
  41.             $queryBuilder->andWhere('p.nom LIKE :nomprenom')
  42.                 ->setParameter('nomprenom'"%$nomprenom%");
  43.         }
  44.         $queryBuilder->orderBy('p.id''DESC');
  45.         // Get all results without pagination
  46.         $produits $queryBuilder->getQuery()->getResult();
  47.         return $this->render('produits/recherche.html.twig', [
  48.             'produits' => $produits,
  49.             'nomprenom' => $nomprenom// Pass the search term to the template
  50.         ]);
  51.     }
  52. //    #[Route('/filter_produits', name: 'app_produits_filter')]
  53. //    public function filter(Request $request, ProduitsRepository $produitsRepository): Response
  54. //    {
  55. ////        $nomprenom = $request->query->get('nomprenom');
  56. //        $nomprenom = preg_replace('/\s+/', ' ', trim($request->query->get('nomprenom')));
  57. //
  58. //        $page = $request->query->getInt('page', 1);
  59. //        $limit = 5;
  60. //
  61. //        // Build the query
  62. //        $queryBuilder = $produitsRepository->createQueryBuilder('p')
  63. //        ->where('p.IsArchive = :isArchive')
  64. //        ->setParameter('isArchive', false);
  65. ////            ->andWhere('p.IsArchive = false');
  66. //
  67. //        if (!empty($nomprenom)) {
  68. //            $queryBuilder->andWhere('p.nom LIKE :nomprenom')
  69. //                ->setParameter('nomprenom', "%$nomprenom%");
  70. //        }
  71. //
  72. //        $queryBuilder->orderBy('p.id', 'DESC');
  73. //
  74. //        // Get the query
  75. //        $query = $queryBuilder->getQuery();
  76. //
  77. //        // Apply pagination
  78. //        $paginator = new Paginator($query);
  79. //        $totalItems = count($paginator);
  80. //        $totalPages = ceil($totalItems / $limit);
  81. //
  82. //        $paginator->getQuery()
  83. //            ->setFirstResult($limit * ($page - 1))
  84. //            ->setMaxResults($limit);
  85. //
  86. //        // Convert paginator to array if needed
  87. //        $produits = iterator_to_array($paginator);
  88. //
  89. //        return $this->render('produits/recherche.html.twig', [
  90. ////            'setting' => $settingsRepository->find(1),
  91. //            'produits' => $produits,
  92. //            'currentPage' => $page,
  93. //            'totalPages' => $totalPages,
  94. //            'nomprenom' => $nomprenom, // Pass the search term to the template
  95. //        ]);
  96. //    }
  97.     #[Route('/archive'name'app_produits_archive'methods: ['GET'])]
  98.     public function archive(Request $requestProduitsRepository $produitsRepositorySecurity $security): Response
  99.     {
  100.         $user $security->getUser();
  101.         $roles $user->getRoles();
  102.         // Pagination
  103.         $page $request->query->getInt('page'1);
  104.         $limit 10;
  105.         // Requête de base : uniquement les produits archivés
  106.         $queryBuilder $produitsRepository->createQueryBuilder('p')
  107.             ->where('p.IsArchive = :isArchive')
  108.             ->setParameter('isArchive'true)
  109.             ->orderBy('p.id''DESC');
  110.         // Filtrage selon le rôle
  111. //        if (in_array('ROLE_ULTRATEX', $roles)) {
  112. //            $queryBuilder
  113. //                ->andWhere('p.societe = :societe')
  114. //                ->setParameter('societe', 'Ultratex');
  115. //        }
  116. //        elseif (in_array('ROLE_ULTRACONFECTION', $roles)) {
  117. //            $queryBuilder
  118. //                ->andWhere('p.societe = :societe')
  119. //                ->setParameter('societe', 'Ultraconfection');
  120. //        }
  121.         // ROLE_ADMIN voit tous les produits archivés
  122.         // Pagination
  123.         $paginator = new Paginator($queryBuilder);
  124.         $allproduit $paginator->getQuery()
  125.             ->setFirstResult($limit * ($page 1))
  126.             ->setMaxResults($limit)
  127.             ->getResult();
  128.         $totalItems count($paginator);
  129.         $totalPages ceil($totalItems $limit);
  130.         return $this->render('produits/archive.html.twig', [
  131.             'produits' => $allproduit,
  132.             'currentPage' => $page,
  133.             'totalPages' => $totalPages,
  134.         ]);
  135.     }
  136.     #[Route('/'name'app_produits_index'methods: ['GET'])]
  137.     public function index(Request $requestProduitsRepository $produitsRepositorySecurity $security): Response
  138.     {
  139.         $user $security->getUser();
  140.         $roles $user->getRoles();
  141. //        dump($roles);
  142.         // Configuration de la pagination
  143.         $page $request->query->getInt('page'1);
  144.         $limit 10;
  145.         // Construction de la requête
  146.         $queryBuilder $produitsRepository->createQueryBuilder('p')
  147.             ->where('p.IsArchive = :isArchive')
  148.             ->setParameter('isArchive'false)
  149.             ->orderBy('p.id''DESC');
  150.         // Filtrage en fonction des rôles
  151. //        if (in_array('ROLE_ULTRATEX', $roles)) {
  152. //            dump('tx');
  153. //            $queryBuilder
  154. //                ->andWhere('p.societe = :societe')
  155. //                ->setParameter('societe', 'Ultratex');
  156. //        }
  157. //        elseif (in_array('ROLE_ULTRACONFECTION', $roles)) {
  158. //            dump("conf");
  159. //            $queryBuilder
  160. //                ->andWhere('p.societe = :societe')
  161. //                ->setParameter('societe', 'Ultraconfection');
  162. //        }
  163.         // ROLE_ADMIN verra tout, donc pas de filtre supplémentaire
  164.         // Application de la pagination
  165.         $paginator = new Paginator($queryBuilder);
  166.         $allproduit $paginator->getQuery()
  167.             ->setFirstResult($limit * ($page 1))
  168.             ->setMaxResults($limit)
  169.             ->getResult();
  170. //        dd($allproduit);
  171.         $totalItems count($paginator);
  172.         $totalPages ceil($totalItems $limit);
  173. //        dd($allproduit);
  174.         return $this->render('produits/index.html.twig', [
  175.             'produits' => $allproduit,
  176.             'currentPage' => $page,
  177.             'totalPages' => $totalPages,
  178.         ]);
  179.     }
  180. //    #[Route('/', name: 'app_produits_index', methods: ['GET'])]
  181. //    public function index(Request $request,ProduitsRepository $produitsRepository): Response
  182. //    {
  183. //
  184. //        // Configuration de la pagination
  185. //        $page = $request->query->getInt('page', 1);
  186. //        $limit = 10;
  187. //
  188. //        // Construction de la requête pour la pagination
  189. //        $queryBuilder = $produitsRepository->createQueryBuilder('p')
  190. //            ->where('p.IsArchive = :isArchive')
  191. //            ->setParameter('isArchive', false)
  192. //            ->orderBy('p.id', 'DESC');
  193. //
  194. //
  195. //        // Application de la pagination
  196. //        $paginator = new Paginator($queryBuilder);
  197. //        $allproduit = $paginator->getQuery()
  198. //            ->setFirstResult($limit * ($page - 1))
  199. //            ->setMaxResults($limit)
  200. //            ->getResult();
  201. //
  202. //        $totalItems = count($paginator);
  203. //        $totalPages = ceil($totalItems / $limit);
  204. //        return $this->render('produits/index.html.twig', [
  205. ////            'produits' => $produitsRepository->findAll(),
  206. //            'produits' =>$allproduit,
  207. //            'currentPage' => $page,
  208. //            'totalPages' => $totalPages,
  209. //        ]);
  210. //    }
  211.     #[Route('/new'name'app_produits_new'methods: ['GET''POST'])]
  212.     public function new(FamilleAccessoireRepository $familleAccessoireRepository,AccessoireRepository $accessoireRepository,Request $requestEntityManagerInterface $entityManager): Response
  213.     {
  214.         if (!$this->getUser()) {
  215.             return $this->redirectToRoute('app_login');
  216.         }
  217.         if (!$this->getUser()) {
  218.             return $this->redirectToRoute('app_login');
  219.         }
  220.         $facc $familleAccessoireRepository->findAll();
  221.         $acc $accessoireRepository->findBy(['IsArchive'=>false]);
  222.         $user $this->security->getUser();
  223.         $role $user->getRoles()[0] ?? null;
  224.         $produit = new Produits();
  225.         $form $this->createForm(ProduitsType::class, $produit);
  226.         $form->handleRequest($request);
  227.         if ($form->isSubmitted() && $form->isValid()) {
  228.             $date = new \DateTime('now', new DateTimeZone('Africa/Tunis'));
  229.             $produit->setIsArchive(false);
  230.             $tissuStatus $request->request->get('tissuStatus');
  231. //            dd($tissuStatus);
  232.             $societe null;
  233.             if ($role === 'ROLE_ULTRATEX') {
  234.                 $societe 'Ultratex';
  235.             } elseif ($role === 'ROLE_ULTRACONFECTION') {
  236.                 $societe 'Ultraconfection';
  237.             }
  238.             $produit->setSociete($societe);
  239.             $logo $form->get('image')->getData();
  240.             if ( $logo) {
  241.                 $originalLogoname pathinfo$logo->getClientOriginalName(), PATHINFO_FILENAME);
  242.                 $slugify = new Slugify();
  243.                 $a=  $slugify->slugify($originalLogoname, ['separator' => '-']);
  244.                 $newLogoname =  $a.'-'.uniqid().'.'.$logo->guessExtension();
  245.                 // Move the file to the directory where brochures are stored
  246.                 try {
  247.                     $logo->move(
  248.                         $this->getParameter('produit_directory'),
  249.                         $newLogoname
  250.                     );
  251.                 } catch (FileException $e) {
  252.                     // ... handle exception if something happens during file upload
  253.                 }
  254.                 $produit->setImage($newLogoname);
  255.             }
  256.             $produit->setDateajout($date);
  257.             $accessoires$request->request->get('accessoire');
  258.             $accs$accessoireRepository->findOneBy(['id'=>$accessoires,'IsArchive'=>false]);
  259. //            dd($accessoires,$accs);
  260.             $produit->setIsTissu($tissuStatus);
  261.             $produit->setAccessoire($accs);
  262.             $entityManager->persist($produit);
  263.             $entityManager->flush();
  264.             $this->addFlash('successproduit''Produit ajouté avec succès.');
  265.             if (!$this->getUser()) {
  266.                 return $this->redirectToRoute('app_login');
  267.             }
  268.             if (!$this->getUser()) {
  269.                 return $this->redirectToRoute('app_login');
  270.             }
  271.             // Trace de creation produit
  272.             /** @var \App\Entity\User $user */
  273.             $user $this->security->getUser();
  274.             $role $user->getRoles()[0] ?? null;
  275.             $email2 $user->getEmail();
  276.             $nom $produit->getNom();
  277.             $trace= new Trace();
  278.             $trace->setDate(new \DateTimeImmutable('now', new \DateTimeZone('Africa/Tunis')));
  279.             $trace->setEmail($email2);
  280.             $trace->setRole($role);
  281.             $trace->setAction("Création du produit '{$nom}'");
  282.             $trace->setUser($user);
  283.             $entityManager->persist($trace);
  284.             $entityManager->flush();
  285.             return $this->redirectToRoute('app_produits_index', [], Response::HTTP_SEE_OTHER);
  286.         }
  287.         return $this->renderForm('produits/new.html.twig', [
  288.             'produit' => $produit,
  289.             'form' => $form,
  290.             'acc'=>$acc,
  291.             'facc'=>$facc
  292.         ]);
  293.     }
  294.     #[Route('/{id}'name'app_produits_show'methods: ['GET'], requirements: ['id' => '\d+'])]
  295.     public function show(Produits $produit): Response
  296.     {
  297.         return $this->render('produits/show.html.twig', [
  298.             'produit' => $produit,
  299.         ]);
  300.     }
  301.     #[Route('/{id}/edit'name'app_produits_edit'methods: ['GET''POST'])]
  302.     public function edit(FamilleAccessoireRepository $familleAccessoireRepository,AccessoireRepository $accessoireRepository,Request $requestProduits $produitEntityManagerInterface $entityManager): Response
  303.     {
  304.         $facc $familleAccessoireRepository->findAll();
  305.         $acc $accessoireRepository->findBy(['IsArchive'=>false]);
  306.         $img $produit->getImage();
  307.         $form $this->createForm(ProduitsType::class, $produit);
  308.         $form->handleRequest($request);
  309. //        dd($produit->getAccessoire(), $produit);
  310.         if ($form->isSubmitted() && $form->isValid()) {
  311.             $istissu $request->request->get('tissuStatus');
  312.             $accessoire $request->request->get('accessoire');
  313.             $accs $accessoireRepository->findOneBy(['id'=>$accessoire,'IsArchive'=>false]);
  314. //          dd($istissu);
  315.             $logo $form->get('image')->getData();
  316.             //detecter les champs
  317.             $produitOriginal = clone $produit;
  318.             $accessor PropertyAccess::createPropertyAccessor();
  319.             $fields = ['nom''coleur''prix''image',  'tva''quantitelimite','stock','image'];
  320.             $changes = [];
  321.             foreach ($fields as $field) {
  322.                 $oldValue $accessor->getValue($produitOriginal$field);
  323.                 $newValue $accessor->getValue($produit$field);
  324.                 if ($oldValue !== $newValue) {
  325.                     $changes[] = "$field: '$oldValue' → '$newValue'";
  326.                 }
  327.             }
  328.             if ( $logo) {
  329.                 $originalLogoname pathinfo$logo->getClientOriginalName(), PATHINFO_FILENAME);
  330.                 $slugify = new Slugify();
  331.                 $a=  $slugify->slugify($originalLogoname, ['separator' => '-']);
  332.                 $newLogoname =  $a.'-'.uniqid().'.'.$logo->guessExtension();
  333.                 // Move the file to the directory where brochures are stored
  334.                 try {
  335.                     $logo->move(
  336.                         $this->getParameter('produit_directory'),
  337.                         $newLogoname
  338.                     );
  339.                 } catch (FileException $e) {
  340.                     // ... handle exception if something happens during file upload
  341.                 }
  342.                 $produit->setImage($newLogoname);
  343.             }
  344.             elseif ($logo === null) {
  345.                 $produit->setImage($img);
  346.             }
  347.             $produit->setAccessoire($accs);
  348.             $produit->setIsTissu($istissu);
  349. //           dd($produit);
  350.             
  351.             $entityManager->flush();
  352.             $this->addFlash('modifproduit''Produit modifié avec succès.');
  353.             /** @var \App\Entity\User $user */
  354.             $user $this->security->getUser();
  355.             $role $user->getRoles()[0] ?? null;
  356.             $email2 $user->getEmail();
  357.             $trace= new Trace();
  358.             $trace->setDate(new \DateTimeImmutable('now', new \DateTimeZone('Africa/Tunis')));
  359.             $trace->setEmail($email2);
  360.             $trace->setRole($role);
  361.             $nom $produit->getNom();
  362.             $action "Modification du produit '{$nom}'";
  363.             /*if (!empty($changes)) {
  364.                 $action .= " | Champs modifiés : " . implode(', ', $changes);
  365.             } else {
  366.                 $action .= " | Aucun changement détecté.";
  367.             }*/
  368.             $trace->setAction($action);
  369.             $trace->setUser($user);
  370.             $entityManager->persist($trace);
  371.             $entityManager->flush();
  372.             return $this->redirectToRoute('app_produits_index', [], Response::HTTP_SEE_OTHER);
  373.         }
  374.         return $this->renderForm('produits/edit.html.twig', [
  375.             'produit' => $produit,
  376.             'form' => $form,
  377.             'acc'=>$acc,
  378.             'facc'=>$facc,
  379.             'accessoireChoisi' => $produit->getAccessoire(),
  380.         ]);
  381.     }
  382.     #[Route('/remove/{id}'name'app_produits_delete')]
  383.     public function delete(Request $requestProduits $produitEntityManagerInterface $entityManager): Response
  384.     {
  385. //        if ($this->isCsrfTokenValid('delete'.$produit->getId(), $request->request->get('_token'))) {
  386.             $produit->setIsArchive(true);
  387.         $entityManager->persist($produit); // Ajout de persist pour s'assurer que le changement est suivi
  388.         //            $entityManager->remove($produit);
  389.             $entityManager->flush();
  390. //        }
  391.         // Trace Archivage du produit
  392.             /** @var \App\Entity\User $user */
  393.             $user $this->security->getUser();
  394.             $role $user->getRoles()[0] ?? null;
  395.             $email2 $user->getEmail();
  396.             $nom $produit->getNom();
  397.             $trace= new Trace();
  398.             $trace->setDate(new \DateTimeImmutable('now', new \DateTimeZone('Africa/Tunis')));
  399.             $trace->setEmail($email2);
  400.             $trace->setRole($role);
  401.             $trace->setAction("Archivage du produit '{$nom}'");
  402.             $trace->setUser($user);
  403.             $entityManager->persist($trace);
  404.             $entityManager->flush();
  405.         return $this->redirectToRoute('app_produits_index', [], Response::HTTP_SEE_OTHER);
  406.     }
  407.     #[Route('/remove-archive/{id}'name'app_produits_delete_archive')]
  408.     public function deletearchive(Request $requestProduits $produitEntityManagerInterface $entityManagerSecurity $security): Response
  409.     {
  410.         $produit->setIsArchive(false);
  411.         $entityManager->persist($produit); // Ajout de persist pour s'assurer que le changement est suivi
  412.         $entityManager->flush();
  413.         // Trace Désarchivage du produit
  414.         $user $security->getUser();
  415.         $role $user->getRoles()[0] ?? null;
  416.         $email2 $user->getEmail();
  417.         $nom $produit->getNom();
  418.         $trace = new Trace();
  419.         $trace->setDate(new \DateTimeImmutable('now', new \DateTimeZone('Africa/Tunis')));
  420.         $trace->setEmail($email2);
  421.         $trace->setRole($role);
  422.         $trace->setAction("Désarchivage du produit '{$nom}'");
  423.         $trace->setUser($user);
  424.         $entityManager->persist($trace);
  425.         $entityManager->flush();
  426.         return $this->redirectToRoute('app_produits_archive', [], Response::HTTP_SEE_OTHER);
  427.     }
  428. //    #[Route('/remove-archive/{id}', name: 'app_produits_delete_archive')]
  429. //    public function deletearchive(Request $request, Produits $produit, EntityManagerInterface $entityManager): Response
  430. //    {
  431. ////        if ($this->isCsrfTokenValid('delete'.$produit->getId(), $request->request->get('_token'))) {
  432. //        $produit->setIsArchive(false);
  433. //        $entityManager->persist($produit);
  434. //        //            $entityManager->remove($produit);
  435. //        $entityManager->flush();
  436. ////        }
  437. //        // Trace Désarchivage du produit
  438. //            /** @var \App\Entity\User $user */
  439. //            $user = $this->security->getUser();
  440. //            $role = $user->getRoles()[0] ?? null;
  441. //            $email2 = $user->getEmail();
  442. //            $nom = $produit->getNom();
  443. //            $trace= new Trace();
  444. //            $trace->setDate(new \DateTimeImmutable('now', new \DateTimeZone('Africa/Tunis')));
  445. //            $trace->setEmail($email2);
  446. //            $trace->setRole($role);
  447. //            $trace->setAction("Désarchivage du produit '{$nom}'");
  448. //            $trace->setUser($user);
  449. //            $entityManager->persist($trace);
  450. //            $entityManager->flush();
  451. //        return $this->redirectToRoute('app_produits_archive', [], Response::HTTP_SEE_OTHER);
  452. //    }
  453.     //logique notification produits épuisés
  454. /*    #[Route('/produitsepuises', name: 'produitsepuises', methods: ['GET', 'POST'])]
  455.     public function produitsepuises(Connection $connection): JsonResponse
  456.     {
  457.         $user = $this->getUser();
  458. //        $role = $user->getRoles()[0] ?? null;
  459.         $roles = $this->getUser()->getRoles();
  460.         $sql = null;
  461.         $params = [];
  462.         if (in_array('ROLE_ULTRATEX', $roles)){
  463.             $sql = "
  464.                 SELECT * FROM produits p
  465.                 WHERE p.quantitelimite IS NOT NULL
  466.                   AND CAST(p.stock AS SIGNED) <= CAST(p.quantitelimite AS SIGNED)
  467.                   AND p.societe = :societe
  468.                 ORDER BY p.id DESC
  469.             ";
  470.             $params = ['societe' => 'Ultratex'];
  471.         }
  472.         elseif (in_array('ROLE_ULTRACONFECTION', $roles)){
  473.             $sql = "
  474.                 SELECT * FROM produits p
  475.                 WHERE p.quantitelimite IS NOT NULL
  476.                   AND CAST(p.stock AS SIGNED) <= CAST(p.quantitelimite AS SIGNED)
  477.                   AND p.societe = :societe
  478.                 ORDER BY p.id DESC
  479.             ";
  480.             $params = ['societe' => 'UltraConfection'];
  481.         } else {
  482.             return new JsonResponse([
  483.                 'nb_total' => 0,
  484.                 'suspensions' => []
  485.             ]);
  486.         }
  487.         $produits = $connection->fetchAllAssociative($sql, $params);
  488.         $response = [];
  489.         foreach ($produits as $produit) {
  490.             $response[] = [
  491.                 'id' => $produit['id'],
  492.                 'prix' => $produit['prix'],
  493.                 'nom' => $produit['nom'],
  494.                 'stock' => (int)$produit['stock'],
  495.                 'quantitelimite' => (int)$produit['quantitelimite'],
  496.             ];
  497.         }
  498.         return new JsonResponse([
  499.             'nb_total' => count($response),
  500.             'suspensions' => $response
  501.         ]);
  502.     }*/
  503.     #[Route('/produitsepuises'name'produitsepuises'methods: ['GET''POST'])]
  504.     public function produitsepuises(ProduitsRepository $produitsRepository): JsonResponse
  505.     {
  506. //        $user = $this->getUser();
  507. //        $roles = $user->getRoles();
  508. //
  509. //        if (in_array('ROLE_ULTRATEX', $roles)) {
  510. //            $societe = 'Ultratex';
  511. //        } elseif (in_array('ROLE_ULTRACONFECTION', $roles)) {
  512. //            $societe = 'UltraConfection';
  513. //        } else {
  514. //            return new JsonResponse([
  515. //                'nb_total' => 0,
  516. //                'suspensions' => []
  517. //            ]);
  518. //        }
  519.         // Récupérer tous les produits de la société
  520.         $produits $produitsRepository->findAll();
  521.         $produitsAlerte = [];
  522.         $nbTotalAlertes 0;
  523.         foreach ($produits as $produit) {
  524.             $alertesCouleurs = [];
  525.             $hasAlerteProduit false;
  526.             // Vérifier les alertes par couleur (détails produit)
  527.             foreach ($produit->getDetailsproduits() as $detail) {
  528.                 $enAlerte false;
  529.                 $message '';
  530.                 // Récupérer les valeurs correctes
  531.                 $qte $detail->getQte() ?? 0;
  532.                 $qtelimite $detail->getQtelimite() ?? 0;
  533.                 if ($produit->getIsTissu()) {
  534.                     // Pour les tissus: vérifier le poids (qte = poids dans ce cas)
  535.                     if ($qtelimite && $qte $qtelimite) {
  536.                         $enAlerte true;
  537.                         $message "Poids: {$qte} / Limite: {$qtelimite}";
  538.                     }
  539.                 } else {
  540.                     // Pour les non-tissus: vérifier la quantité
  541.                     if ($qtelimite && $qte $qtelimite) {
  542.                         $enAlerte true;
  543.                         $message "Quantité: {$qte} / Limite: {$qtelimite}";
  544.                     }
  545.                 }
  546.                 if ($enAlerte) {
  547.                     $couleur $detail->getCouleur();
  548.                     $alertesCouleurs[] = [
  549.                         'couleur_nom' => $couleur $couleur->getNom() : 'Sans couleur',
  550. //                        'couleur_code' => $couleur ? $couleur->getCode() : '#666',
  551.                         'message' => $message,
  552.                         'qte' => $qte,
  553.                         'qtelimite' => $qtelimite
  554.                     ];
  555.                     $hasAlerteProduit true;
  556.                     $nbTotalAlertes++;
  557.                 }
  558.             }
  559.             // Vérifier les alertes au niveau produit
  560.             if (!$produit->getIsTissu()) {
  561.                 // Pour non-tissu: vérifier stock global vs quantitelimite
  562.                 $stock $produit->getStock() ?? 0;
  563.                 $quantitelimite $produit->getQuantitelimite() ?? 0;
  564.                 if ($quantitelimite && $stock $quantitelimite) {
  565.                     $hasAlerteProduit true;
  566.                     $nbTotalAlertes++;
  567.                 }
  568.             } else {
  569.                 // Pour tissu: vérifier totalepoid vs totpoidlimite
  570.                 $totalepoid $produit->getTotalepoid() ?? 0;
  571.                 $totpoidlimite $produit->getTotpoidlimite() ?? 0;
  572.                 if ($totpoidlimite && $totalepoid $totpoidlimite) {
  573.                     $hasAlerteProduit true;
  574.                     $nbTotalAlertes++;
  575.                 }
  576.             }
  577.             if ($hasAlerteProduit) {
  578.                 $produitsAlerte[] = [
  579.                     'id' => $produit->getId(),
  580.                     'nom' => $produit->getNom(),
  581.                     'reference' => $produit->getReference(),
  582.                     'is_tissu' => $produit->getIsTissu(),
  583.                     'stock' => $produit->getStock() ?? 0,
  584.                     'quantitelimite' => $produit->getQuantitelimite() ?? 0,
  585.                     'totalepoid' => $produit->getTotalepoid() ?? 0,
  586.                     'totpoidlimite' => $produit->getTotpoidlimite() ?? 0,
  587.                     'couleurs' => $alertesCouleurs
  588.                 ];
  589.             }
  590.         }
  591.         dump($nbTotalAlertes,$produitsAlerte);
  592.         return new JsonResponse([
  593.             'nb_total' => $nbTotalAlertes,
  594.             'suspensions' => $produitsAlerte
  595.         ]);
  596.     }
  597. //    #[Route('/produitsepuises', name: 'produitsepuises', methods: ['GET', 'POST'])]
  598. //    public function produitsepuises(Connection $connection,ProduitsRepository $produitsRepository): JsonResponse
  599. //    {
  600. //        $produits = $produitsRepository->findAll();
  601. ////        dump($produits);
  602. //        $user = $this->getUser();
  603. //        $roles = $user->getRoles();
  604. //
  605. //        $sql = null;
  606. //        $params = [];
  607. //
  608. //        if (in_array('ROLE_ULTRATEX', $roles)) {
  609. //            $societe = 'Ultratex';
  610. //        } elseif (in_array('ROLE_ULTRACONFECTION', $roles)) {
  611. //            $societe = 'UltraConfection';
  612. //        } else {
  613. //            return new JsonResponse([
  614. //                'nb_total' => 0,
  615. //                'suspensions' => []
  616. //            ]);
  617. //        }
  618. //
  619. //        $sql = "
  620. //    SELECT * FROM produits p
  621. //    WHERE (p.quantitelimite IS NOT NULL OR p.totpoidlimite IS NOT NULL)
  622. //    AND (
  623. //        (p.is_tissu = 1 AND CAST(p.totalepoid AS SIGNED) < CAST(p.totpoidlimite AS SIGNED))
  624. //        OR
  625. //        (COALESCE(p.is_tissu, 0) = 0 AND CAST(p.stock AS SIGNED) < CAST(p.quantitelimite AS SIGNED))
  626. //    )
  627. //    AND p.societe = :societe
  628. //    ORDER BY p.id DESC
  629. //";
  630. //
  631. //
  632. //
  633. //
  634. //        $params = ['societe' => $societe];
  635. //
  636. //        $produits = $connection->fetchAllAssociative($sql, $params);
  637. //
  638. //        $response = [];
  639. //        foreach ($produits as $produit) {
  640. //            $response[] = [
  641. //                'id' => $produit['id'],
  642. //                'prix' => $produit['prix'],
  643. //                'nom' => $produit['nom'],
  644. //                'stock' => (int) ($produit['stock'] ?? 0),
  645. //                'quantitelimite' => (int) ($produit['quantitelimite'] ?? 0),
  646. //                'totalepoid' => (float) ($produit['totalepoid'] ?? 0),
  647. //                'totpoidlimite' => (float) ($produit['totpoidlimite'] ?? 0),
  648. //                'is_tissu' => (bool) $produit['is_tissu'],
  649. //            ];
  650. //        }
  651. ////        dump(count($response),$response);
  652. //
  653. //        return new JsonResponse([
  654. //            'nb_total' => count($response),
  655. //            'suspensions' => $response
  656. //        ]);
  657. //    }
  658. //
  659. //    #[Route('/produitsepuises', name: 'produitsepuises', methods: ['GET', 'POST'])]
  660. //    public function produitsepuises(ProduitsRepository $produitsRepository): JsonResponse
  661. //    {
  662. //        $user = $this->security->getUser();
  663. //        $role = $user->getRoles()[0] ?? null;
  664. //        if ($role === 'ROLE_ULTRATEX') {
  665. //            $produits = $produitsRepository->findProduitsStockLimiteForUltratex();
  666. //        }
  667. //        elseif ($role === 'ROLE_ULTRACONFECTION') {
  668. //            $produits = $produitsRepository->findProduitsStockLimiteForUltraConfection();
  669. //        }
  670. //        //dd($produits);
  671. //        $response = [];
  672. //        foreach ($produits as $produit) {
  673. //            $response[] = [
  674. //                'id' => $produit->getId(),
  675. //                'prix' => $produit->getPrix(),
  676. //                'nom' => $produit->getNom(),
  677. //                'stock' => $produit->getStock(),
  678. //                'quantitelimite' => $produit->getQuantitelimite(),
  679. //            ];
  680. //        }
  681. //
  682. //        return new JsonResponse([
  683. //            'nb_total' => count($response),
  684. //            'suspensions' => $response
  685. //        ]);
  686. //    }
  687.     #[Route('/check-reference-used'name'check_reference_used'methods: ['GET''POST'])]
  688.     public function checkReferenceUsed(
  689.         Request $request,
  690.         ProduitsRepository $produitsRepository,
  691.         LoggerInterface $logger
  692.     ): JsonResponse {
  693.         $reference $request->get('reference');
  694.         $logger->info('🔍 Requête AJAX reçue avec la référence : ' $reference);
  695.         if (!$reference) {
  696.             $logger->warning(' Référence manquante dans la requête AJAX');
  697.             return new JsonResponse(['error' => 'Référence manquante'], 400);
  698.         }
  699.         $produit $produitsRepository->findOneBy(['reference' => $reference]);
  700.         if ($produit) {
  701.             $logger->info('Référence déjà utilisée');
  702.         } else {
  703.             $logger->info('Référence libre');
  704.         }
  705.         return new JsonResponse(['used' => $produit !== null]);
  706.     }
  707. }