src/Controller/FrontController/ProductController.php line 47

Open in your IDE?
  1. <?php
  2. namespace App\Controller\FrontController;
  3. use App\Acme\Bundle\FrontUtility\ProductUtility;
  4. use App\Entity\Product;
  5. use App\Entity\UserPlatform;
  6. use App\Entity\Location;
  7. use App\Entity\Order;
  8. use App\Entity\DetailsOrders;
  9. use App\Form\SubscriptionForm\UserMultilType;
  10. use App\Form\ProductType;
  11. use App\Form\CommandeValideType;
  12. use App\Form\RentProductType;
  13. use App\Repository\ProductRepository;
  14. use App\Repository\LocationRepository;
  15. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpFoundation\Response;
  18. use Symfony\Component\HttpFoundation\JsonResponse;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  21. use App\Repository\UserPlatformRepository;
  22. use Symfony\Component\EventDispatcher\EventDispatcher;
  23. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  24. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  25. use Doctrine\ORM\EntityManagerInterface;
  26. use App\Acme\Bundle\Utility\UtilitySearchSystem;
  27. use App\Repository\StockRepository;
  28. use App\Entity\MotRechercher;
  29. use App\Entity\PriceProduct;
  30. use App\Repository\MotRechercherRepository;
  31. use Exception;
  32. use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
  33. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  34. /**
  35.  * @Route("/produit")
  36.  */
  37. class ProductController extends AbstractController
  38. {
  39.     /**
  40.      * @Route("/", name="app_product_index", methods={"GET"})
  41.      */
  42.     public function index(ProductRepository $productRepository): Response
  43.     {
  44.         return $this->render('/frontView/product/index.html.twig', [
  45.             'topOrderedProducts' => $productRepository->findTopOrderedProductsRandom(4),
  46.             'recentProducts' => $productRepository->findRecentProducts(4),
  47.             'temoin' => 0,
  48.             'message' => ''
  49.         ]);
  50.     }
  51.     /**
  52.      * @Route("/search-product", name="app_product_search", methods={"GET"})
  53.      */
  54.     public function searchProduct(
  55.         Request $request,
  56.         ProductRepository $productRepository,
  57.         MotRechercherRepository $motRechercherRepository
  58.     ): Response {
  59.         $resultat = array();
  60.         if ("GET" == $request->getMethod()) {
  61.             $motrechercher = $request->query->get('searchname');
  62.             if (empty($motrechercher)) {
  63.                 $resultat = array();
  64.             } else {
  65.                 $mot = $motrechercher;
  66.                 $res_objet = UtilitySearchSystem::initStepSearch($motrechercher);
  67.                 //si parmit les recherche du client se trouve dans la liste de mots cles de base
  68.                 if (count($res_objet) > 0) {
  69.                     $resultat = $productRepository->searchProduct($res_objet);
  70.                     if (0 === count($resultat)) {
  71.                         $motRechercherRepository->createOrUpdateMotRecherche($mot,\DateTime::createFromFormat('Y-m-d H:i:s',Date('Y-m-d H:i:s')));
  72.                     }
  73.                 } else {
  74.                     $resultat = array();
  75.                 }
  76.             }
  77.         }
  78.         return $this->render('/frontView/product/index.html.twig', [
  79.             'products' => $resultat,
  80.             'temoin' => 0,
  81.             'message' => ''
  82.         ]);
  83.     }
  84.     
  85.     /**
  86.      * @Route("/ajax-search", name="ajax_search", methods={"GET"})
  87.      */
  88.     public function ajaxSearch(
  89.         Request $request,
  90.         ProductRepository $productRepository
  91.     ): JsonResponse {
  92.         $keyword = $request->query->get('q');
  93.         // $keyword = 'protec';
  94.         if (!$keyword || strlen($keyword) < 2) {
  95.             return $this->json([]);
  96.         }
  97.         $products = $productRepository->findSuggestions($keyword);
  98.         $data = [];
  99.         foreach ($products as $product) {
  100.             $data[] = [
  101.                 'id' => $product->getId(),
  102.                 'title' => $product->getTitle(),
  103.                 'image' => $product->getPicture()/*,
  104.                 'price' => $product->getPrice(),*/
  105.             ];
  106.         }
  107.         // dd($data);
  108.         return $this->json($data);
  109.     }
  110.     /**
  111.      * @Route("/list-categorie/{idcategorie}/{type}", name="app_product_category", methods={"GET"})
  112.      */
  113.     public function lisCategorie(ProductRepository $productRepository, int $idcategorie, string $type): Response
  114.     {
  115.         $criteria = array();
  116.         if ("categorie" == $type) {
  117.             $criteria = array('fkcategorie'=>$idcategorie, 'enabled'=>true);
  118.         } else {
  119.             $criteria = array('fksousCategorie'=>$idcategorie, 'enabled'=>true);
  120.         }
  121.         $listProducts = $productRepository->findBy($criteria);
  122.         return $this->render('/frontView/product/index.html.twig', [
  123.             'products' => $listProducts,
  124.         ]);
  125.     }
  126.     public function createUser(
  127.         $form,
  128.         $user,
  129.         $arrayresult,
  130.         Request $request,
  131.         UserPasswordEncoderInterface $passwordEncoder,
  132.         UserPlatformRepository $userPlatformRepository
  133.     ) {
  134.         $error = 1;
  135.         if ($user->getPassword() != $form->get('confirmpass')->getData()) {
  136.             $arrayresult['error'] = true;
  137.             $arrayresult['msg'] = "Mot de passe non confirmé.";
  138.         } elseif (strpos($user->getEmail(), " ")) {
  139.             $arrayresult['error'] = true;
  140.             $arrayresult['msg'] = "l'identifiant \"".$user->getEmail()."\" ne doit pas contenir un espace.";
  141.         } elseif (strlen($user->getEmail()) < 5) {
  142.             $arrayresult['error'] = true;
  143.             $arrayresult['msg'] = "l'identifiant \"".$user->getEmail()."\" doit contenir plus de 5 caracteres.";
  144.         } else {
  145.             $user->setRoles(["ROLE_CUSTOMER"]);
  146.             $user->setPassword(
  147.                 $passwordEncoder->encodePassword($user, $user->getPassword())
  148.             );
  149.             $userPlatformRepository->add($user, true);
  150.             //Authentification
  151.             $token = new UsernamePasswordToken($user, $user->getPassword(), "public", $user->getRoles());
  152.             $this->get("security.token_storage")->setToken($token);
  153.             $event = new InteractiveLoginEvent($request, $token);
  154.             //$this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
  155.             $error = 0;
  156.         }
  157.         return $error;
  158.     }
  159.     public function createCommande(
  160.     Request $request,
  161.     Order $commande,
  162.     $listPanierSession,
  163.     StockRepository $stockRepository,
  164.     EntityManagerInterface $entityManager,
  165.     AuthorizationCheckerInterface $authorizationChecker
  166. ) {
  167.     $commande->setDateOrder(\DateTime::createFromFormat('Y-m-d H:i:s', Date('Y-m-d H:i:s')));
  168.     $commande->setCustomer($this->getUser());
  169.     $entityManager->getRepository(Order::class)->add($commande, true);
  170.     $commande->setReforder("RP-CMD-" . $commande->getId());
  171.     $entityManager->getRepository(Order::class)->add($commande, true);
  172.     // ── COUPON ───────────────────────────────────────────────────────────
  173.     $couponData = $request->getSession()->get('coupon');
  174.     // ── Calculer le prix unitaire correct selon rôle + quantité ──────────
  175.     $getPrixUnitaire = function (
  176.         $priceProduct,
  177.         int $quantity,
  178.         AuthorizationCheckerInterface $authorizationChecker
  179.     ): float {
  180.         if ($authorizationChecker->isGranted('ROLE_COM')) {
  181.             return $priceProduct->getPriceCustomer();
  182.         }
  183.         if ($authorizationChecker->isGranted('ROLE_CUSTOMER')) {
  184.             return $priceProduct->getPriceCustomer();
  185.         }
  186.         return $priceProduct->getPriceCustomer();
  187.     };
  188.     // ── Total brut (nécessaire pour répartir la remise coupon) ────────────
  189.     $totalBrut = 0.0;
  190.     if ($couponData) {
  191.         foreach ($listPanierSession as $item) {
  192.             $pp  = $entityManager->getRepository(PriceProduct::class)->getPriceProduct(
  193.                 $entityManager->getRepository(Product::class)->find($item['produit']->getId())
  194.             );
  195.             $qty = 1;
  196.             // Priorité : override_price (quantité modifiée côté JS/AJAX)
  197.             $pu = isset($item['override_price'])
  198.                 ? (float) $item['override_price']
  199.                 : $getPrixUnitaire($pp, $qty, $authorizationChecker);
  200.             $totalBrut += $pu * $qty;
  201.         }
  202.     }
  203.     // ── Traitement des lignes de commande ─────────────────────────────────
  204.     $listPanierValider    = [];
  205.     $listPanierNonValider = [];
  206.     for ($incr = 0; $incr < count($listPanierSession); $incr++) {
  207.         $item    = $listPanierSession[$incr];
  208.         $product = $entityManager->getRepository(Product::class)->find($item['produit']->getId());
  209.         $pp      = $entityManager->getRepository(PriceProduct::class)->getPriceProduct($product);
  210.         $qty     = 1;
  211.         $item['number'] = 1;
  212.         // ── Prix unitaire : override JS/AJAX en priorité, sinon calcul rôle ──
  213.         $prixUnitaire = isset($item['override_price'])
  214.             ? (float) $item['override_price']
  215.             : $getPrixUnitaire($pp, $qty, $authorizationChecker);
  216.         // ── Remise coupon répartie proportionnellement ────────────────────
  217.         if ($couponData && $totalBrut > 0) {
  218.             $ligneBrut      = $prixUnitaire * $qty;
  219.             $ratio          = $ligneBrut / $totalBrut;
  220.             $remiseUnitaire = round(($couponData['discount'] * $ratio) / $qty, 4);
  221.             $prixUnitaire   = round($prixUnitaire - $remiseUnitaire, 4);
  222.         }
  223.         // ── Création de la ligne DetailsOrders ───────────────────────────
  224.         $newDetailsOrders = new DetailsOrders();
  225.         $newDetailsOrders->setIdorder($commande);
  226.         $newDetailsOrders->setIdproduct($product);
  227.         $newDetailsOrders->setQuantity($qty);
  228.         $newDetailsOrders->setPrixUnitaire($prixUnitaire);
  229.         $newDetailsOrders->setState(0);
  230.         $newDetailsOrders->setMotif("");
  231.         $entityManager->getRepository(DetailsOrders::class)->add($newDetailsOrders, true);
  232.         // ── Mise à jour du stock ──────────────────────────────────────────
  233.         $listPanierValider[] = $item;
  234.     }
  235.     // ── COUPON : persister sur la commande + incrémenter usage ───────────
  236.     if ($couponData && !empty($listPanierValider)) {
  237.         $commande->setCouponRef($couponData['ref']);
  238.         $commande->setDiscountAmount((float) $couponData['discount']);
  239.         $commande->setTotalAfterDiscount(round($totalBrut - $couponData['discount'], 2));
  240.         $entityManager->getRepository(Order::class)->add($commande, true);
  241.         $coupon = $entityManager->getRepository(\App\Entity\Coupon::class)->find($couponData['id']);
  242.         if ($coupon) {
  243.             $coupon->incrementUsageCount();
  244.             $entityManager->flush();
  245.         }
  246.         $request->getSession()->remove('coupon');
  247.     }
  248.     // ── Résultats en session pour affichage ──────────────────────────────
  249.     $request->getSession()->set("panier_valider", $listPanierValider);
  250.     $request->getSession()->set("panier_non_valider", $listPanierNonValider);
  251. }
  252.     public function validerCommande(
  253.         $arrayresult,
  254.         $form,
  255.         $user,
  256.         $session,
  257.         &$listPanierSession,
  258.         Request $request,
  259.         StockRepository $stockRepository,
  260.         UserPasswordEncoderInterface $passwordEncoder,
  261.         EntityManagerInterface $entityManager,
  262.         UserPlatformRepository $userPlatformRepository,
  263.         AuthorizationCheckerInterface $authorizationChecker
  264.     ) {
  265.         $form->handleRequest($request);
  266.         if ($form->isSubmitted() && $form->isValid()) {
  267.             try {
  268.                 $commande = new Order();
  269.                 $commande->setState(0);
  270.                 if (null == $this->getUser()) {
  271.                     $createUser = $this->createUser($form, $user, $arrayresult, $request, $passwordEncoder, $userPlatformRepository);
  272.                     if (0 === $createUser) {
  273.                         $this->createCommande($request, $commande, $listPanierSession, $stockRepository, $entityManager, $authorizationChecker);
  274.                     }
  275.                 } else {
  276.                     $this->createCommande($request, $commande, $listPanierSession, $stockRepository, $entityManager, $authorizationChecker);
  277.                 }
  278.                 $session->set('listPanier', []);
  279.                 $listPanierSession = [];
  280.             } catch (Exception $exc) {
  281.                 return $this->render('frontView/error.html.twig', [
  282.                     'msg' => $exc->getMessage(),
  283.                 ]);
  284.             }
  285.         }
  286.     }
  287.     /**
  288.      * @Route("/panier/{product}", name="app_product_panier", methods={"GET", "POST"})
  289.      */
  290.     public function addPanier(
  291.         Request $request,
  292.         ProductRepository $productRepository,
  293.         StockRepository $stockRepository,
  294.         Product $product,
  295.         EntityManagerInterface $entityManager
  296.     ): Response {
  297.         //controle si l'utilisateur est membre
  298.         $isMember = false;
  299.         $listPanier = [];
  300.         $arrayresult = array("error"=>false,"msg"=>"");
  301.         $user = new UserPlatform();
  302.         $availableStock = $stockRepository->getAvailableStock($product);
  303.         // If RENT → ask dates
  304.         if ($product->getStatetype() === 2) {
  305.             if ($availableStock <= 0) {
  306.                 // $reponse = $stockRepository->addProductIntoOrder($product, 1);
  307.                 $reponse = "Stock disponible 0";
  308.                 return $this->render('/frontView/product/index.html.twig', [
  309.                     'products' => $productRepository->findAll(),
  310.                     'temoin' => $product->getId(),
  311.                     'message' => $reponse
  312.                 ]);
  313.             }
  314.             return $this->redirectToRoute('app_product_rent', [
  315.                 'product' => $product->getId()
  316.             ]);
  317.         }
  318.         
  319.         if (null == $this->getUser()) {
  320.             //recupérer le session list panier si existe
  321.             $price_product = $entityManager->getRepository(PriceProduct::class)->getPriceProduct($product);
  322.             $formatPanier = array('produit'=>$product,'number'=>1, 'price_product'=>$price_product);
  323.             $session = $request->getSession();
  324.             $listPanierSession = $session->get('listPanier');
  325.             if (null == $listPanierSession) {
  326.                 $isMember = "la session panier n'est pas creer";
  327.                 $listPanier = array();
  328.                 $reponse = $stockRepository->addProductIntoOrder($product, 1);
  329.                 if ('' === $reponse) {
  330.                     array_push($listPanier, $formatPanier);
  331.                 } else {
  332.                     return $this->render('/frontView/product/index.html.twig', [
  333.                         'products' => $productRepository->findAll(),
  334.                         'temoin' => $product->getId(),
  335.                         'message' => $reponse
  336.                     ]);
  337.                 }
  338.                 $session->set('listPanier', $listPanier);
  339.                 $listPanierSession = $listPanier;
  340.             } else {
  341.                 $verificationBasket = new ProductUtility();
  342.                 $controlProd = $verificationBasket->isProductInBasket($listPanierSession, $product);
  343.                 if ($controlProd['inBasket']) {
  344.                     $c = 1;
  345.                     $reponse = $stockRepository->addProductIntoOrder($product, $c);
  346.                     if ('' === $reponse) {
  347.                         $listPanierSession[$controlProd['indice']]['number'] = 1;
  348.                     } else {
  349.                         return $this->render('/frontView/product/index.html.twig', [
  350.                             'products' => $productRepository->findAll(),
  351.                             'temoin' => $product->getId(),
  352.                             'message' => $reponse.". Vous avez déjà ".$listPanierSession[$controlProd['indice']]['number']." dans votre panier"
  353.                         ]);
  354.                     }
  355.                 } else {
  356.                     $reponse = $stockRepository->addProductIntoOrder($product, 1);
  357.                     if ('' === $reponse) {
  358.                         array_push($listPanierSession, $formatPanier);
  359.                     } else {
  360.                         return $this->render('/frontView/product/index.html.twig', [
  361.                             'products' => $productRepository->findAll(),
  362.                             'temoin' => $product->getId(),
  363.                             'message' => $reponse
  364.                         ]);
  365.                     }
  366.                 }
  367.                 $session->set('listPanier', $listPanierSession);
  368.             }
  369.             $form = $this->createForm(UserMultilType::class, $user);
  370.         } else {
  371.             //traitement pour voir les commandes du client
  372.             $price_product = $entityManager->getRepository(PriceProduct::class)->getPriceProduct($product);
  373.             $formatPanier = array('produit'=>$product,'number'=>1, 'price_product'=>$price_product);
  374.             $session = $request->getSession();
  375.             $listPanierSession = $session->get('listPanier');
  376.             if (null == $listPanierSession) {
  377.                 $isMember = "la session panier n'est pas creer";
  378.                 $listPanier = array();
  379.                 $reponse = $stockRepository->addProductIntoOrder($product, 1);
  380.                 if ('' === $reponse) {
  381.                     array_push($listPanier, $formatPanier);
  382.                 } else {
  383.                     return $this->render('/frontView/product/index.html.twig', [
  384.                         'products' => $productRepository->findAll(),
  385.                         'temoin' => $product->getId(),
  386.                         'message' => $reponse
  387.                     ]);
  388.                 }
  389.                 $session->set('listPanier', $listPanier);
  390.                 $listPanierSession = $listPanier;
  391.             } else {
  392.                 $verificationBasket = new ProductUtility();
  393.                 $controlProd = $verificationBasket->isProductInBasket($listPanierSession, $product);
  394.                 if ($controlProd['inBasket']) {
  395.                     $c = 1;
  396.                     $reponse = $stockRepository->addProductIntoOrder($product, $c);
  397.                     if ('' === $reponse) {
  398.                         $listPanierSession[$controlProd['indice']]['number'] = 1;
  399.                     } else {
  400.                         return $this->render('/frontView/product/index.html.twig', [
  401.                             'products' => $productRepository->findAll(),
  402.                             'temoin' => $product->getId(),
  403.                             'message' => $reponse.". Vous avez déjà ".$listPanierSession[$controlProd['indice']]['number']." dans votre panier"
  404.                         ]);
  405.                     }
  406.                 } else {
  407.                     $reponse = $stockRepository->addProductIntoOrder($product, 1);//Stock disponible 0
  408.                     if ('' === $reponse) {
  409.                         array_push($listPanierSession, $formatPanier);
  410.                     } else {
  411.                         return $this->render('/frontView/product/index.html.twig', [
  412.                             'products' => $productRepository->findAll(),
  413.                             'temoin' => $product->getId(),
  414.                             'message' => $reponse
  415.                         ]);
  416.                     }
  417.                 }
  418.                 //array_push($listPanierSession,$formatPanier);
  419.                 $session->set('listPanier', $listPanierSession);
  420.             }
  421.             $form = $this->createForm(CommandeValideType::class, null);
  422.         }
  423.         return $this->redirectToRoute('app_product_list_panier');
  424.         // $form->handleRequest($request);
  425.         // if ($form->isSubmitted() && $form->isValid()) {
  426.         //     try{
  427.         //         $commande = new Order();
  428.         //         $commande->setState(0);
  429.         //         if($this->getUser() == null){
  430.         //             if($user->getPassword() != $form->get('confirmpass')->getData()){
  431.         //                     $arrayresult['error'] = true;
  432.         //                     $arrayresult['msg'] = "Mot de passe non confirmé.";
  433.         //                 } else if(strpos($user->getEmail()," ")){
  434.         //                     $arrayresult['error'] = true;
  435.         //                     $arrayresult['msg'] = "l'identifiant \"".$user->getEmail()."\" ne doit pas contenir un espace.";
  436.         //                 }
  437.         //                 else if(strlen($user->getEmail()) < 5){
  438.         //                     $arrayresult['error'] = true;
  439.         //                     $arrayresult['msg'] = "l'identifiant \"".$user->getEmail()."\" doit contenir plus de 5 caracteres.";
  440.         //                 }
  441.         //                 else {
  442.         //                     $user->setRoles(["ROLE_CUSTOMER"]);
  443.         //                     $user->setPassword(
  444.         //                     $passwordEncoder->encodePassword($user, $user->getPassword()));
  445.         //                     $userPlatformRepository->add($user, true);
  446.         //                     //Authentification
  447.         //                     $token = new UsernamePasswordToken($user, $user->getPassword(), "public", $user->getRoles());
  448.         //                     $this->get("security.token_storage")->setToken($token);
  449.         //                     $event = new InteractiveLoginEvent($request, $token);
  450.         //                     //$this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
  451.         //                     //creation commande
  452.         //                     $commande->setDateOrder(\DateTime::createFromFormat('Y-m-d H:i:s',Date('Y-m-d H:i:s')));
  453.         //                     $commande->setCustomer($user);
  454.         //                     $save = $entityManager->getRepository(Order::class)->add($commande,true);
  455.         //                     $session = $request->getSession();
  456.         //                     $listPanierSession = $session->get('listPanier');
  457.         //                     for($incr = 0 ; $incr < count($listPanierSession) ; $incr++){
  458.         //                         $newDetailsOrders = new DetailsOrders();
  459.         //                         $newDetailsOrders->setIdorder($commande);
  460.         //                         $product = $entityManager->getRepository(Product::class)->find($listPanierSession[$incr]['produit']->getId());
  461.         //                         $newDetailsOrders->setIdproduct($product);
  462.         //                         $newDetailsOrders->setQuantity($listPanierSession[$incr]['number']);
  463.         //                         $entityManager->getRepository(DetailsOrders::class)->add($newDetailsOrders,true);
  464.         //                     }
  465.         //                     //return $this->redirectToRoute('app_login', [], Response::HTTP_SEE_OTHER);
  466.         //                 }
  467.         //         }
  468.         //         else {
  469.         //             //$commande = new Order();
  470.         //             $commande->setDateOrder(\DateTime::createFromFormat('Y-m-d H:i:s',Date('Y-m-d H:i:s')));
  471.         //             $commande->setCustomer($this->getUser());
  472.         //             $save = $entityManager->getRepository(Order::class)->add($commande,true);
  473.         //             $session = $request->getSession();
  474.         //             $listPanierSession = $session->get('listPanier');
  475.         //             for($incr = 0 ; $incr < count($listPanierSession) ; $incr++){
  476.         //                 $newDetailsOrders = new DetailsOrders();
  477.         //                 $newDetailsOrders->setIdorder($commande);
  478.         //                 $product = $entityManager->getRepository(Product::class)->find($listPanierSession[$incr]['produit']->getId());
  479.         //                 $newDetailsOrders->setIdproduct($product);
  480.         //                 $newDetailsOrders->setQuantity($listPanierSession[$incr]['number']);
  481.         //                 $entityManager->getRepository(DetailsOrders::class)->add($newDetailsOrders,true);
  482.         //             }
  483.         //             //$arrayresult = array("error"=>true,"msg"=>"test");
  484.         //         }
  485.         //         $session->set('listPanier',[]);
  486.         //         $listPanierSession = [];
  487.         //     }
  488.         //     catch(Exception $exc){
  489.         //         return $this->render('frontView/error.html.twig', [
  490.         //                 'msg' => $exc->getMessage(),
  491.         //         ]);
  492.         //     }
  493.         // }
  494.         // return $this->renderForm('frontView/product/addpanier.html.twig', [
  495.         //     'listPanier' => $listPanierSession,
  496.         //     'arrayresult' => $arrayresult,
  497.         //     'form' => $form,
  498.         // ]);
  499.     }
  500.     /**
  501.      * @Route("/panier/rent/{product}", name="app_product_rent")
  502.      */
  503.     public function rentProduct(
  504.         Request $request,
  505.         Product $product,
  506.         EntityManagerInterface $entityManager,
  507.         StockRepository $stockRepository
  508.     ): Response {
  509.         // Safety check
  510.         if ($product->getStatetype() !== 2) {
  511.             return $this->redirectToRoute('app_product_panier', [
  512.                 'product' => $product->getId()
  513.             ]);
  514.         }
  515.         $form = $this->createForm(RentProductType::class);
  516.         $form->handleRequest($request);
  517.         if ($form->isSubmitted() && $form->isValid()) {
  518.             $data = $form->getData();
  519.             // Date validation
  520.             if ($data['endDate'] <= $data['startDate']) {
  521.                 $this->addFlash('error', 'La date de fin doit être postérieure à la date de début.');
  522.                 return $this->redirectToRoute('app_product_rent', [
  523.                     'product' => $product->getId()
  524.                 ]);
  525.             }
  526.             $session = $request->getSession();
  527.             $listPanier = $session->get('listPanier', []);
  528.             // Prevent duplicate rental of same product
  529.             foreach ($listPanier as $item) {
  530.                 if (
  531.                     $item['produit']->getId() === $product->getId()
  532.                     && isset($item['rent'])
  533.                 ) {
  534.                     $productName = $item['produit']->getTitle();
  535.                     $this->addFlash('error', "Le produit \"$productName\" est déjà loué dans votre panier");
  536.                     // return $this->redirectToRoute('app_product_list_panier');
  537.                     return $this->redirectToRoute('app_product_rent', [
  538.                     'product' => $product->getId()
  539.                 ]);
  540.                 }
  541.             }
  542.             $price_product = $entityManager
  543.                 ->getRepository(PriceProduct::class)
  544.                 ->getPriceProduct($product);
  545.             $listPanier[] = [
  546.                 'produit' => $product,
  547.                 'number' => 1,
  548.                 'price_product' => $price_product,
  549.                 'rent' => [
  550.                     'startDate' => $data['startDate'],
  551.                     'endDate' => $data['endDate'],
  552.                 ],
  553.             ];
  554.             $session->set('listPanier', $listPanier);
  555.             /*Add to db*/
  556.             // Prevent overlapping rentals
  557.             $existing = $entityManager->getRepository(Location::class)
  558.                 ->findOneBy([
  559.                     'product' => $product,
  560.                     'status' => 'active'
  561.                 ]);
  562.             if ($existing) {
  563.                 $this->addFlash('error', 'Ce produit est déjà loué.');
  564.                 // return $this->redirectToRoute('app_product_list');
  565.                 return $this->redirectToRoute('app_product_rent', [
  566.                     'product' => $product->getId()
  567.                 ]);
  568.             }
  569.             $location = new Location();
  570.             $location->setProduct($product);
  571.             $location->setUser($this->getUser());
  572.             $location->setStartDate($data['startDate']);
  573.             $location->setEndDate($data['endDate']);
  574.             $location->setCreatedAt(\DateTime::createFromFormat('Y-m-d H:i:s', Date('Y-m-d H:i:s')));
  575.             $location->setStatus('active');
  576.             // Optional price calculation
  577.             $days = $data['startDate']->diff($data['endDate'])->days;
  578.             $location->setPrice($days * $product->getPriceProducts()[0]->getPriceCustomer());
  579.             $entityManager->persist($location);
  580.             $entityManager->flush();
  581.             $this->addFlash('success', 'Location enregistrée avec succès');
  582.             return $this->redirectToRoute('app_product_list_panier');
  583.         }
  584.         return $this->render('frontView/product/rent.html.twig', [
  585.             'product' => $product,
  586.             'form' => $form->createView(),
  587.         ]);
  588.     }
  589.     /**
  590.      * @Route("/panier-remove", name="app_product_panier_remove", methods={"GET", "POST"})
  591.      */
  592.     public function removePanier(
  593.         Request $request
  594.     ): Response {
  595.         $session = $request->getSession();
  596.         $session->set('listPanier', []);
  597.         return $this->redirectToRoute('app_product_list_panier', [], Response::HTTP_SEE_OTHER);
  598.     }
  599.     /**
  600.      * @Route("/panier-product-remove/{productID}", name="app_product_panier_product_remove", methods={"GET"})
  601.      */
  602.     public function removeProductInPanier(
  603.         Request $request,
  604.         int $productID,
  605.         ProductRepository $productRepository
  606.     ): Response {
  607.         $session = $request->getSession();
  608.         $paniers = $session->get('listPanier');
  609.         if ($paniers) {
  610.             for ($i = 0; $i< count($paniers); $i++) {
  611.                 $panier = $paniers[$i];
  612.                 if ($panier['produit']->getId() === $productID) {
  613.                     $product = $productRepository->find($productID);
  614.                     $verificationBasket = new ProductUtility();
  615.                     $controlProd = $verificationBasket->isProductInBasket($paniers, $product);
  616.                     if ($controlProd['inBasket']) {
  617.                         unset($paniers[$i]);
  618.                         $paniers = array_values($paniers);
  619.                     }
  620.                 }
  621.             }
  622.         }
  623.         $session->set('listPanier', $paniers);
  624.         return $this->redirectToRoute('app_product_list_panier', [], Response::HTTP_SEE_OTHER);
  625.     }
  626.     /**
  627.      * @Route("/list-panier", name="app_product_list_panier", methods={"GET", "POST"})
  628.      */
  629.     public function listPanier(
  630.         Request $request,
  631.         UserPasswordEncoderInterface $passwordEncoder,
  632.         EntityManagerInterface $entityManager,
  633.         StockRepository $stockRepository,
  634.         UserPlatformRepository $userPlatformRepository,
  635.         LocationRepository $locationRepository,
  636.         AuthorizationCheckerInterface $authorizationChecker
  637.     ): Response {
  638.         $arrayresult = array("error"=>false,"msg"=>"");
  639.         $session = $request->getSession();
  640.         $listPanierSession = $session->get('listPanier');
  641.         if (is_array($listPanierSession)) {
  642.             foreach ($listPanierSession as &$panierItem) {
  643.                 $panierItem['number'] = 1;
  644.             }
  645.             unset($panierItem);
  646.             $session->set('listPanier', $listPanierSession);
  647.         }
  648.         $listPanierValider = null;
  649.         $listPanierNonValider = null;
  650.         $user = new UserPlatform();
  651.         if (null == $this->getUser()) {
  652.             $form = $this->createForm(UserMultilType::class, $user);
  653.         } else {
  654.             $form = $this->createForm(CommandeValideType::class, null);
  655.         }
  656.         $this->validerCommande($arrayresult, $form, $user, $session, $listPanierSession, $request, $stockRepository, $passwordEncoder, $entityManager, $userPlatformRepository, $authorizationChecker);
  657.         // dd($listPanierSession);
  658.         if ($session->get('panier_valider')) {
  659.             $listPanierValider = $session->get('panier_valider');
  660.             $listPanierNonValider = $session->get('panier_non_valider');
  661.             $session->remove('panier_valider');
  662.             $session->remove('panier_non_valider');
  663.         }
  664.         // Remove rent product if not active
  665.         $listPanierSession = $session->get('listPanier', []);
  666.         if ($this->getUser()) {
  667.             $activeLocations = $locationRepository->findBy([
  668.                 'user' => $this->getUser(),
  669.                 'status' => 'active'
  670.             ]);
  671.             $activeProductIds = array_map(
  672.                 fn($loc) => $loc->getProduct()->getId(),
  673.                 $activeLocations
  674.             );
  675.             foreach ($listPanierSession as $key => $item) {
  676.                 if (
  677.                     isset($item['rent']) &&
  678.                     !in_array($item['produit']->getId(), $activeProductIds)
  679.                 ) {
  680.                     unset($listPanierSession[$key]);
  681.                 }
  682.             }
  683.             // Reindex & update session
  684.             $listPanierSession = array_values($listPanierSession);
  685.             $session->set('listPanier', $listPanierSession);
  686.         }
  687.         return $this->renderForm('frontView/product/addpanier.html.twig', [
  688.             'listPanier' => $listPanierSession,
  689.             'listPanierValider' => $listPanierValider,
  690.             'listPanierNonValider' => $listPanierNonValider,
  691.             'arrayresult' => $arrayresult,
  692.             'form' => $form,
  693.         ]);
  694.         /* return $this->renderForm('frontView/product/listcommande.html.twig', [
  695.         ]); */
  696.     }
  697.     /**
  698.      * @Route("/points/{id}", name="app_product_modif", methods={"GET"})
  699.      */
  700.     public function modifPoint(int $id, ProductRepository $productRepository): Response
  701.     {
  702.         $prod = $productRepository->getPoint($id);
  703.         $sommestockinit = 0;
  704.         $sommestockfinal = 0;
  705.         $sommestockinit = $prod['points'];
  706.         $sommestockfinal = $sommestockinit + 1;
  707.         $productRepository->updatePoint($sommestockfinal, $id);
  708.         return $this->redirectToRoute('app_product_show', [
  709.             'id'=>$id,
  710.             'modif'=>'validation'
  711.         ], Response::HTTP_SEE_OTHER);
  712.     }
  713.     
  714.     
  715.     /**
  716.      * @Route("/ajax-random-products", name="ajax_random_products", methods={"GET"})
  717.      */
  718.     public function ajaxRandomProducts(ProductRepository $productRepository): JsonResponse
  719.     {
  720.         $categories = $productRepository->findRandomGroupedByCategory();
  721.         // dd($categories);
  722.         return $this->json($categories);
  723.     }
  724.     
  725.     /**
  726.      * @Route("/{id}/{modif}", name="app_product_show", methods={"GET"})
  727.      */
  728.     public function show(Request $request, Product $product, ProductRepository $productRepository, EntityManagerInterface $em, string $modif = null): Response
  729.     {
  730.         $sommestockinit = 0;
  731.         $sommestockfinal = 0;
  732.         $prod = array();
  733.         // if($this->getUser() != null ){
  734.         // if($modif != "validation"){
  735.         //     if($this->isGranted('ROLE_CUSTOMER')){
  736.         //         return $this->redirectToRoute('app_product_modif', [
  737.         //             'id'=>$product->getId(),
  738.         //         ], Response::HTTP_SEE_OTHER);
  739.         //     }
  740.         // }
  741.         /*if($this->isGranted('ROLE_CUSTOMER')){
  742.             $prod = $productRepository->getPoint($id);
  743.             $sommestockinit = 0;
  744.             $sommestockfinal = 0;
  745.             $sommestockinit = $prod['points'];
  746.             $sommestockfinal = $sommestockinit + 1;
  747.             $productRepository->updatePoint($sommestockfinal,$id);
  748.         }*/
  749.         /*if($this->isGranted('ROLE_CUSTOMER')){
  750.             $prod = $entityManager->getRepository(Product::class)->getPoint($id);
  751.             $sommestockinit = 0;
  752.             $sommestockfinal = 0;
  753.             $sommestockinit = $prod['points'];
  754.             $sommestockfinal = $sommestockinit + 1;
  755.             $productRepository->updatePoint($sommestockfinal,$id);
  756.             $entityManager->getRepository(Product::class)->updatePoint($sommestockfinal,$id);
  757.         }*/
  758.         // }
  759.         //$product = $productRepository->find($id);
  760.         // if ($request->getMethod() === 'GET') {
  761.         //     $product->setPoints($product->getPoints() + 1);
  762.         //     $em->flush();
  763.         // }
  764.         // If coming from suggestion
  765.         if ($request->query->get('fromSearch')) {
  766.             $product->setSearchCount($product->getSearchCount() + 1);
  767.         }
  768.         $em->flush();
  769.         
  770.         return $this->render('frontView/product/show.html.twig', [
  771.             'product' => $product,
  772.             'sommestockinit' => $sommestockinit,
  773.             'sommestockfinal' => $sommestockfinal,
  774.             'type'=> $product->getStatetype(),//getStatetype() !== 1
  775.             'prod' => $prod,
  776.         ]);
  777.     }
  778.     
  779.     /**
  780.      * @Route("/{id}/click", name="app_product_click", methods={"POST"})
  781.      */
  782.     public function click(
  783.         Request $request,
  784.         Product $product,
  785.         EntityManagerInterface $em
  786.     ): JsonResponse {
  787.         $product->setPoints($product->getPoints() + 1);
  788.         // Increment search count only if coming from search
  789.         /*if ($request->query->get('fromSearch')) {
  790.             $product->setSearchCount($product->getSearchCount() + 1);
  791.         }*/
  792.         $em->flush();
  793.         return new JsonResponse(['ok' => true]);
  794.     }
  795.     /**
  796.      * @Route("/{id}/click-search", name="app_product_click_search", methods={"POST"})
  797.      */
  798.     public function clickSearch(
  799.         Request $request,
  800.         Product $product,
  801.         EntityManagerInterface $em
  802.     ): JsonResponse {
  803.         // Increment search count only if coming from search
  804.         if ($request->query->get('fromSearch')) {
  805.             $product->setSearchCount($product->getSearchCount() + 1);
  806.         }
  807.         $em->flush();
  808.         return new JsonResponse(['ok' => true]);
  809.     }
  810. }