src/Controller/FrontController/ProductController.php line 705

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->getEffectivePriceCustomer();
  182.         }
  183.         if ($authorizationChecker->isGranted('ROLE_CUSTOMER')) {
  184.             return $priceProduct->getEffectivePriceCustomer();
  185.         }
  186.         return $priceProduct->getEffectivePriceCustomer();
  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 ($product->getStatetype() === 2 && ($product->getStatdispo() === 3 || $availableStock <= 0)) {
  304.             return $this->render('/frontView/product/index.html.twig', [
  305.                 'products' => $productRepository->findAll(),
  306.                 'temoin' => $product->getId(),
  307.                 'message' => 'Ce produit est en rupture de stock.',
  308.             ]);
  309.         }
  310.         // Les locations utilisent le type historique 99. Le type 2 correspond aux produits physiques.
  311.         if ($product->getStatetype() === 99) {
  312.             if ($availableStock <= 0) {
  313.                 // $reponse = $stockRepository->addProductIntoOrder($product, 1);
  314.                 $reponse = "Stock disponible 0";
  315.                 return $this->render('/frontView/product/index.html.twig', [
  316.                     'products' => $productRepository->findAll(),
  317.                     'temoin' => $product->getId(),
  318.                     'message' => $reponse
  319.                 ]);
  320.             }
  321.             return $this->redirectToRoute('app_product_rent', [
  322.                 'product' => $product->getId()
  323.             ]);
  324.         }
  325.         
  326.         if (null == $this->getUser()) {
  327.             //recupérer le session list panier si existe
  328.             $price_product = $entityManager->getRepository(PriceProduct::class)->getPriceProduct($product);
  329.             $formatPanier = array('produit'=>$product,'number'=>1, 'price_product'=>$price_product);
  330.             $session = $request->getSession();
  331.             $listPanierSession = $session->get('listPanier');
  332.             if (null == $listPanierSession) {
  333.                 $isMember = "la session panier n'est pas creer";
  334.                 $listPanier = array();
  335.                 $reponse = $stockRepository->addProductIntoOrder($product, 1);
  336.                 if ('' === $reponse) {
  337.                     array_push($listPanier, $formatPanier);
  338.                 } else {
  339.                     return $this->render('/frontView/product/index.html.twig', [
  340.                         'products' => $productRepository->findAll(),
  341.                         'temoin' => $product->getId(),
  342.                         'message' => $reponse
  343.                     ]);
  344.                 }
  345.                 $session->set('listPanier', $listPanier);
  346.                 $listPanierSession = $listPanier;
  347.             } else {
  348.                 $verificationBasket = new ProductUtility();
  349.                 $controlProd = $verificationBasket->isProductInBasket($listPanierSession, $product);
  350.                 if ($controlProd['inBasket']) {
  351.                     $c = 1;
  352.                     $reponse = $stockRepository->addProductIntoOrder($product, $c);
  353.                     if ('' === $reponse) {
  354.                         $listPanierSession[$controlProd['indice']]['number'] = 1;
  355.                     } else {
  356.                         return $this->render('/frontView/product/index.html.twig', [
  357.                             'products' => $productRepository->findAll(),
  358.                             'temoin' => $product->getId(),
  359.                             'message' => $reponse.". Vous avez déjà ".$listPanierSession[$controlProd['indice']]['number']." dans votre panier"
  360.                         ]);
  361.                     }
  362.                 } else {
  363.                     $reponse = $stockRepository->addProductIntoOrder($product, 1);
  364.                     if ('' === $reponse) {
  365.                         array_push($listPanierSession, $formatPanier);
  366.                     } else {
  367.                         return $this->render('/frontView/product/index.html.twig', [
  368.                             'products' => $productRepository->findAll(),
  369.                             'temoin' => $product->getId(),
  370.                             'message' => $reponse
  371.                         ]);
  372.                     }
  373.                 }
  374.                 $session->set('listPanier', $listPanierSession);
  375.             }
  376.             $form = $this->createForm(UserMultilType::class, $user);
  377.         } else {
  378.             //traitement pour voir les commandes du client
  379.             $price_product = $entityManager->getRepository(PriceProduct::class)->getPriceProduct($product);
  380.             $formatPanier = array('produit'=>$product,'number'=>1, 'price_product'=>$price_product);
  381.             $session = $request->getSession();
  382.             $listPanierSession = $session->get('listPanier');
  383.             if (null == $listPanierSession) {
  384.                 $isMember = "la session panier n'est pas creer";
  385.                 $listPanier = array();
  386.                 $reponse = $stockRepository->addProductIntoOrder($product, 1);
  387.                 if ('' === $reponse) {
  388.                     array_push($listPanier, $formatPanier);
  389.                 } else {
  390.                     return $this->render('/frontView/product/index.html.twig', [
  391.                         'products' => $productRepository->findAll(),
  392.                         'temoin' => $product->getId(),
  393.                         'message' => $reponse
  394.                     ]);
  395.                 }
  396.                 $session->set('listPanier', $listPanier);
  397.                 $listPanierSession = $listPanier;
  398.             } else {
  399.                 $verificationBasket = new ProductUtility();
  400.                 $controlProd = $verificationBasket->isProductInBasket($listPanierSession, $product);
  401.                 if ($controlProd['inBasket']) {
  402.                     $c = 1;
  403.                     $reponse = $stockRepository->addProductIntoOrder($product, $c);
  404.                     if ('' === $reponse) {
  405.                         $listPanierSession[$controlProd['indice']]['number'] = 1;
  406.                     } else {
  407.                         return $this->render('/frontView/product/index.html.twig', [
  408.                             'products' => $productRepository->findAll(),
  409.                             'temoin' => $product->getId(),
  410.                             'message' => $reponse.". Vous avez déjà ".$listPanierSession[$controlProd['indice']]['number']." dans votre panier"
  411.                         ]);
  412.                     }
  413.                 } else {
  414.                     $reponse = $stockRepository->addProductIntoOrder($product, 1);//Stock disponible 0
  415.                     if ('' === $reponse) {
  416.                         array_push($listPanierSession, $formatPanier);
  417.                     } else {
  418.                         return $this->render('/frontView/product/index.html.twig', [
  419.                             'products' => $productRepository->findAll(),
  420.                             'temoin' => $product->getId(),
  421.                             'message' => $reponse
  422.                         ]);
  423.                     }
  424.                 }
  425.                 //array_push($listPanierSession,$formatPanier);
  426.                 $session->set('listPanier', $listPanierSession);
  427.             }
  428.             $form = $this->createForm(CommandeValideType::class, null);
  429.         }
  430.         return $this->redirectToRoute('app_product_list_panier');
  431.         // $form->handleRequest($request);
  432.         // if ($form->isSubmitted() && $form->isValid()) {
  433.         //     try{
  434.         //         $commande = new Order();
  435.         //         $commande->setState(0);
  436.         //         if($this->getUser() == null){
  437.         //             if($user->getPassword() != $form->get('confirmpass')->getData()){
  438.         //                     $arrayresult['error'] = true;
  439.         //                     $arrayresult['msg'] = "Mot de passe non confirmé.";
  440.         //                 } else if(strpos($user->getEmail()," ")){
  441.         //                     $arrayresult['error'] = true;
  442.         //                     $arrayresult['msg'] = "l'identifiant \"".$user->getEmail()."\" ne doit pas contenir un espace.";
  443.         //                 }
  444.         //                 else if(strlen($user->getEmail()) < 5){
  445.         //                     $arrayresult['error'] = true;
  446.         //                     $arrayresult['msg'] = "l'identifiant \"".$user->getEmail()."\" doit contenir plus de 5 caracteres.";
  447.         //                 }
  448.         //                 else {
  449.         //                     $user->setRoles(["ROLE_CUSTOMER"]);
  450.         //                     $user->setPassword(
  451.         //                     $passwordEncoder->encodePassword($user, $user->getPassword()));
  452.         //                     $userPlatformRepository->add($user, true);
  453.         //                     //Authentification
  454.         //                     $token = new UsernamePasswordToken($user, $user->getPassword(), "public", $user->getRoles());
  455.         //                     $this->get("security.token_storage")->setToken($token);
  456.         //                     $event = new InteractiveLoginEvent($request, $token);
  457.         //                     //$this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
  458.         //                     //creation commande
  459.         //                     $commande->setDateOrder(\DateTime::createFromFormat('Y-m-d H:i:s',Date('Y-m-d H:i:s')));
  460.         //                     $commande->setCustomer($user);
  461.         //                     $save = $entityManager->getRepository(Order::class)->add($commande,true);
  462.         //                     $session = $request->getSession();
  463.         //                     $listPanierSession = $session->get('listPanier');
  464.         //                     for($incr = 0 ; $incr < count($listPanierSession) ; $incr++){
  465.         //                         $newDetailsOrders = new DetailsOrders();
  466.         //                         $newDetailsOrders->setIdorder($commande);
  467.         //                         $product = $entityManager->getRepository(Product::class)->find($listPanierSession[$incr]['produit']->getId());
  468.         //                         $newDetailsOrders->setIdproduct($product);
  469.         //                         $newDetailsOrders->setQuantity($listPanierSession[$incr]['number']);
  470.         //                         $entityManager->getRepository(DetailsOrders::class)->add($newDetailsOrders,true);
  471.         //                     }
  472.         //                     //return $this->redirectToRoute('app_login', [], Response::HTTP_SEE_OTHER);
  473.         //                 }
  474.         //         }
  475.         //         else {
  476.         //             //$commande = new Order();
  477.         //             $commande->setDateOrder(\DateTime::createFromFormat('Y-m-d H:i:s',Date('Y-m-d H:i:s')));
  478.         //             $commande->setCustomer($this->getUser());
  479.         //             $save = $entityManager->getRepository(Order::class)->add($commande,true);
  480.         //             $session = $request->getSession();
  481.         //             $listPanierSession = $session->get('listPanier');
  482.         //             for($incr = 0 ; $incr < count($listPanierSession) ; $incr++){
  483.         //                 $newDetailsOrders = new DetailsOrders();
  484.         //                 $newDetailsOrders->setIdorder($commande);
  485.         //                 $product = $entityManager->getRepository(Product::class)->find($listPanierSession[$incr]['produit']->getId());
  486.         //                 $newDetailsOrders->setIdproduct($product);
  487.         //                 $newDetailsOrders->setQuantity($listPanierSession[$incr]['number']);
  488.         //                 $entityManager->getRepository(DetailsOrders::class)->add($newDetailsOrders,true);
  489.         //             }
  490.         //             //$arrayresult = array("error"=>true,"msg"=>"test");
  491.         //         }
  492.         //         $session->set('listPanier',[]);
  493.         //         $listPanierSession = [];
  494.         //     }
  495.         //     catch(Exception $exc){
  496.         //         return $this->render('frontView/error.html.twig', [
  497.         //                 'msg' => $exc->getMessage(),
  498.         //         ]);
  499.         //     }
  500.         // }
  501.         // return $this->renderForm('frontView/product/addpanier.html.twig', [
  502.         //     'listPanier' => $listPanierSession,
  503.         //     'arrayresult' => $arrayresult,
  504.         //     'form' => $form,
  505.         // ]);
  506.     }
  507.     /**
  508.      * @Route("/panier/rent/{product}", name="app_product_rent")
  509.      */
  510.     public function rentProduct(
  511.         Request $request,
  512.         Product $product,
  513.         EntityManagerInterface $entityManager,
  514.         StockRepository $stockRepository
  515.     ): Response {
  516.         // Safety check
  517.         if ($product->getStatetype() !== 99) {
  518.             return $this->redirectToRoute('app_product_panier', [
  519.                 'product' => $product->getId()
  520.             ]);
  521.         }
  522.         $form = $this->createForm(RentProductType::class);
  523.         $form->handleRequest($request);
  524.         if ($form->isSubmitted() && $form->isValid()) {
  525.             $data = $form->getData();
  526.             // Date validation
  527.             if ($data['endDate'] <= $data['startDate']) {
  528.                 $this->addFlash('error', 'La date de fin doit être postérieure à la date de début.');
  529.                 return $this->redirectToRoute('app_product_rent', [
  530.                     'product' => $product->getId()
  531.                 ]);
  532.             }
  533.             $session = $request->getSession();
  534.             $listPanier = $session->get('listPanier', []);
  535.             // Prevent duplicate rental of same product
  536.             foreach ($listPanier as $item) {
  537.                 if (
  538.                     $item['produit']->getId() === $product->getId()
  539.                     && isset($item['rent'])
  540.                 ) {
  541.                     $productName = $item['produit']->getTitle();
  542.                     $this->addFlash('error', "Le produit \"$productName\" est déjà loué dans votre panier");
  543.                     // return $this->redirectToRoute('app_product_list_panier');
  544.                     return $this->redirectToRoute('app_product_rent', [
  545.                     'product' => $product->getId()
  546.                 ]);
  547.                 }
  548.             }
  549.             $price_product = $entityManager
  550.                 ->getRepository(PriceProduct::class)
  551.                 ->getPriceProduct($product);
  552.             $listPanier[] = [
  553.                 'produit' => $product,
  554.                 'number' => 1,
  555.                 'price_product' => $price_product,
  556.                 'rent' => [
  557.                     'startDate' => $data['startDate'],
  558.                     'endDate' => $data['endDate'],
  559.                 ],
  560.             ];
  561.             $session->set('listPanier', $listPanier);
  562.             /*Add to db*/
  563.             // Prevent overlapping rentals
  564.             $existing = $entityManager->getRepository(Location::class)
  565.                 ->findOneBy([
  566.                     'product' => $product,
  567.                     'status' => 'active'
  568.                 ]);
  569.             if ($existing) {
  570.                 $this->addFlash('error', 'Ce produit est déjà loué.');
  571.                 // return $this->redirectToRoute('app_product_list');
  572.                 return $this->redirectToRoute('app_product_rent', [
  573.                     'product' => $product->getId()
  574.                 ]);
  575.             }
  576.             $location = new Location();
  577.             $location->setProduct($product);
  578.             $location->setUser($this->getUser());
  579.             $location->setStartDate($data['startDate']);
  580.             $location->setEndDate($data['endDate']);
  581.             $location->setCreatedAt(\DateTime::createFromFormat('Y-m-d H:i:s', Date('Y-m-d H:i:s')));
  582.             $location->setStatus('active');
  583.             // Optional price calculation
  584.             $days = $data['startDate']->diff($data['endDate'])->days;
  585.             $location->setPrice($days * $product->getPriceProducts()[0]->getPriceCustomer());
  586.             $entityManager->persist($location);
  587.             $entityManager->flush();
  588.             $this->addFlash('success', 'Location enregistrée avec succès');
  589.             return $this->redirectToRoute('app_product_list_panier');
  590.         }
  591.         return $this->render('frontView/product/rent.html.twig', [
  592.             'product' => $product,
  593.             'form' => $form->createView(),
  594.         ]);
  595.     }
  596.     /**
  597.      * @Route("/panier-remove", name="app_product_panier_remove", methods={"GET", "POST"})
  598.      */
  599.     public function removePanier(
  600.         Request $request
  601.     ): Response {
  602.         $session = $request->getSession();
  603.         $session->set('listPanier', []);
  604.         return $this->redirectToRoute('app_product_list_panier', [], Response::HTTP_SEE_OTHER);
  605.     }
  606.     /**
  607.      * @Route("/panier-product-remove/{productID}", name="app_product_panier_product_remove", methods={"GET"})
  608.      */
  609.     public function removeProductInPanier(
  610.         Request $request,
  611.         int $productID,
  612.         ProductRepository $productRepository
  613.     ): Response {
  614.         $session = $request->getSession();
  615.         $paniers = $session->get('listPanier');
  616.         if ($paniers) {
  617.             for ($i = 0; $i< count($paniers); $i++) {
  618.                 $panier = $paniers[$i];
  619.                 if ($panier['produit']->getId() === $productID) {
  620.                     $product = $productRepository->find($productID);
  621.                     $verificationBasket = new ProductUtility();
  622.                     $controlProd = $verificationBasket->isProductInBasket($paniers, $product);
  623.                     if ($controlProd['inBasket']) {
  624.                         unset($paniers[$i]);
  625.                         $paniers = array_values($paniers);
  626.                     }
  627.                 }
  628.             }
  629.         }
  630.         $session->set('listPanier', $paniers);
  631.         return $this->redirectToRoute('app_product_list_panier', [], Response::HTTP_SEE_OTHER);
  632.     }
  633.     /**
  634.      * @Route("/list-panier", name="app_product_list_panier", methods={"GET", "POST"})
  635.      */
  636.     public function listPanier(
  637.         Request $request,
  638.         UserPasswordEncoderInterface $passwordEncoder,
  639.         EntityManagerInterface $entityManager,
  640.         StockRepository $stockRepository,
  641.         UserPlatformRepository $userPlatformRepository,
  642.         LocationRepository $locationRepository,
  643.         AuthorizationCheckerInterface $authorizationChecker
  644.     ): Response {
  645.         $arrayresult = array("error"=>false,"msg"=>"");
  646.         $session = $request->getSession();
  647.         $listPanierSession = $session->get('listPanier');
  648.         if (is_array($listPanierSession)) {
  649.             foreach ($listPanierSession as &$panierItem) {
  650.                 if ($panierItem['produit']->getStatetype() !== 2) {
  651.                     $panierItem['number'] = 1;
  652.                 }
  653.             }
  654.             unset($panierItem);
  655.             $session->set('listPanier', $listPanierSession);
  656.         }
  657.         $listPanierValider = null;
  658.         $listPanierNonValider = null;
  659.         $user = new UserPlatform();
  660.         if (null == $this->getUser()) {
  661.             $form = $this->createForm(UserMultilType::class, $user);
  662.         } else {
  663.             $form = $this->createForm(CommandeValideType::class, null);
  664.         }
  665.         $this->validerCommande($arrayresult, $form, $user, $session, $listPanierSession, $request, $stockRepository, $passwordEncoder, $entityManager, $userPlatformRepository, $authorizationChecker);
  666.         // dd($listPanierSession);
  667.         if ($session->get('panier_valider')) {
  668.             $listPanierValider = $session->get('panier_valider');
  669.             $listPanierNonValider = $session->get('panier_non_valider');
  670.             $session->remove('panier_valider');
  671.             $session->remove('panier_non_valider');
  672.         }
  673.         // Remove rent product if not active
  674.         $listPanierSession = $session->get('listPanier', []);
  675.         if ($this->getUser()) {
  676.             $activeLocations = $locationRepository->findBy([
  677.                 'user' => $this->getUser(),
  678.                 'status' => 'active'
  679.             ]);
  680.             $activeProductIds = array_map(
  681.                 fn($loc) => $loc->getProduct()->getId(),
  682.                 $activeLocations
  683.             );
  684.             foreach ($listPanierSession as $key => $item) {
  685.                 if (
  686.                     isset($item['rent']) &&
  687.                     !in_array($item['produit']->getId(), $activeProductIds)
  688.                 ) {
  689.                     unset($listPanierSession[$key]);
  690.                 }
  691.             }
  692.             // Reindex & update session
  693.             $listPanierSession = array_values($listPanierSession);
  694.             $session->set('listPanier', $listPanierSession);
  695.         }
  696.         return $this->renderForm('frontView/product/addpanier.html.twig', [
  697.             'listPanier' => $listPanierSession,
  698.             'listPanierValider' => $listPanierValider,
  699.             'listPanierNonValider' => $listPanierNonValider,
  700.             'arrayresult' => $arrayresult,
  701.             'form' => $form,
  702.         ]);
  703.         /* return $this->renderForm('frontView/product/listcommande.html.twig', [
  704.         ]); */
  705.     }
  706.     /**
  707.      * @Route("/points/{id}", name="app_product_modif", methods={"GET"})
  708.      */
  709.     public function modifPoint(int $id, ProductRepository $productRepository): Response
  710.     {
  711.         $prod = $productRepository->getPoint($id);
  712.         $sommestockinit = 0;
  713.         $sommestockfinal = 0;
  714.         $sommestockinit = $prod['points'];
  715.         $sommestockfinal = $sommestockinit + 1;
  716.         $productRepository->updatePoint($sommestockfinal, $id);
  717.         return $this->redirectToRoute('app_product_show', [
  718.             'id'=>$id,
  719.             'modif'=>'validation'
  720.         ], Response::HTTP_SEE_OTHER);
  721.     }
  722.     
  723.     
  724.     /**
  725.      * @Route("/ajax-random-products", name="ajax_random_products", methods={"GET"})
  726.      */
  727.     public function ajaxRandomProducts(ProductRepository $productRepository): JsonResponse
  728.     {
  729.         $categories = $productRepository->findRandomGroupedByCategory();
  730.         // dd($categories);
  731.         return $this->json($categories);
  732.     }
  733.     
  734.     /**
  735.      * @Route("/{id}/{modif}", name="app_product_show", methods={"GET"})
  736.      */
  737.     public function show(Request $request, Product $product, ProductRepository $productRepository, EntityManagerInterface $em, string $modif = null): Response
  738.     {
  739.         $sommestockinit = 0;
  740.         $sommestockfinal = 0;
  741.         $prod = array();
  742.         // if($this->getUser() != null ){
  743.         // if($modif != "validation"){
  744.         //     if($this->isGranted('ROLE_CUSTOMER')){
  745.         //         return $this->redirectToRoute('app_product_modif', [
  746.         //             'id'=>$product->getId(),
  747.         //         ], Response::HTTP_SEE_OTHER);
  748.         //     }
  749.         // }
  750.         /*if($this->isGranted('ROLE_CUSTOMER')){
  751.             $prod = $productRepository->getPoint($id);
  752.             $sommestockinit = 0;
  753.             $sommestockfinal = 0;
  754.             $sommestockinit = $prod['points'];
  755.             $sommestockfinal = $sommestockinit + 1;
  756.             $productRepository->updatePoint($sommestockfinal,$id);
  757.         }*/
  758.         /*if($this->isGranted('ROLE_CUSTOMER')){
  759.             $prod = $entityManager->getRepository(Product::class)->getPoint($id);
  760.             $sommestockinit = 0;
  761.             $sommestockfinal = 0;
  762.             $sommestockinit = $prod['points'];
  763.             $sommestockfinal = $sommestockinit + 1;
  764.             $productRepository->updatePoint($sommestockfinal,$id);
  765.             $entityManager->getRepository(Product::class)->updatePoint($sommestockfinal,$id);
  766.         }*/
  767.         // }
  768.         //$product = $productRepository->find($id);
  769.         // if ($request->getMethod() === 'GET') {
  770.         //     $product->setPoints($product->getPoints() + 1);
  771.         //     $em->flush();
  772.         // }
  773.         // If coming from suggestion
  774.         if ($request->query->get('fromSearch')) {
  775.             $product->setSearchCount($product->getSearchCount() + 1);
  776.         }
  777.         $em->flush();
  778.         
  779.         return $this->render('frontView/product/show.html.twig', [
  780.             'product' => $product,
  781.             'sommestockinit' => $sommestockinit,
  782.             'sommestockfinal' => $sommestockfinal,
  783.             'type'=> $product->getStatetype(),//getStatetype() !== 1
  784.             'prod' => $prod,
  785.         ]);
  786.     }
  787.     
  788.     /**
  789.      * @Route("/{id}/click", name="app_product_click", methods={"POST"})
  790.      */
  791.     public function click(
  792.         Request $request,
  793.         Product $product,
  794.         EntityManagerInterface $em
  795.     ): JsonResponse {
  796.         $product->setPoints($product->getPoints() + 1);
  797.         // Increment search count only if coming from search
  798.         /*if ($request->query->get('fromSearch')) {
  799.             $product->setSearchCount($product->getSearchCount() + 1);
  800.         }*/
  801.         $em->flush();
  802.         return new JsonResponse(['ok' => true]);
  803.     }
  804.     /**
  805.      * @Route("/{id}/click-search", name="app_product_click_search", methods={"POST"})
  806.      */
  807.     public function clickSearch(
  808.         Request $request,
  809.         Product $product,
  810.         EntityManagerInterface $em
  811.     ): JsonResponse {
  812.         // Increment search count only if coming from search
  813.         if ($request->query->get('fromSearch')) {
  814.             $product->setSearchCount($product->getSearchCount() + 1);
  815.         }
  816.         $em->flush();
  817.         return new JsonResponse(['ok' => true]);
  818.     }
  819. }