src/Controller/AccueilController.php line 1099

Open in your IDE?
  1. <?php
  2. // src/Controller/AccueilController
  3. /*
  4.  * 
  5.  * Date de modification:16/05/2025
  6.  * Description:Controller LayoutAccueil 5sur5 Séjour
  7.  *
  8.  */
  9. namespace App\Controller;
  10. use App\Entity\Fonctions;
  11. use App\Entity\User;
  12. use App\Entity\Ref;
  13. use App\Entity\Commande;
  14. use App\Entity\Typeproduit;
  15. use App\Service\AttachementService;
  16. use App\Service\BlogService;
  17. use App\Service\EmailsCmdService;
  18. use App\Service\SejourService;
  19. use App\Service\SiteService;
  20. use App\Service\TypeProduiteService;
  21. use App\Service\UserService;
  22. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  23. use Symfony\Component\Routing\Annotation\Route;
  24. use Symfony\Component\HttpFoundation\Response;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\JsonResponse;
  27. use Doctrine\ORM\EntityManagerInterface;
  28. use Symfony\Component\Mailer\MailerInterface;
  29. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  30. use Symfony\Component\Mime\Address;
  31. use Psr\Log\LoggerInterface;
  32. class AccueilController extends AbstractController
  33. {
  34.     private $typeProduiteService;
  35.     private $siteService;
  36.     private $blogService;
  37.     private $UserService;
  38.     private $sejourService;
  39.     private $attachementService;
  40.     private $mailer;
  41.     private $logger;
  42.     private $emailsCmdService;
  43.     public function __construct(TypeProduiteService $typeProduiteServiceSiteService $siteServiceBlogService $blogServiceUserService $UserServiceSejourService $sejourServiceAttachementService $attachementServiceMailerInterface $mailerLoggerInterface $loggerEmailsCmdService $emailsCmdService)
  44.     {
  45.         $this->typeProduiteService $typeProduiteService;
  46.         $this->siteService $siteService;
  47.         $this->blogService $blogService;
  48.         $this->UserService $UserService;
  49.         $this->sejourService $sejourService;
  50.         $this->attachementService $attachementService;
  51.         $this->mailer $mailer;
  52.         $this->logger $logger;
  53.         $this->emailsCmdService $emailsCmdService;
  54.     }
  55.     /**
  56.      * @Route("/Accueil5sur5", name="layoutAccueil")
  57.      * */
  58.     public function layoutAccueil()
  59.     {
  60.         return $this->render('Accueil/layoutAccueil.html.twig');
  61.     }
  62.     /**
  63.      * @Route("/Accueil5sur5/header_layoutAccueil", name="header_layoutAccueil")
  64.      */
  65.     public function header(Request $request): Response
  66.     {
  67.         $produit $this->typeProduiteService;
  68.         $liste $produit->produitlistType();
  69.         // dd($liste);
  70.         $session $request->getSession();
  71.         $Products $session->get("Panier");
  72.         if ($Products == Null) {
  73.             $Products = [];
  74.         }
  75.         return $this->render('Accueil/header.html.twig', [
  76.             'produit' => $liste,
  77.             'Products' => $Products,
  78.         ]);
  79.     }
  80.     /**
  81.      * @Route("/Accueil5sur5/header_Parent", name="header_Parent")
  82.      */
  83.     public function header_Parent(Request $request): Response
  84.     {
  85.         $produit $this->typeProduiteService;
  86.         $liste $produit->produitlistType();
  87.         // dd($liste);
  88.         $session $request->getSession();
  89.         $Products $session->get("Panier");
  90.         if ($Products == Null) {
  91.             $Products = [];
  92.         }
  93.         return $this->render('Accueil/headerParents.html.twig', [
  94.             'produit' => $liste,
  95.             'Products' => $Products,
  96.         ]);
  97.     }
  98.     /**
  99.      * @Route("/Accueil5sur5/headerLogin", name="headerLogin")
  100.      */
  101.     public function headerLogin(Request $request): Response
  102.     {
  103.         $produit $this->typeProduiteService;
  104.         $liste $produit->produitlistType();
  105.         // dd($liste);
  106.         $session $request->getSession();
  107.         $Products $session->get("Panier");
  108.         if ($Products == Null) {
  109.             $Products = [];
  110.         }
  111.         return $this->render('Accueil/headerLogin.html.twig', [
  112.             'produit' => $liste,
  113.             'Products' => $Products,
  114.         ]);
  115.     }
  116.     /**
  117.      * @Route("/", name="page_Accueil")
  118.      */
  119.     public function PageAccueil()
  120.     {
  121.         $produit $this->typeProduiteService;
  122.         $liste $produit->produitlistType();
  123.         $siteservice $this->siteService;
  124.         $site $siteservice->getActiveSite();
  125.         $list $this->blogService->allblog();
  126.         //dd($list);
  127.         return $this->render('Accueil/PageAccueil.html.twig', ["site" => $site'list' => $list'produit' => $liste]);
  128.     }
  129.     /**
  130.      * @Route("/Parent/", name="Parent")
  131.      */
  132.     public function Acceuil(Request $request)
  133.     {
  134.         $produit $this->typeProduiteService;
  135.         $liste $produit->produitlistType();
  136.         $siteservice $this->siteService;
  137.         $site $siteservice->getActiveSite();
  138.         $list $this->blogService->allblog();
  139.         $session $request->getSession();
  140.         $Products $session->get("Panier");
  141.         if ($Products == Null) {
  142.             $Products = [];
  143.         }
  144.         return $this->render('Accueil/PageAccueil.html.twig', ["site" => $site'list' => $list'produit' => $liste'Products' => $Products]);
  145.     }
  146.     /**
  147.      * @Route("/Accueil5sur5/footer_layoutAccueil", name="footer_layoutAccueil")
  148.      */
  149.     public function footer()
  150.     {
  151.         return $this->render('Accueil/footer.html.twig');
  152.     }
  153.     /**
  154.      * @Route("/Accompagnateur/register", name="accomp_register",methods={"POST","GET"})
  155.      */
  156.     public function register(Request $request)
  157.     
  158.     {
  159.         // Forcer type_user=EF si la requête vient de la page écoles publiques
  160.         $referer $request->headers->get('referer');
  161.         if ($referer && strpos($referer'/ecoles-publiques/creer') !== false) {
  162.             $request->request->set('type_user''EF');
  163.             error_log("🏫 Création depuis page écoles publiques → Force type_user=EF");
  164.         }
  165.         
  166.         ini_set("max_execution_time", -1);
  167.         ini_set('memory_limit''-1');
  168.         $em $this->getDoctrine()->getManager();
  169.         $UserService $this->UserService;
  170.         $SejourService $this->sejourService;
  171.         $AttachementService $this->attachementService;
  172.         $nom $request->get("nom_acc");
  173.         $prenom $request->get('prenom_acc');
  174.         $etablisment $request->get("etablisment");
  175.         $fonction $request->get("fonction");
  176.         $EntityFonction $em->getRepository(Fonctions::class)->find($fonction);
  177.         if ($EntityFonction) {
  178.             $nameFonction $EntityFonction->getName();
  179.         } else {
  180.             $nameFonction "";
  181.         }
  182.         $adressetablisment $request->get("adressetablisment");
  183.         // prix et reverse
  184.         $prixcnxparent 2.90;
  185.         $prixcnxpartenaire 0;
  186.         $reversecnxpart 0;
  187.         $reverseventepart 0;
  188.         $phoneacc $request->get("phone_acc");
  189.         $mail $request->get("email");
  190.         $password $request->get("password");
  191.         $role "ROLE_ACC";
  192.         $themSejour $request->get('theme_sejour');
  193.         $adressSejour $request->get("adress_sejour");
  194.         $codePostal $request->get("codePostal");
  195.         $dateDebut $request->get("date_debut_sejour");
  196.         $FinSejour $request->get("date_fin_sejour");
  197.         $AgeDugroupe $request->get("age_dugroupe_sejour");
  198.         $NbEnfant $request->get("NbEnfant");
  199.         $pays $request->get("pays");
  200.         $ville $request->get("ville");
  201.         $CODEpOSTALetablisment $request->get("CODEpOSTALetablisment");
  202.         $villeetablisment $request->get("villeetablisment");
  203.         
  204.         // Récupérer le type de séjour depuis le formulaire (EP, EF, PF)
  205.         $type_user $request->get("type_user");
  206.         if (!$type_user) {
  207.             $type_user "PP"// Par défaut: École Publique (parents paient)
  208.         }
  209.     
  210.         // Mapper le type_user vers le type de séjour et connpay
  211.         // Logique du code séjour : [Type][Pay][Timestamp]
  212.         // Type: E=École, P=Partenaire, C=CSE
  213.         // Pay: P=Payant (parents), F=Free (gratuit/structure)
  214.         switch ($type_user) {
  215.             case 'EF':
  216.                 // École Française (page dédiée) = École + Gratuit
  217.         $type "ECOLES/AUTRES";
  218.                 $connpay 0// Gratuit (0 = Free)
  219.                 break;
  220.             case 'PF':
  221.                 // Partenaire Financé (structure prend en charge) = Partenaire + Structure finance
  222.                 $type "PARTENAIRES/VOYAGISTES";
  223.                 $connpay 0// Structure finance (0 = Free)
  224.                 break;
  225.             case 'PP':
  226.             default:
  227.                 // École Publique (parents paient par défaut) = École + Parents paient
  228.                 $type "ECOLES/AUTRES";
  229.                 $connpay 1// Parents paient (1 = Payant)
  230.                 break;
  231.         }
  232.         
  233.         error_log("🔍 Type reçu du formulaire: type_user=$type_user → Type séjour=$type, connpay=$connpay");
  234.      
  235.         $bytes random_bytes(5);
  236.         $passAcommpa bin2hex($bytes);
  237.         if ($NbEnfant) {
  238.             $NbEnfant $NbEnfant;
  239.         } else {
  240.             $NbEnfant 0;
  241.         }
  242.         $dateSJoue = new \Datetime();
  243.         $Milliseconde $dateSJoue->format('u');
  244.         $annes $dateSJoue->format('y');
  245.         $joours $dateSJoue->format('d');
  246.         $joours $dateSJoue->format('t');
  247.         $emailaccf "Acompa" $annes $joours $Milliseconde "@fictif.com";
  248.         //CREATION ACCOMPAGNATEUR
  249.         $accomp $UserService->creationNewAcommpa($nom$prenom$etablisment$nameFonction$adressetablisment$phoneacc$emailaccf$role$passAcommpa$mail);
  250.         $accomp->setIdFonction($EntityFonction);
  251.         $em->persist($accomp);
  252.         $em->flush();
  253.         //CREATION PARTENAIRE
  254.         $part $em->getRepository(User::class)->VerifierAddresseEmailPartenaire($mail'ROLE_PARTENAIRE');
  255.         if (is_null($part)) {
  256.             $part $UserService->creationNewUser($nom$prenom$etablisment$nameFonction$adressetablisment$phoneacc$mail$passAcommpa"ROLE_PARTENAIRE");
  257.             $part->setIdFonction($EntityFonction);
  258.             $em->persist($part);
  259.             $em->flush();
  260.         }
  261.         //CREATION ETABLISSEMENT + PARTENAIRE
  262.         $Etablisment $UserService->creationNewEtablisment($part$nom$prenom$etablisment$fonction$adressetablisment$phoneacc$mail"ROLE_PARTENAIRE"$password$prixcnxparent$prixcnxpartenaire$reversecnxpart$reverseventepart);
  263.         if ($CODEpOSTALetablisment == "") {
  264.             $CODEpOSTALetablisment null;
  265.         }
  266.         $Etablisment->setCodepostaleatb($CODEpOSTALetablisment);
  267.         $Etablisment->setVille($villeetablisment);
  268.         $em->persist($Etablisment);
  269.         $em->flush();
  270.         //CREATION SEJOUR ACCOM + PARTENAIRE + ETABILSSEMENT
  271.         // Ne pas surcharger $connpay via la fonction (ex: VIP)
  272.         // Le code séjour doit refléter exclusivement le choix utilisateur (type_user)
  273.         $sejour $SejourService->CreationNouveauSejourParAccompagnateur($themSejour$adressSejour$dateDebut$FinSejour$AgeDugroupe$type$NbEnfant$connpay$pays$ville$prixcnxparent$prixcnxpartenaire$reversecnxpart$reverseventepart);
  274.         $sejour->setCodePostal(intval($codePostal));
  275.         $SejourService->affecterAccompaniateur($sejour$accomp);
  276.         $SejourService->affecterPartenaire($sejour$part);
  277.         $SejourService->affecteretablisment($sejour$Etablisment);
  278.         $em->persist($sejour);
  279.         $em->flush();
  280.         // Gestion du paiement par la structure
  281.         $paymentMethodStructure $request->get('payment_method_structure');
  282.         $billingEmail $request->get('billing_email');
  283.         $billingContact $request->get('billing_contact');
  284.         
  285.         // Si c'est une structure qui paie (PF) et qu'un mode de paiement est spécifié
  286.         if ($type_user === 'PF' && $paymentMethodStructure) {
  287.             // Récupérer le statut "en attente de paiement"
  288.             $statutAttentePaiement $em->getRepository(\App\Entity\Ref::class)->findOneBy(['libiller' => 'attente_paiement']);
  289.             if (!$statutAttentePaiement) {
  290.                 // Créer le statut s'il n'existe pas
  291.                 $statutAttentePaiement = new \App\Entity\Ref();
  292.                 $statutAttentePaiement->setLibiller('attente_paiement');
  293.                 // Pas de typeref nécessaire ici, on reste cohérent avec les autres statuts "attente_paiement"
  294.                 $em->persist($statutAttentePaiement);
  295.                 $em->flush();
  296.             }
  297.             
  298.             // Mettre le séjour en attente de paiement
  299.             $sejour->setStatut($statutAttentePaiement);
  300.             $em->persist($sejour);
  301.             $em->flush();
  302.             
  303.             // Créer une commande pour le séjour
  304.             $commande = new Commande();
  305.             $commande->setIdUser($part);
  306.             $commande->setIdSejour($sejour);
  307.             
  308.             // Récupérer le statut "en attente" pour la commande
  309.             $statutCommandeEnAttente $em->getRepository(\App\Entity\Ref::class)->find(1); // 1 = en attente
  310.             if ($statutCommandeEnAttente) {
  311.                 $commande->setStatut($statutCommandeEnAttente);
  312.             }
  313.             
  314.             $commande->setMontantht(39);
  315.             $commande->setMontantrth(46.80); // 39€ HT + 20% TVA
  316.             $commande->setMontanenv(46.80);
  317.             $commande->setTva(20);
  318.             $commande->setDateCreateCommande(new \DateTime());
  319.             $commande->setNumComande(time());
  320.             $commande->setPeriode('sejour_simple');
  321.             
  322.             // Normaliser le mode de paiement
  323.             $paymentTypeNormalized = ($paymentMethodStructure === 'carte') ? 'stripe' 'rib';
  324.             $commande->setPaymentType($paymentTypeNormalized);
  325.             
  326.             $em->persist($commande);
  327.             $em->flush();
  328.             
  329.             error_log("💰 Commande créée pour séjour #{$sejour->getId()}, mode de paiement: {$paymentTypeNormalized}");
  330.             
  331.             // Stocker les infos de facturation en session pour l'envoi RIB si nécessaire
  332.             $session $request->getSession();
  333.             $session->set('sejour_payment_info', [
  334.                 'sejour_id' => $sejour->getId(),
  335.                 'commande_id' => $commande->getId(),
  336.                 'payment_method' => $paymentTypeNormalized,
  337.                 'billing_email' => $billingEmail,
  338.                 'billing_contact' => $billingContact
  339.             ]);
  340.             
  341.             // Ne pas envoyer les codes immédiatement si virement (sera envoyé avec le RIB)
  342.             // Si carte : les codes seront envoyés après paiement
  343.             if ($paymentTypeNormalized === 'rib') {
  344.                 // Les codes seront envoyés via la route send-rib-codes
  345.                 error_log("📧 Mode virement : codes séjour seront envoyés avec le RIB");
  346.                 $UserService->EnvoyerEmailAcommpatActivationNewMail($sejour$accomp);
  347.             } else {
  348.                 // Pour carte : les codes seront envoyés après paiement réussi
  349.                 error_log("💳 Mode carte : codes séjour seront envoyés après paiement");
  350.                 $UserService->EnvoyerEmailAcommpatActivationNewMail($sejour$accomp);
  351.             }
  352.         } else {
  353.             // Si parents paient ou pas de mode de paiement : envoyer les codes normalement
  354.             $UserService->EnvoyerEmailAcommpatActivationNewMail($sejour$accomp);
  355.         }
  356.         //AFFECTAION LOGO TO USER PARTENAIRE ADN ACCOMPAGNATEUR
  357.         if ($request->request->has('path')) {
  358.             $ty "logo séjour";
  359.             $AttachementService->creationLogoSejour($accomp$request->get('path'), $ty);
  360.             $AttachementService->creationLogoSejour($part$request->get('path'), $ty);
  361.         }
  362.         $TypeSejour 8;
  363.        
  364.         $session $request->getSession();
  365.         $session->set('Sejour'$sejour->getId());
  366.         //$this->redirectToRoute('app_back_Acommpa');
  367.         return new JsonResponse(["idSejour" => $sejour->getId()]);
  368.     }
  369.     //inscription du parent 
  370.     /**
  371.      * @Route("/Parent/register", name="parent_register",methods={"POST","GET"})
  372.      */
  373.     public function registerparent(Request $request)
  374.     {
  375.         $UserService $this->UserService;
  376.         //
  377.         $nom $request->get("nomparent");
  378.         $prenom $request->get('prenomparent');
  379.         $mailparent $request->get("mailprent");
  380.         $numtel $request->get("numtel");
  381.         $passwordparent $request->get("passwordparent");
  382.         $confirmpassword $request->get("confirmpassword");
  383.         $notifsms $request->get("sms");
  384.         $notifmail $request->get('mailnotif');
  385.         if ($confirmpassword != $passwordparent) {
  386.             return new JsonResponse('erorpasswordconfirm');
  387.         }
  388.         $role "ROLE_PARENT";
  389.         $verification $UserService->verifmailold($mailparent);
  390.         //var_dump($verification);
  391.         if ($verification == NULL) {
  392.             $accomp $UserService->creationNewParent($nom$prenom$mailparent$numtel$role$passwordparent$notifsms$notifmail);
  393.             return new JsonResponse('done');
  394.         } else {
  395.             return new JsonResponse('eror');
  396.         }
  397.     }
  398.     /**
  399.      * @Route("/Accueil5sur5/5sur5", name="sur5")
  400.      */
  401.     public function sur5()
  402.     {
  403.         $produit $this->typeProduiteService;
  404.         $liste $produit->produitlistType();
  405.         //dd($liste);
  406.         return $this->render('Accueil/5sur5.html.twig', [
  407.             'produit' => $liste,
  408.         ]);
  409.     }
  410.     /**
  411.      * @Route("/Parent/Accueil5sur5/5sur5", name="5sur5Parent")
  412.      */
  413.     public function sur5Parent()
  414.     {
  415.         $produit $this->typeProduiteService;
  416.         $liste $produit->produitlistType();
  417.         //dd($liste);
  418.         return $this->render('Accueil/5sur5.html.twig', [
  419.             'produit' => $liste,
  420.         ]);
  421.     }
  422.     /**
  423.      * @Route("/Accueil5sur5/album/{id}", name="album")
  424.      */
  425.     public function produitlist($id)
  426.     {
  427.         $produit $this->typeProduiteService;
  428.         $liste $produit->produitlistType();
  429.         $produit $id;
  430.         //dd($liste);
  431.         return $this->render('Accueil/album.html.twig', [
  432.             'produit' => $liste,
  433.             'showArt' => $produit,
  434.         ]);
  435.     }
  436.     /**
  437.      * @Route("/Parent/Accueil5sur5/album/{id}", name="albumParent")
  438.      */
  439.     public function produitlistParent($id)
  440.     {
  441.         $produit $this->typeProduiteService;
  442.         $liste $produit->produitlistType();
  443.         // dd($liste);
  444.         $produit $id;
  445.         return $this->render('Accueil/album.html.twig', [
  446.             'produit' => $liste,
  447.             'showArt' => $produit,
  448.         ]);
  449.     }
  450. /**
  451.      * @Route("/Accueil5sur5/Boutique_Souvenirs", name="boutique5sur5_Souvenir")
  452.      */
  453.     public function boutique5sur5()
  454.     {
  455.        $produit $this->typeProduiteService;
  456.         $liste $produit->produitlistTypeConditionnement();
  457.       
  458.      
  459.         return $this->render('Accueil/boutique_5sur5.html.twig', [
  460.          
  461.         
  462.             'produit' => $liste,
  463.             
  464.         ]);
  465.     }
  466.     /**
  467.      * @Route("/Accueil5sur5/AlaUne", name="AlaUne")
  468.      */
  469.     public function AlaUne()
  470.     {
  471.         $blogsbolt $this->blogService;
  472.         $list $blogsbolt->allblog();
  473.         //dd($list);
  474.         return $this->render('Accueil/AlaUne.html.twig', ['list' => $list]);
  475.     }
  476.     /**
  477.      * @Route("/Parent/Accueil5sur5/AlaUne", name="AlaUneParent")
  478.      */
  479.     public function AlaUneParent()
  480.     {
  481.         $blogsbolt $this->blogService;
  482.         $list $blogsbolt->allblog();
  483.         //dd($list);
  484.         return $this->render('Accueil/AlaUneParent.html.twig', ['list' => $list]);
  485.     }
  486.     /**
  487.      * @Route("/Accueil5sur5/DetailsAlaUne/{id}", name="DetailsAlaUne")
  488.      */
  489.     public function DetailsAlaUne($id)
  490.     {
  491.         $blo $this->blogService;
  492.         $blog $blo->myblog($id);
  493.         return $this->render('Accueil/DetailsAlaUne.html.twig', ['blog' => $blog]);
  494.     }
  495.     /**
  496.      * @Route("/ServiceClient_5sur5", name="ServiceClient_5sur5")
  497.      * */
  498.     public function ServiceClient_5sur5()
  499.     {
  500.         $produit $this->typeProduiteService;
  501.         $liste $produit->produitlistType();
  502.         // dd($liste);
  503.         return $this->render('Accueil/ServiceClient_5sur5.html.twig', [
  504.             'produit' => $liste,
  505.         ]);
  506.     }
  507.     /**
  508.      * @Route("/Besoindaide_5sur5_accueil", name="Besoindaide_5sur5_accueil")
  509.      */
  510.     public function Besoindaide_5sur5_accueil(): Response
  511.     {
  512.         $produit $this->typeProduiteService;
  513.         $liste $produit->produitlistType();
  514.         // dd($liste);
  515.         return $this->render('Accueil/besoindaide_5sur5_accueil.html.twig', [
  516.             'produit' => $liste,
  517.         ]);
  518.     }
  519.     /**
  520.      * @Route("/Mentionlegale_5sur5", name="Mentionlegale_5sur5")
  521.      */
  522.     public function Mentionlegale()
  523.     {
  524.         return $this->render('Accueil/mentionlegal.html.twig', []);
  525.     }
  526.    
  527.        /**
  528.      * @Route("/Conditons_generales_5sur5", name="Conditons_generales_5sur5")
  529.      */
  530.     public function Conditons_generales()
  531.     {
  532.         return $this->render('Accueil/ConditionsGenerales.html.twig', []);
  533.     }
  534.     
  535.     /**
  536.      * @Route("/Politique_Confidentialite_5sur5", name="Politique_Confidentialite_5sur5")
  537.      */
  538.     public function PolitiqueConfidentialite()
  539.     {
  540.         return $this->render('Accueil/PolitiqueConfidentialite.html.twig', []);
  541.     }   
  542.     /**
  543.      * @Route("/unsubscribe-user", name="unsubscribe_user")
  544.      */
  545.     public function unsubscribeUser(Request $requestEntityManagerInterface $em): Response
  546.     {
  547.         $email $request->query->get('email');
  548.         
  549.         if (!$email) {
  550.             return $this->render('unsubscribe/error.html.twig', [
  551.                 'message' => 'Email manquant'
  552.             ]);
  553.         }
  554.         $user $em->getRepository(User::class)->findOneBy(['email' => $email]);
  555.         if (!$user) {
  556.             return $this->render('unsubscribe/error.html.twig', [
  557.                 'message' => 'Utilisateur non trouvé'
  558.             ]);
  559.         }
  560.         $user->setShowpubprod('unsuscribe');
  561.         $em->flush();
  562.         return $this->render('unsubscribe/success.html.twig', [
  563.             'email' => $email
  564.         ]);
  565.     }
  566.     /**
  567.      * @Route("/contact", name="app_contact", methods={"POST"})
  568.      */
  569.     public function processContactForm(Request $request): Response
  570.     {
  571.         try {
  572.             // Récupérer les données du formulaire (support des anciens et nouveaux noms)
  573.             $name $request->request->get('name') ?: $request->request->get('fullname');
  574.             $organization $request->request->get('organization') ?: $request->request->get('org');
  575.             $email $request->request->get('email');
  576.             $telephone $request->request->get('telephone') ?: $request->request->get('phone');
  577.             $sejoursCount $request->request->get('sejours_count') ?: $request->request->get('sejours');
  578.             $message $request->request->get('message''');
  579.             $topic $request->request->get('topic''contact');
  580.             $objet $request->request->get('objet''contact');
  581.             $pack $request->request->get('pack''');
  582.             $consent $request->request->get('consent');
  583.             
  584.             // Support ancien format avec 'subject'
  585.             $subject $request->request->get('subject');
  586.             // Validation des données
  587.             if (empty($name) || empty($email) || empty($organization) || empty($consent)) {
  588.                 return new JsonResponse([
  589.                     'success' => false,
  590.                     'message' => 'Tous les champs obligatoires doivent être remplis (nom, email, établissement, consentement).'
  591.                 ], 400);
  592.             }
  593.             if (!filter_var($emailFILTER_VALIDATE_EMAIL)) {
  594.                 return new JsonResponse([
  595.                     'success' => false,
  596.                     'message' => 'L\'adresse email n\'est pas valide.'
  597.                 ], 400);
  598.             }
  599.             // Préparer le sujet selon le type de demande
  600.             if (empty($subject)) {
  601.                 $currentDate = new \DateTime();
  602.                 if ($objet === 'expert') {
  603.                     $subject 'Demande expert_' $currentDate->format('d/m/Y');
  604.                 } elseif ($objet === 'demo' || $topic === 'demo') {
  605.                     $subject 'Demande demo_' $currentDate->format('d/m/Y');
  606.                 } else {
  607.                 $subject 'Nouveau message de contact - 5sur5séjour';
  608.                 }
  609.             }
  610.             // Créer l'email
  611.             $emailContent = (new TemplatedEmail())
  612.                 ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  613.                 ->to(new Address('ramzi.benlarbi@gmail.com''Ramzi Benlarbi'))
  614.                 ->addCc(new Address('yousra.tlich@gmail.com''Yousra Tlich'))
  615.                 ->addCc(new Address('partenariat@5sur5sejour.com''Partenariat 5sur5séjour'))
  616.                 ->subject($subject)
  617.                 ->htmlTemplate('emails/contact_form.html.twig')
  618.                 ->context([
  619.                     'name' => $name,
  620.                     'organization' => $organization,
  621.                     'email' => $email,
  622.                     'telephone' => $telephone,
  623.                     'sejours_count' => $sejoursCount,
  624.                     'subject' => $subject,
  625.                     'message' => $message,
  626.                     'topic' => $topic,
  627.                     'objet' => $objet,
  628.                     'pack' => $pack,
  629.                     'date' => new \DateTime()
  630.                 ]);
  631.             // Envoyer l'email
  632.             $this->mailer->send($emailContent);
  633.             // Logger le succès
  634.             $this->logger->info('Email de contact envoyé avec succès', [
  635.                 'from' => $email,
  636.                 'name' => $name,
  637.                 'subject' => $subject
  638.             ]);
  639.             return new JsonResponse([
  640.                 'success' => true,
  641.                 'message' => 'Votre message a été envoyé avec succès ! Nous vous répondrons dans les plus brefs délais.'
  642.             ]);
  643.         } catch (\Exception $e) {
  644.             // Logger l'erreur
  645.             $this->logger->error('Erreur lors de l\'envoi de l\'email de contact', [
  646.                 'error' => $e->getMessage(),
  647.                 'trace' => $e->getTraceAsString()
  648.             ]);
  649.             return new JsonResponse([
  650.                 'success' => false,
  651.                 'message' => 'Une erreur est survenue lors de l\'envoi du message. Veuillez réessayer plus tard.'
  652.             ], 500);
  653.         }
  654.     }
  655.     /**
  656.      * @Route("/contact/grand-volume", name="app_contact_grand_volume", methods={"POST"})
  657.      */
  658.     public function processGrandVolumeForm(Request $request): JsonResponse
  659.     {
  660.         try {
  661.             // Récupérer les données du formulaire
  662.             $nomStructure $request->request->get('nom_structure');
  663.             $typeStructure $request->request->get('type_structure');
  664.             $nombreSejours $request->request->get('nombre_sejours');
  665.             $contactEmail $request->request->get('contact_email');
  666.             $contactTelephone $request->request->get('contact_telephone');
  667.             $message $request->request->get('message''');
  668.             $acceptRgpd $request->request->get('accept_rgpd');
  669.             // Validation des données
  670.             if (empty($nomStructure) || empty($typeStructure) || empty($nombreSejours) || 
  671.                 empty($contactEmail) || empty($contactTelephone) || empty($acceptRgpd)) {
  672.                 return new JsonResponse([
  673.                     'success' => false,
  674.                     'message' => 'Tous les champs obligatoires doivent être remplis.'
  675.                 ], 400);
  676.             }
  677.             if (!filter_var($contactEmailFILTER_VALIDATE_EMAIL)) {
  678.                 return new JsonResponse([
  679.                     'success' => false,
  680.                     'message' => 'L\'adresse email n\'est pas valide.'
  681.                 ], 400);
  682.             }
  683.             if (intval($nombreSejours) < 26) {
  684.                 return new JsonResponse([
  685.                     'success' => false,
  686.                     'message' => 'Le nombre de séjours doit être d\'au moins 26 par an.'
  687.                 ], 400);
  688.             }
  689.             // Préparer le sujet
  690.             $subject 'Demande de devis Grand Volume - ' $nomStructure ' (' $nombreSejours ' séjours/an)';
  691.             // Créer l'email pour l'équipe
  692.             try {
  693.                 $emailContent = (new TemplatedEmail())
  694.                     ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  695.                     ->to('partenariat@5sur5sejour.com')
  696.                     ->addTo('yousra.tlich@gmail.com')
  697.                     ->addTo('ramzi.benlarbi@gmail.com')
  698.                     ->subject($subject)
  699.                     ->htmlTemplate('emails/grand_volume_request.html.twig')
  700.                     ->context([
  701.                         'nomStructure' => $nomStructure,
  702.                         'typeStructure' => $typeStructure,
  703.                         'nombreSejours' => $nombreSejours,
  704.                         'contactEmail' => $contactEmail,
  705.                         'contactTelephone' => $contactTelephone,
  706.                         'message' => $message
  707.                     ]);
  708.                 $this->mailer->send($emailContent);
  709.             } catch (\Exception $emailException) {
  710.                 $this->logger->error('Erreur lors de l\'envoi de l\'email à l\'équipe', [
  711.                     'error' => $emailException->getMessage()
  712.                 ]);
  713.                 throw $emailException;
  714.             }
  715.             // Email de confirmation au client
  716.             try {
  717.                 $clientEmail = (new TemplatedEmail())
  718.                     ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  719.                     ->to($contactEmail)
  720.                     ->subject('Votre demande de devis Grand Volume a été reçue')
  721.                     ->htmlTemplate('emails/grand_volume_confirmation.html.twig')
  722.                     ->context([
  723.                         'nomStructure' => $nomStructure
  724.                     ]);
  725.                 $this->mailer->send($clientEmail);
  726.             } catch (\Exception $emailException) {
  727.                 // On log l'erreur mais on continue car l'email principal a été envoyé
  728.                 $this->logger->warning('Erreur lors de l\'envoi de l\'email de confirmation au client', [
  729.                     'error' => $emailException->getMessage()
  730.                 ]);
  731.             }
  732.             return new JsonResponse([
  733.                 'success' => true,
  734.                 'message' => 'Votre demande de devis a été envoyée avec succès ! Notre équipe vous contactera dans les plus brefs délais pour vous proposer une offre personnalisée.'
  735.             ]);
  736.         } catch (\Exception $e) {
  737.             $this->logger->error('Erreur lors de l\'envoi du formulaire grand volume', [
  738.                 'error' => $e->getMessage(),
  739.                 'file' => $e->getFile(),
  740.                 'line' => $e->getLine(),
  741.                 'trace' => $e->getTraceAsString()
  742.             ]);
  743.             // En mode dev, retourner le message d'erreur détaillé
  744.             if ($this->getParameter('kernel.environment') === 'dev') {
  745.                 return new JsonResponse([
  746.                     'success' => false,
  747.                     'message' => 'Erreur : ' $e->getMessage() . ' (ligne ' $e->getLine() . ')'
  748.                 ], 500);
  749.             }
  750.             return new JsonResponse([
  751.                 'success' => false,
  752.                 'message' => 'Une erreur est survenue lors de l\'envoi de votre demande. Veuillez réessayer plus tard.'
  753.             ], 500);
  754.         }
  755.     }
  756.     /**
  757.      * @Route("/contact/boite-vocale-devis", name="app_contact_boite_vocale_devis", methods={"POST"})
  758.      */
  759.     public function processBoiteVocaleDevisForm(Request $request): JsonResponse
  760.     {
  761.         try {
  762.             // Récupérer les données du formulaire
  763.             $nomStructure $request->request->get('nom_structure');
  764.             $typeStructure $request->request->get('type_structure');
  765.             $nombreParticipants $request->request->get('nombre_participants');
  766.             $dateDebut $request->request->get('date_debut');
  767.             $dateFin $request->request->get('date_fin');
  768.             $themeSejour $request->request->get('theme_sejour');
  769.             $contactEmail $request->request->get('contact_email');
  770.             $contactTelephone $request->request->get('contact_telephone');
  771.             $message $request->request->get('message''');
  772.             $acceptRgpd $request->request->get('accept_rgpd');
  773.             // Validation des données
  774.             if (empty($nomStructure) || empty($typeStructure) || empty($nombreParticipants) || 
  775.                 empty($dateDebut) || empty($dateFin) || empty($themeSejour) ||
  776.                 empty($contactEmail) || empty($contactTelephone) || empty($acceptRgpd)) {
  777.                 return new JsonResponse([
  778.                     'success' => false,
  779.                     'message' => 'Tous les champs obligatoires doivent être remplis.'
  780.                 ], 400);
  781.             }
  782.             if (!filter_var($contactEmailFILTER_VALIDATE_EMAIL)) {
  783.                 return new JsonResponse([
  784.                     'success' => false,
  785.                     'message' => 'L\'adresse email n\'est pas valide.'
  786.                 ], 400);
  787.             }
  788.             if (intval($nombreParticipants) < 71) {
  789.                 return new JsonResponse([
  790.                     'success' => false,
  791.                     'message' => 'Le nombre de participants doit être d\'au moins 71 pour un grand séjour.'
  792.                 ], 400);
  793.             }
  794.             // Validation des dates
  795.             $dateDebutObj = new \DateTime($dateDebut);
  796.             $dateFinObj = new \DateTime($dateFin);
  797.             if ($dateFinObj $dateDebutObj) {
  798.                 return new JsonResponse([
  799.                     'success' => false,
  800.                     'message' => 'La date de fin doit être postérieure à la date de début.'
  801.                 ], 400);
  802.             }
  803.             // Préparer le sujet
  804.             $subject 'Demande de devis Boîte Vocale - ' $nomStructure ' (' $nombreParticipants ' participants)';
  805.             // Créer l'email pour l'équipe
  806.             try {
  807.                 $emailContent = (new TemplatedEmail())
  808.                     ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  809.                     ->to('partenariat@5sur5sejour.com')
  810.                     ->addTo('yousra.tlich@gmail.com')
  811.                     ->addTo('ramzi.benlarbi@gmail.com')
  812.                     ->subject($subject)
  813.                     ->htmlTemplate('emails/boite_vocale/devis_request.html.twig')
  814.                     ->context([
  815.                         'nomStructure' => $nomStructure,
  816.                         'typeStructure' => $typeStructure,
  817.                         'nombreParticipants' => $nombreParticipants,
  818.                         'dateDebut' => $dateDebut,
  819.                         'dateFin' => $dateFin,
  820.                         'themeSejour' => $themeSejour,
  821.                         'contactEmail' => $contactEmail,
  822.                         'contactTelephone' => $contactTelephone,
  823.                         'message' => $message
  824.                     ]);
  825.                 $this->mailer->send($emailContent);
  826.             } catch (\Exception $emailException) {
  827.                 $this->logger->error('Erreur lors de l\'envoi de l\'email à l\'équipe (boîte vocale)', [
  828.                     'error' => $emailException->getMessage()
  829.                 ]);
  830.                 throw $emailException;
  831.             }
  832.             // Email de confirmation au client
  833.             try {
  834.                 $clientEmail = (new TemplatedEmail())
  835.                     ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  836.                     ->to($contactEmail)
  837.                     ->subject('Votre demande de devis Boîte Vocale a été reçue')
  838.                     ->htmlTemplate('emails/boite_vocale/devis_confirmation.html.twig')
  839.                     ->context([
  840.                         'nomStructure' => $nomStructure
  841.                     ]);
  842.                 $this->mailer->send($clientEmail);
  843.             } catch (\Exception $emailException) {
  844.                 // On log l'erreur mais on continue car l'email principal a été envoyé
  845.                 $this->logger->warning('Erreur lors de l\'envoi de l\'email de confirmation au client (boîte vocale)', [
  846.                     'error' => $emailException->getMessage()
  847.                 ]);
  848.             }
  849.             return new JsonResponse([
  850.                 'success' => true,
  851.                 'message' => 'Votre demande de devis a été envoyée avec succès ! Notre équipe vous contactera dans les plus brefs délais pour vous proposer une offre personnalisée.'
  852.             ]);
  853.         } catch (\Exception $e) {
  854.             $this->logger->error('Erreur lors de l\'envoi du formulaire devis boîte vocale', [
  855.                 'error' => $e->getMessage(),
  856.                 'file' => $e->getFile(),
  857.                 'line' => $e->getLine(),
  858.                 'trace' => $e->getTraceAsString()
  859.             ]);
  860.             // En mode dev, retourner le message d'erreur détaillé
  861.             if ($this->getParameter('kernel.environment') === 'dev') {
  862.                 return new JsonResponse([
  863.                     'success' => false,
  864.                     'message' => 'Erreur : ' $e->getMessage() . ' (ligne ' $e->getLine() . ')'
  865.                 ], 500);
  866.             }
  867.             return new JsonResponse([
  868.                 'success' => false,
  869.                 'message' => 'Une erreur est survenue lors de l\'envoi de votre demande. Veuillez réessayer plus tard.'
  870.             ], 500);
  871.         }
  872.     }
  873.     /**
  874.      * @Route("/contact/demo", name="app_contact_demo", methods={"POST"})
  875.      */
  876.     public function processDemoForm(Request $request): Response
  877.     {
  878.         try {
  879.             // Récupérer les données du formulaire de démo
  880.             $fullname $request->request->get('fullname');
  881.             $org $request->request->get('org');
  882.             $email $request->request->get('email');
  883.             $phone $request->request->get('phone');
  884.             $message $request->request->get('message');
  885.             $topic $request->request->get('topic');
  886.             $pack $request->request->get('pack');
  887.             $consent $request->request->get('consent');
  888.             // Validation des données
  889.             if (empty($fullname) || empty($org) || empty($email) || empty($consent)) {
  890.                 return new JsonResponse([
  891.                     'success' => false,
  892.                     'message' => 'Tous les champs obligatoires doivent être remplis et le consentement accepté.'
  893.                 ], 400);
  894.             }
  895.             if (!filter_var($emailFILTER_VALIDATE_EMAIL)) {
  896.                 return new JsonResponse([
  897.                     'success' => false,
  898.                     'message' => 'L\'adresse email n\'est pas valide.'
  899.                 ], 400);
  900.             }
  901.             // Préparer le sujet avec la date
  902.             $currentDate = new \DateTime();
  903.             $subject 'Demande demo_' $currentDate->format('d/m/Y');
  904.             // Créer l'email pour la demande de démo
  905.             $emailContent = (new TemplatedEmail())
  906.                 ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  907.                 ->to(new Address('ramzi.benlarbi@gmail.com''Ramzi Benlarbi'))
  908.                 ->addCc(new Address('yousra.tlich@gmail.com''Yousra Tlich'))
  909.                 ->addCc(new Address('partenariat@5sur5sejour.com''Partenariat 5sur5séjour'))
  910.                 ->subject($subject)
  911.                 ->htmlTemplate('emails/demo_request.html.twig')
  912.                 ->context([
  913.                     'fullname' => $fullname,
  914.                     'org' => $org,
  915.                     'email' => $email,
  916.                     'phone' => $phone,
  917.                     'message' => $message,
  918.                     'topic' => $topic,
  919.                     'pack' => $pack,
  920.                     'date' => $currentDate
  921.                 ]);
  922.             // Envoyer l'email
  923.             $this->mailer->send($emailContent);
  924.             // Logger le succès
  925.             $this->logger->info('Email de demande de démo envoyé avec succès', [
  926.                 'from' => $email,
  927.                 'fullname' => $fullname,
  928.                 'org' => $org,
  929.                 'topic' => $topic
  930.             ]);
  931.             return new JsonResponse([
  932.                 'success' => true,
  933.                 'message' => 'Votre demande de démo a été envoyée avec succès ! Nous vous recontacterons dans les 24 heures.'
  934.             ]);
  935.         } catch (\Exception $e) {
  936.             // Logger l'erreur
  937.             $this->logger->error('Erreur lors de l\'envoi de l\'email de demande de démo', [
  938.                 'error' => $e->getMessage(),
  939.                 'trace' => $e->getTraceAsString()
  940.             ]);
  941.             return new JsonResponse([
  942.                 'success' => false,
  943.                 'message' => 'Une erreur est survenue lors de l\'envoi de la demande. Veuillez réessayer plus tard.'
  944.             ], 500);
  945.         }
  946.     }
  947.     /**
  948.      * @Route("/Accueil5sur5/Pack_Access", name="pack_access")
  949.      * @Route("/Accueil5sur5/Pack_Decouverte", name="pack_decouverte")
  950.      */
  951.     public function packAccess()
  952.     {
  953.         return $this->render('Accueil/pack_access.html.twig');
  954.     }
  955.     /**
  956.      * @Route("/Accueil5sur5/Pack_Annuel_Partenaires", name="pack_annuel_partenaires")
  957.      * 
  958.      */
  959.     public function packAnnuelPartenaires()
  960.     {
  961.         return $this->render('Accueil/pack_annuel_partenaires.html.twig');
  962.     }
  963.     /**
  964.      * @Route("/Accueil5sur5/Boite_Vocale", name="boite_vocale")
  965.      */
  966.     public function boiteVocale()
  967.     {
  968.         return $this->render('Accueil/boite_vocale.html.twig');
  969.     }
  970.     /**
  971.      * @Route("/Accueil5sur5/Commande_Groupee", name="commande_groupee_accueil")
  972.      */
  973.     public function commandeGroupeeAccueil()
  974.     {
  975.         return $this->render('Accueil/CommandeGroupee.html.twig');
  976.     }
  977.     /**
  978.      * @Route("/checkout/boite-vocale/{pack}", name="checkout_boite_vocale", defaults={"pack"="35"})
  979.      */
  980.     public function checkoutBoiteVocale(string $pack)
  981.     {
  982.         // Configuration des packs
  983.         $packConfigs = [
  984.             '35' => ['name' => 'Pack 35 enfants''price' => 40'max' => 35],
  985.             '70' => ['name' => 'Pack 70 enfants''price' => 70'max' => 70],
  986.             'plus' => ['name' => 'Grand séjour''price' => 0'max' => null]
  987.         ];
  988.         
  989.         $packConfig $packConfigs[$pack] ?? $packConfigs['35'];
  990.         
  991.         return $this->render('Accueil/checkout_boite_vocale.html.twig', [
  992.             'pack_type' => $pack,
  993.             'pack_config' => $packConfig
  994.         ]);
  995.     }
  996.     /**
  997.      * @Route("/checkout/process-boite-vocale", name="checkout_process_boite_vocale", methods={"POST"})
  998.      */
  999.     public function processCheckoutBoiteVocale(Request $requestEntityManagerInterface $em)
  1000.     {
  1001.         try {
  1002.             // Récupérer les données du formulaire
  1003.             $data = [
  1004.                 'company_name' => $request->request->get('company_name'),
  1005.                 'company_type' => $request->request->get('company_type'),
  1006.                 'phone' => $request->request->get('phone'),
  1007.                 'address' => $request->request->get('address'),
  1008.                 'postal_code' => $request->request->get('postal_code'),
  1009.                 'city' => $request->request->get('city'),
  1010.                 'first_name' => $request->request->get('first_name'),
  1011.                 'last_name' => $request->request->get('last_name'),
  1012.                 'email' => $request->request->get('email'),
  1013.                 'role' => $request->request->get('role'),
  1014.                 'date_debut' => $request->request->get('date_debut'),
  1015.                 'date_fin' => $request->request->get('date_fin'),
  1016.                 'nombre_participants' => $request->request->get('nombre_participants'),
  1017.                 'theme_sejour' => $request->request->get('theme_sejour'),
  1018.                 'adresse_sejour' => $request->request->get('adresse_sejour'),
  1019.                 'pack_type' => $request->request->get('pack_type''35'),
  1020.                 'payment_method' => $request->request->get('payment_method''online')
  1021.             ];
  1022.             
  1023.             // Validation des champs obligatoires
  1024.             $requiredFields = ['company_name''phone''address''postal_code''city''first_name''last_name''email''date_debut''date_fin''nombre_participants''theme_sejour''adresse_sejour'];
  1025.             foreach ($requiredFields as $field) {
  1026.                 if (empty($data[$field])) {
  1027.                     return new JsonResponse([
  1028.                         'success' => false,
  1029.                         'error' => "Le champ {$field} est obligatoire"
  1030.                     ], 400);
  1031.                 }
  1032.             }
  1033.             
  1034.             // Déterminer les prix selon le pack
  1035.             $packPrices = [
  1036.                 '35' => ['ht' => 40'ttc' => 48],
  1037.                 '70' => ['ht' => 70'ttc' => 84],
  1038.                 'plus' => ['ht' => 0'ttc' => 0// Sur devis
  1039.             ];
  1040.             $prices $packPrices[$data['pack_type']] ?? $packPrices['35'];
  1041.             
  1042.             // Créer ou récupérer l'utilisateur
  1043.             $userRepository $em->getRepository(User::class);
  1044.             $user $userRepository->findOneBy(['email' => $data['email']]);
  1045.             
  1046.             if (!$user) {
  1047.                 $user = new User();
  1048.                 $user->setEmail($data['email']);
  1049.                 $user->setNom($data['last_name']);
  1050.                 $user->setPrenom($data['first_name']);
  1051.                 $user->setTelephone($data['phone']);
  1052.                 $user->setNometablisment($data['company_name']);
  1053.                 $mdpTemp substr(md5(uniqid()), 08);
  1054.                 $user->setPassword(password_hash($mdpTempPASSWORD_BCRYPT));
  1055.                 $user->setRoles(['ROLE_PARTENAIRE']);
  1056.                 $user->setStatut(1);
  1057.                 $em->persist($user);
  1058.                 $em->flush();
  1059.             }
  1060.             
  1061.             // Récupérer le statut "en attente"
  1062.             $statutEnAttente $em->getRepository(Ref::class)->find(1);
  1063.             if (!$statutEnAttente) {
  1064.                 $statutEnAttente = new Ref();
  1065.                 $statutEnAttente->setLibiller('attente_paiement');
  1066.                 $em->persist($statutEnAttente);
  1067.                 $em->flush();
  1068.             }
  1069.             
  1070.             // Créer la commande
  1071.             $commande = new Commande();
  1072.             $commande->setIdUser($user);
  1073.             $commande->setStatut($statutEnAttente);
  1074.             $commande->setMontantht($prices['ht']);
  1075.             $commande->setMontantrth($prices['ttc']);
  1076.             $commande->setMontanenv($prices['ttc']);
  1077.             $commande->setTva(20);
  1078.             $commande->setDateCreateCommande(new \DateTime());
  1079.             $commande->setPeriode('boite_vocale'); // Identifier comme commande boîte vocale
  1080.             $commande->setNumComande(time());
  1081.             
  1082.             // Normaliser la méthode de paiement
  1083.             $methodNormalized strtolower($data['payment_method']);
  1084.             $aliases = [
  1085.                 'online' => 'stripe',
  1086.                 'cb' => 'stripe',
  1087.                 'payplug' => 'stripe',
  1088.                 'card' => 'stripe',
  1089.                 'bank' => 'rib',
  1090.                 'transfer' => 'rib',
  1091.                 'virement' => 'rib',
  1092.                 'bank_transfer' => 'rib'
  1093.             ];
  1094.             if (isset($aliases[$methodNormalized])) {
  1095.                 $methodNormalized $aliases[$methodNormalized];
  1096.             }
  1097.             $commande->setPaymentType($methodNormalized);
  1098.             
  1099.             // Stocker les infos du séjour dans un champ JSON ou commentaire (à adapter selon votre structure)
  1100.             // Pour l'instant, on stocke dans le numéro de commande comme référence
  1101.             $commande->setNumComande(time() . '_' $data['pack_type']);
  1102.             
  1103.             $em->persist($commande);
  1104.             $em->flush();
  1105.             
  1106.             // Stocker les données en session pour la page de confirmation
  1107.             $session $request->getSession();
  1108.             $session->set('checkout_data', [
  1109.                 'commande_id' => $commande->getId(),
  1110.                 'type' => 'boite_vocale',
  1111.                 'pack_type' => $data['pack_type'],
  1112.                 'montant_ht' => $prices['ht'],
  1113.                 'montant_ttc' => $prices['ttc'],
  1114.                 'payment_method' => $methodNormalized,
  1115.                 'user' => $user,
  1116.                 'data' => $data
  1117.             ]);
  1118.             
  1119.             // Traiter selon la méthode de paiement
  1120.             if ($methodNormalized === 'stripe') {
  1121.                 // Rediriger vers Payplug
  1122.                 $session->set('commandeActual'$commande->getId());
  1123.                 $paymentUrl $this->generateUrl('partenaire_payplug_chargement_form', [], \Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_URL);
  1124.                 
  1125.                 return new JsonResponse([
  1126.                     'success' => true,
  1127.                     'paymentType' => 'stripe',
  1128.                     'message' => 'Redirection vers le paiement sécurisé...',
  1129.                     'redirectUrl' => $paymentUrl
  1130.                 ]);
  1131.             } else {
  1132.                 // RIB - Envoyer l'email avec les coordonnées bancaires
  1133.                 try {
  1134.                     $email = (new TemplatedEmail())
  1135.                         ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  1136.                         ->to($user->getEmail())
  1137.                         ->cc('yousra.tlich@gmail.com''ramzi.benlarbi@gmail.com')
  1138.                         ->subject('Virement bancaire - Boîte Vocale - Commande N°' $commande->getId())
  1139.                         ->htmlTemplate('emails/boite_vocale/rib_commande.html.twig')
  1140.                         ->context([
  1141.                             'user' => $user,
  1142.                             'commande' => $commande,
  1143.                             'data' => $data,
  1144.                             'pack_type' => $data['pack_type'],
  1145.                             'pack_label' => $data['pack_type'] === '35' 'Pack 35 enfants' : ($data['pack_type'] === '70' 'Pack 70 enfants' 'Grand séjour'),
  1146.                             'montant_ht' => $prices['ht'],
  1147.                             'montant_ttc' => $prices['ttc']
  1148.                         ]);
  1149.                     
  1150.                     $this->mailer->send($email);
  1151.                 } catch (\Exception $e) {
  1152.                     error_log("⚠️ Erreur envoi email RIB: " $e->getMessage());
  1153.                 }
  1154.                 
  1155.                 // Retourner succès avec message pour popup
  1156.                 return new JsonResponse([
  1157.                     'success' => true,
  1158.                     'paymentType' => 'rib',
  1159.                     'message' => 'Votre demande a bien été envoyée, nous reviendrons vers vous dans les plus brefs délais.',
  1160.                     'redirectUrl' => $this->generateUrl('checkout_success', ['method' => 'rib'])
  1161.                 ]);
  1162.             }
  1163.             
  1164.         } catch (\Exception $e) {
  1165.             error_log("❌ Erreur checkout boîte vocale: " $e->getMessage());
  1166.             error_log($e->getTraceAsString());
  1167.             return new JsonResponse([
  1168.                 'success' => false,
  1169.                 'error' => 'Une erreur est survenue lors du traitement de votre commande. Veuillez réessayer.'
  1170.             ], 500);
  1171.         }
  1172.     }
  1173.     /**
  1174.      * @Route("/checkout/pack/{pack}", name="checkout_pack", defaults={"pack"="serenite"})
  1175.      */
  1176.     public function checkoutPack(string $pack)
  1177.     {
  1178.         // Configuration des packs
  1179.         $packsConfig = [
  1180.             'decouverte' => [
  1181.                 'id' => 'decouverte',
  1182.                 'name' => 'Pack Découverte',
  1183.                 'subtitle' => 'Abonnement annuel',
  1184.                 'price' => 290,
  1185.                 'price_ht' => '290 € HT',
  1186.                 'onboarding' => 'Inclus',
  1187.                 'vocal_price' => '+5 € / séjour',
  1188.                 'features' => [
  1189.                     'Séjours illimités toute l\'année',
  1190.                     'Multi-sites pour une équipe',
  1191.                     'Reporting mensuel & facturation',
  1192.                     'Support prioritaire individuel'
  1193.                 ],
  1194.                 'info' => 'Plusieurs séjours par an ? Tarif dégressif automatique !'
  1195.             ],
  1196.             'serenite' => [
  1197.                 'id' => 'serenite',
  1198.                 'name' => 'Pack Annuel – 25 séjours',
  1199.                 'subtitle' => 'Le plus utilisé',
  1200.                 'description' => 'Le pack idéal pour les structures qui organisent plusieurs séjours par an. Jusqu\'à 25 séjours inclus dans votre abonnement annuel.',
  1201.                 'price' => 490,
  1202.                 'price_ht' => '490 € HT',
  1203.                 'price_suffix' => '/ an / structure',
  1204.                 'onboarding' => 'Déploiement par l\'équipe 5sur5',
  1205.                 'vocal_price' => ''// Retiré - plus de voix téléphonique
  1206.                 'benefit' => '+90% de connexions parents',
  1207.                 'benefit_subtitle' => 'Pas d\'action de votre part, on s\'occupe de tout mettre en place',
  1208.                 'features' => [
  1209.                     'Support prioritaire',
  1210.                     'Jusqu\'à 25 séjours inclus',
  1211.                     'Déploiement par l\'équipe 5sur5',
  1212.                     'Accompagnateurs illimités',
  1213.                     'Support premium'
  1214.                 ],
  1215.                 'info' => 'Budget annuel fixe, 0 dépassement. Un prix unique qui couvre tous vos séjours et tous les parents connectés. Aucun dépassement, données sécurisées RGPD en France.',
  1216.                 'additional_info' => 'Que vous organisiez 2 ou 20 séjours par an, tout est couvert sans frais supplémentaires. Notre plateforme gère automatiquement les familles, les albums souvenirs et la communication en temps réel.'
  1217.             ],
  1218.             'pro_illimite' => [
  1219.                 'id' => 'pro_illimite',
  1220.                 'name' => 'Pack Pro Illimité',
  1221.                 'subtitle' => 'Abonnement annuel',
  1222.                 'price' => 790,
  1223.                 'price_ht' => '790 € HT',
  1224.                 'onboarding' => 'Inclus + Formation avancée',
  1225.                 'vocal_price' => 'Inclus',
  1226.                 'features' => [
  1227.                     'Séjours illimités toute l\'année',
  1228.                     'Multi-sites pour une équipe',
  1229.                     'Reporting mensuel & facturation',
  1230.                     'Support prioritaire individuel',
  1231.                     'Voix téléphonique illimitée',
  1232.                     'Formation avancée de l\'équipe'
  1233.                 ],
  1234.                 'info' => 'Le meilleur rapport qualité/prix pour les structures avec plusieurs séjours !'
  1235.             ]
  1236.         ];
  1237.         
  1238.         // Vérifier que le pack existe
  1239.         if (!isset($packsConfig[$pack])) {
  1240.             throw $this->createNotFoundException('Pack non trouvé');
  1241.         }
  1242.         return $this->render('Accueil/checkout_pack.html.twig', [
  1243.             'pack' => $pack,
  1244.             'packConfig' => $packsConfig[$pack]
  1245.         ]);
  1246.     }
  1247.     /**
  1248.      * @Route("/checkout/process", name="checkout_process_pack", methods={"POST"})
  1249.      */
  1250.     public function checkoutProcessPack(Request $requestMailerInterface $mailer)
  1251.     {
  1252.         try {
  1253.             error_log('🔍 CHECKOUT START - Processing form submission');
  1254.             
  1255.             // Récupération des données du formulaire
  1256.             $data = [
  1257.                 'pack_id' => $request->request->get('pack_id'),
  1258.                 'payment_method' => $request->request->get('payment_method'),
  1259.                 'company_name' => $request->request->get('company_name'),
  1260.                 'company_type' => $request->request->get('company_type'),
  1261.                 'siren' => $request->request->get('siren'),
  1262.                 'phone' => $request->request->get('phone'),
  1263.                 'address' => $request->request->get('address'),
  1264.                 'postal_code' => $request->request->get('postal_code'),
  1265.                 'city' => $request->request->get('city'),
  1266.                 'first_name' => $request->request->get('first_name'),
  1267.                 'last_name' => $request->request->get('last_name'),
  1268.                 'email' => $request->request->get('email'),
  1269.                 'role' => $request->request->get('role'),
  1270.                 'need_onboarding' => $request->request->get('need_onboarding') ? true false,
  1271.             ];
  1272.             error_log('📋 Data received: ' json_encode($data));
  1273.             // Validation
  1274.             $requiredFields = ['pack_id''payment_method''company_name''company_type''phone'
  1275.                               'address''postal_code''city''first_name''last_name''email''role'];
  1276.             
  1277.             foreach ($requiredFields as $field) {
  1278.                 if (empty($data[$field])) {
  1279.                     error_log('❌ Missing required field: ' $field);
  1280.                     $this->addFlash('error''Tous les champs obligatoires doivent être remplis.');
  1281.                     return $this->redirectToRoute('checkout_pack', ['pack' => $data['pack_id'] ?? 'serenite']);
  1282.                 }
  1283.             }
  1284.             error_log('✅ Validation passed');
  1285.             // ==================== CRÉER LA COMMANDE EN BASE DE DONNÉES ====================
  1286.             $em $this->getDoctrine()->getManager();
  1287.             $commande null;
  1288.             
  1289.             // Si c'est un paiement RIB ou Devis, créer la commande maintenant
  1290.             if (in_array($data['payment_method'], ['transfer''rib''bank_transfer''quote''devis'])) {
  1291.                 try {
  1292.                     error_log('📦 Création commande pack pour: ' $data['pack_id']);
  1293.                     
  1294.                     // Créer ou récupérer l'utilisateur
  1295.                     $userRepository $em->getRepository(User::class);
  1296.                     $user $userRepository->findOneBy(['email' => $data['email']]);
  1297.                     
  1298.                     if (!$user) {
  1299.                         $user = new User();
  1300.                         $user->setEmail($data['email']);
  1301.                         $user->setNom($data['last_name']);
  1302.                         $user->setPrenom($data['first_name']);
  1303.                         $user->setTelephone($data['phone'] ?? '');
  1304.                         $user->setNometablisment($data['company_name'] ?? '');
  1305.                         $mdpTemp substr(md5(uniqid()), 08);
  1306.                         $user->setPassword(password_hash($mdpTempPASSWORD_BCRYPT));
  1307.                         $user->setRoles(['ROLE_PARTENAIRE']);
  1308.                         $user->setStatut(1);
  1309.                         $em->persist($user);
  1310.                         $em->flush();
  1311.                         error_log('✅ Utilisateur créé: ' $user->getEmail());
  1312.                     }
  1313.                     
  1314.                     // Déterminer les montants
  1315.                     $packPrices = [
  1316.                         'serenite' => ['ht' => 490'ttc' => 588],
  1317.                         'decouverte' => ['ht' => 290'ttc' => 348],
  1318.                     ];
  1319.                     $prices $packPrices[$data['pack_id']] ?? $packPrices['serenite'];
  1320.                     
  1321.                     // Récupérer le statut "en attente"
  1322.                     $statutEnAttente $em->getRepository(Ref::class)->find(1);
  1323.                     if (!$statutEnAttente) {
  1324.                         $statutEnAttente = new Ref();
  1325.                         $statutEnAttente->setLibiller('En attente');
  1326.                         $em->persist($statutEnAttente);
  1327.                         $em->flush();
  1328.                     }
  1329.                     
  1330.                     // Créer la commande
  1331.                     $commande = new Commande();
  1332.                     $commande->setIdUser($user);
  1333.                     $commande->setStatut($statutEnAttente);
  1334.                     $commande->setMontantht($prices['ht']);
  1335.                     $commande->setMontantrth($prices['ttc']);
  1336.                     $commande->setMontanenv($prices['ttc']);
  1337.                     $commande->setTva(20);
  1338.                     $commande->setDateCreateCommande(new \DateTime());
  1339.                     $commande->setDateExpidition((new \DateTime())->modify('+12 months'));
  1340.                     $commande->setPeriode('annuel');
  1341.                     $commande->setPaymentType('rib');
  1342.                     $commande->setNumComande(time());
  1343.                     
  1344.                     $em->persist($commande);
  1345.                     $em->flush();
  1346.                     
  1347.                     error_log('✅ Commande créée: ID=' $commande->getId() . ' N°' $commande->getNumComande());
  1348.                     
  1349.                 } catch (\Exception $e) {
  1350.                     error_log('❌ Erreur création commande: ' $e->getMessage());
  1351.                     // Continuer quand même pour envoyer les emails
  1352.                 }
  1353.             }
  1354.             // Stocker en session AVANT d'envoyer les emails
  1355.             $data['commande_id'] = $commande $commande->getId() : null;
  1356.             $data['commande_numero'] = $commande $commande->getNumComande() : null;
  1357.             $request->getSession()->set('checkout_data'$data);
  1358.             error_log('💾 Data stored in session');
  1359.             // Envoyer les emails de manière asynchrone (ne pas bloquer la requête)
  1360.             try {
  1361.                 error_log('📧 Attempting to send email to team...');
  1362.                 
  1363.                 // Envoyer email à l'équipe 5sur5
  1364.                 $emailToTeam = (new TemplatedEmail())
  1365.                     ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  1366.                     ->to('contact@5sur5sejour.com')
  1367.                     ->cc('yousra.tlich@gmail.com''ramzi.benlarbi@gmail.com')
  1368.                     ->subject('Nouvelle souscription Pack ' strtoupper($data['pack_id']) . ' - ' $data['company_name'])
  1369.                     ->htmlTemplate('emails/checkout_notification_team.html.twig')
  1370.                     ->context([
  1371.                         'data' => $data,
  1372.                         'date' => new \DateTime()
  1373.                     ]);
  1374.                 $mailer->send($emailToTeam);
  1375.                 error_log('✅ Email to team sent');
  1376.                 // Envoyer email de confirmation au client
  1377.                 $emailToClient = (new TemplatedEmail())
  1378.                     ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  1379.                     ->to($data['email'])
  1380.                     ->subject('Confirmation de votre souscription - 5sur5 Séjour')
  1381.                     ->htmlTemplate('emails/checkout_confirmation_client.html.twig')
  1382.                     ->context([
  1383.                         'data' => $data,
  1384.                         'date' => new \DateTime()
  1385.                     ]);
  1386.                 $mailer->send($emailToClient);
  1387.                 error_log('✅ Email to client sent');
  1388.                 
  1389.             } catch (\Exception $emailError) {
  1390.                 // Log l'erreur mais ne bloque pas le processus
  1391.                 error_log('⚠️ Email error (non-blocking): ' $emailError->getMessage());
  1392.             }
  1393.             // Redirection selon le mode de paiement
  1394.             error_log('🔄 Redirecting to success page, method: ' $data['payment_method']);
  1395.             
  1396.             // 🧪 MODE TEST : Le paiement en ligne est automatiquement en succès
  1397.             error_log('🧪 [MODE TEST] Paiement en ligne simulé comme réussi');
  1398.             
  1399.             switch ($data['payment_method']) {
  1400.                 case 'online':
  1401.                     // Simulation de paiement en ligne réussi (mode test)
  1402.                     error_log('✅ [TEST] Paiement en ligne simulé - SUCCÈS automatique');
  1403.                     $this->addFlash('success''✅ Paiement réussi ! (Mode Test - Paiement simulé)');
  1404.                     return $this->redirectToRoute('checkout_success', ['method' => 'online']);
  1405.                     
  1406.                 case 'transfer':
  1407.                     $this->addFlash('info''Demande de virement enregistrée. Vous recevrez les coordonnées bancaires par email.');
  1408.                     return $this->redirectToRoute('checkout_success', ['method' => 'transfer']);
  1409.                     
  1410.                 case 'quote':
  1411.                     $this->addFlash('info''Demande de devis enregistrée. Vous recevrez le devis par email.');
  1412.                     return $this->redirectToRoute('checkout_success', ['method' => 'quote']);
  1413.                     
  1414.                 default:
  1415.                     error_log('❌ Invalid payment method: ' $data['payment_method']);
  1416.                     throw new \Exception('Mode de paiement invalide');
  1417.             }
  1418.         } catch (\Exception $e) {
  1419.             error_log('❌ CHECKOUT ERROR: ' $e->getMessage());
  1420.             error_log('Stack trace: ' $e->getTraceAsString());
  1421.             $this->addFlash('error''Une erreur est survenue. Veuillez réessayer. Détail: ' $e->getMessage());
  1422.             return $this->redirectToRoute('checkout_pack', ['pack' => $request->request->get('pack_id''serenite')]);
  1423.         }
  1424.     }
  1425.     /**
  1426.      * @Route("/checkout/success/{method}", name="checkout_success")
  1427.      */
  1428.     public function checkoutSuccess(Request $requeststring $method)
  1429.     {
  1430.         $data $request->getSession()->get('checkout_data');
  1431.         
  1432.         if (!$data) {
  1433.             return $this->redirectToRoute('page_Accueil');
  1434.         }
  1435.         return $this->render('Accueil/checkout_success.html.twig', [
  1436.             'data' => $data,
  1437.             'method' => $method
  1438.         ]);
  1439.     }
  1440.     /**
  1441.      * @Route("/Accueil5sur5/Pack_Pro_Illimite", name="pack_pro_illimite")
  1442.      */
  1443.     public function packProIllimite()
  1444.     {
  1445.         return $this->render('Accueil/pack_pro_illimite.html.twig');
  1446.     }
  1447.     /**
  1448.      * @Route("/bank-transfer-request", name="bank_transfer_request", methods={"POST"})
  1449.      */
  1450.     public function bankTransferRequest(Request $requestEntityManagerInterface $em): JsonResponse
  1451.     {
  1452.         try {
  1453.             $this->logger->info('🔍 Début de la demande de RIB');
  1454.             
  1455.             // Accepter les deux formats de paramètres
  1456.             $fullname $request->request->get('full_name') ?: $request->request->get('rib_fullname');
  1457.             $emailUser $request->request->get('billing_email') ?: $request->request->get('rib_email');
  1458.             $phone $request->request->get('phone') ?: $request->request->get('rib_phone');
  1459.             $org $request->request->get('company') ?: $request->request->get('rib_org');
  1460.             $message $request->request->get('message') ?: $request->request->get('rib_message');
  1461.             
  1462.             // Paramètres spécifiques au pack
  1463.             $packId $request->request->get('pack_id');
  1464.             $participants $request->request->get('participants');
  1465.             $totalAmount $request->request->get('total_amount');
  1466.             $startDate $request->request->get('start_date');
  1467.             $endDate $request->request->get('end_date');
  1468.             $theme $request->request->get('theme');
  1469.             $accompagnateur $request->request->get('accompagnateur');
  1470.             $this->logger->info('📝 Données reçues', [
  1471.                 'fullname' => $fullname,
  1472.                 'email' => $emailUser,
  1473.                 'pack_id' => $packId,
  1474.                 'participants' => $participants,
  1475.                 'total_amount' => $totalAmount,
  1476.                 'theme' => $theme,
  1477.                 'start_date' => $startDate,
  1478.                 'end_date' => $endDate
  1479.             ]);
  1480.             // Validation basique
  1481.             if (empty($fullname) || empty($emailUser)) {
  1482.                 return new JsonResponse([
  1483.                     'success' => false,
  1484.                     'message' => 'Le nom et l\'email sont obligatoires.'
  1485.                 ], 400);
  1486.             }
  1487.             // Générer un numéro de demande unique
  1488.             $requestNumber 'RIB-' date('Ymd') . '-' strtoupper(substr(md5(uniqid()), 06));
  1489.             $this->logger->info('🔢 Numéro de demande généré: ' $requestNumber);
  1490.             // Créer ou récupérer l'utilisateur accompagnateur
  1491.             try {
  1492.                 $this->logger->info('👤 Recherche utilisateur: ' $emailUser);
  1493.                 $userRepository $em->getRepository(User::class);
  1494.                 $user $userRepository->findOneBy(['email' => $emailUser]);
  1495.                 
  1496.                 if (!$user) {
  1497.                     $this->logger->info('➕ Création nouvel utilisateur');
  1498.                     $user = new User();
  1499.                     $user->setEmail($emailUser);
  1500.                     $user->setNom($fullname);
  1501.                     $user->setPrenom('');
  1502.                     $user->setTelephone($phone ?? '');
  1503.                     $user->setNometablisment($org ?? '');
  1504.                     
  1505.                     // Générer un mot de passe temporaire
  1506.                     $mdpTemp substr(md5(uniqid()), 08);
  1507.                     $user->setPassword(password_hash($mdpTempPASSWORD_BCRYPT));
  1508.                     $user->setRoles(['ROLE_ACCOMPAGNATEUR']);
  1509.                     $user->setStatut(1);
  1510.                     
  1511.                     $em->persist($user);
  1512.                     $em->flush();
  1513.                     
  1514.                     $this->logger->info('✅ Utilisateur créé: ID=' $user->getId());
  1515.                 } else {
  1516.                     $this->logger->info('✅ Utilisateur existant trouvé: ID=' $user->getId());
  1517.                 }
  1518.             } catch (\Exception $userError) {
  1519.                 $this->logger->error('❌ Erreur création utilisateur', [
  1520.                     'error' => $userError->getMessage(),
  1521.                     'trace' => $userError->getTraceAsString()
  1522.                 ]);
  1523.                 throw $userError;
  1524.             }
  1525.             
  1526.             // Déterminer si c'est un pack annuel (serenite/decouverte) ou un séjour simple
  1527.             $isPack in_array($packId, ['serenite''decouverte''Pack Sérénité''Pack Découverte']);
  1528.             $this->logger->info('🔍 Détection type de demande', [
  1529.                 'pack_id' => $packId,
  1530.                 'isPack' => $isPack 'OUI' 'NON',
  1531.                 'test_array' => ['serenite''decouverte''Pack Sérénité''Pack Découverte']
  1532.             ]);
  1533.             
  1534.             $sejour null;
  1535.             $commande null;
  1536.             
  1537.             if ($isPack) {
  1538.                 // ==================== CRÉATION COMMANDE PACK ====================
  1539.                 try {
  1540.                     $this->logger->info('📦 Création commande pack: ' $packId);
  1541.                     
  1542.                     // Mapping pack → labeletype
  1543.                     $packNames = [
  1544.                         'decouverte' => 'Pack Découverte',
  1545.                         'serenite' => 'Pack Sérénité',
  1546.                         'Pack Découverte' => 'Pack Découverte',
  1547.                         'Pack Sérénité' => 'Pack Sérénité'
  1548.                     ];
  1549.                     $packLabel $packNames[$packId] ?? 'Pack Sérénité';
  1550.                     
  1551.                     // Récupérer le produit en BDD
  1552.                     $typeProduit $em->getRepository(Typeproduit::class)->findOneBy([
  1553.                         'labeletype' => $packLabel
  1554.                     ]);
  1555.                     
  1556.                     // Récupérer le statut "en attente"
  1557.                     $statutEnAttente $em->getRepository(Ref::class)->find(1);
  1558.                     if (!$statutEnAttente) {
  1559.                         $statutEnAttente = new Ref();
  1560.                         $statutEnAttente->setLibiller('En attente');
  1561.                         $em->persist($statutEnAttente);
  1562.                         $em->flush();
  1563.                     }
  1564.                     
  1565.                     // Déterminer les montants du pack
  1566.                     $defaultsByPack = [
  1567.                         'Pack Sérénité' => ['ht' => 490'ttc' => 588],
  1568.                         'Pack Découverte' => ['ht' => 290'ttc' => 348],
  1569.                     ];
  1570.                     $montantHt $typeProduit $typeProduit->getMontantHt() : null;
  1571.                     $montantTtc $typeProduit $typeProduit->getMontantTTC() : null;
  1572.                     
  1573.                     if (empty($montantHt) || empty($montantTtc)) {
  1574.                         $fallback $defaultsByPack[$packLabel] ?? $defaultsByPack['Pack Sérénité'];
  1575.                         $montantHt $montantHt ?: $fallback['ht'];
  1576.                         $montantTtc $montantTtc ?: $fallback['ttc'];
  1577.                     }
  1578.                     
  1579.                     // Créer la commande avec statut "en attente"
  1580.                     $commande = new Commande();
  1581.                     $commande->setIdUser($user);
  1582.                     $commande->setStatut($statutEnAttente);
  1583.                     $commande->setMontantht($montantHt);
  1584.                     $commande->setMontantrth($montantTtc);
  1585.                     $commande->setMontanenv($montantTtc);
  1586.                     $commande->setTva(20);
  1587.                     
  1588.                     // Dates d'abonnement: début maintenant, fin dans 12 mois
  1589.                     $startDateTime = new \DateTime();
  1590.                     $endDateTime = (clone $startDateTime)->modify('+12 months');
  1591.                     
  1592.                     $commande->setDateCreateCommande($startDateTime);
  1593.                     $commande->setDateExpidition($endDateTime);
  1594.                     $commande->setPeriode('annuel');
  1595.                     $commande->setPaymentType('rib');
  1596.                     $commande->setNumComande(time());
  1597.                     
  1598.                     $this->logger->info('💾 Avant persist/flush commande');
  1599.                     $em->persist($commande);
  1600.                     $this->logger->info('💾 Après persist, avant flush');
  1601.                     $em->flush();
  1602.                     $this->logger->info('💾 Après flush');
  1603.                     
  1604.                     $commandeId $commande->getId();
  1605.                     $this->logger->info('✅ Commande pack créée: ID=' $commandeId ' Montant=' $montantTtc '€');
  1606.                     
  1607.                     // Vérifier que la commande existe vraiment en BDD
  1608.                     $commandeVerif $em->getRepository(Commande::class)->find($commandeId);
  1609.                     if ($commandeVerif) {
  1610.                         $this->logger->info('✅ VÉRIFICATION: Commande #' $commandeId ' existe bien en BDD');
  1611.                     } else {
  1612.                         $this->logger->error('❌ VÉRIFICATION: Commande #' $commandeId ' N\'EXISTE PAS en BDD !');
  1613.                     }
  1614.                     
  1615.                 } catch (\Exception $commandeError) {
  1616.                     $this->logger->error('❌ Erreur création commande pack', [
  1617.                         'error' => $commandeError->getMessage(),
  1618.                         'trace' => $commandeError->getTraceAsString()
  1619.                     ]);
  1620.                     // NE PAS continuer si la création échoue
  1621.                     return new JsonResponse([
  1622.                         'success' => false,
  1623.                         'message' => 'Erreur lors de la création de la commande: ' $commandeError->getMessage()
  1624.                     ], 500);
  1625.                 }
  1626.                 
  1627.             } else {
  1628.                 // ==================== CRÉATION SÉJOUR SIMPLE PF ====================
  1629.                 try {
  1630.                     $this->logger->info('🏕️ Création du séjour simple PF');
  1631.                     $dateDebut $startDate ?: date('Y-m-d');
  1632.                     $dateFin $endDate ?: date('Y-m-d'strtotime($dateDebut ' +7 days'));
  1633.                     $themeTexte $theme ?: 'Séjour';
  1634.                     $nbParticipants $participants ?: 10;
  1635.                     
  1636.                     $sejour $this->sejourService->CreationNouveauSejour(
  1637.                         $themeTexte,              // themSejour
  1638.                         '',                       // adressSejour
  1639.                         '',                       // codePostal
  1640.                         $dateDebut,              // dateDebut
  1641.                         $dateFin,                // FinSejour
  1642.                         '6-10 ans',              // AgeDugroupe
  1643.                         'PF',                    // type (Partenaire Financé)
  1644.                         $user->getId(),          // userid
  1645.                         $nbParticipants,         // NbEnfant
  1646.                         0,                       // connpay (0 = non payé)
  1647.                         'France',                // pays
  1648.                         '',                      // ville
  1649.                         null,                    // prixcnxparent
  1650.                         null,                    // prixcnxpartenaire
  1651.                         null,                    // reversecnxpart
  1652.                         null                     // reverseventepart
  1653.                     );
  1654.                     
  1655.                     // Récupérer ou créer le statut "attente_paiement"
  1656.                     $statutAttentePaiement $em->getRepository(Ref::class)->findOneBy(['libiller' => 'attente_paiement']);
  1657.                     
  1658.                     if (!$statutAttentePaiement) {
  1659.                         $this->logger->warning('⚠️ Statut "attente_paiement" non trouvé');
  1660.                     } else {
  1661.                         $sejour->setStatut($statutAttentePaiement);
  1662.                         $em->flush();
  1663.                         $this->logger->info('✅ Statut défini: ' $statutAttentePaiement->getLibiller());
  1664.                     }
  1665.                     
  1666.                     $this->logger->info('✅ Séjour créé: Code=' $sejour->getCodeSejour() . ' ID=' $sejour->getId());
  1667.                 } catch (\Exception $sejourError) {
  1668.                     $this->logger->error('❌ Erreur création séjour', [
  1669.                         'error' => $sejourError->getMessage(),
  1670.                         'trace' => $sejourError->getTraceAsString()
  1671.                     ]);
  1672.                     throw $sejourError;
  1673.                 }
  1674.             }
  1675.             // Envoyer email à l'équipe avec les informations complètes
  1676.             $emailContext = [
  1677.                 'fullname' => $fullname,
  1678.                 'user_email' => $emailUser,
  1679.                 'phone' => $phone,
  1680.                 'org' => $org,
  1681.                 'message' => $message,
  1682.                 'pack_id' => $packId,
  1683.                 'participants' => $participants,
  1684.                 'total_amount' => $totalAmount,
  1685.                 'start_date' => $startDate,
  1686.                 'end_date' => $endDate,
  1687.                 'theme' => $theme,
  1688.                 'accompagnateur' => $accompagnateur,
  1689.                 'request_number' => $requestNumber,
  1690.             ];
  1691.             
  1692.             // Ajouter les infos spécifiques selon le type
  1693.             if ($isPack && $commande) {
  1694.                 $emailContext['commande_id'] = $commande->getId();
  1695.                 $emailContext['commande_numero'] = $commande->getNumComande();
  1696.                 $emailContext['montant_ht'] = $commande->getMontantht();
  1697.                 $emailContext['montant_ttc'] = $commande->getMontantrth();
  1698.                 $emailContext['is_pack'] = true;
  1699.             } else if ($sejour) {
  1700.                 $emailContext['code_sejour'] = $sejour->getCodeSejour();
  1701.                 $emailContext['sejour_id'] = $sejour->getId();
  1702.                 $emailContext['is_pack'] = false;
  1703.             }
  1704.             
  1705.             $subjectPrefix $isPack '📦 Demande RIB Pack Annuel' '🏦 Demande RIB Paiement Séjour Simple';
  1706.             
  1707.             // Ajouter le numéro de commande au sujet si c'est un pack
  1708.             $subjectSuffix $requestNumber;
  1709.             if ($isPack && $commande) {
  1710.                 $subjectSuffix .= ' - Commande #' $commande->getNumComande();
  1711.             }
  1712.             
  1713.             $teamEmail = (new TemplatedEmail())
  1714.                 ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  1715.                 ->to('partenariat@5sur5sejour.com')
  1716.                 ->cc('ramzi.benlarbi@gmail.com''yousra.tlich@gmail.com')
  1717.                 ->subject($subjectPrefix ' - ' $org ' - ' $subjectSuffix)
  1718.                 ->htmlTemplate('emails/bank_transfer_request_team.html.twig')
  1719.                 ->context($emailContext);
  1720.             $this->mailer->send($teamEmail);
  1721.             // Email de confirmation au client avec RIB
  1722.             $ribDetails = [
  1723.                 'iban' => 'FR76 1010 7001 5300 0123 4567 890',
  1724.                 'bic' => 'BREDFRPPXXX',
  1725.                 'beneficiaire' => '5SUR5 SEJOUR',
  1726.                 'reference' => $requestNumber
  1727.             ];
  1728.             // Préparer le contexte email client
  1729.             $clientEmailContext = [
  1730.                 'fullname' => $fullname,
  1731.                 'request_number' => $requestNumber,
  1732.                 'rib' => $ribDetails,
  1733.                 'pack_id' => $packId,
  1734.                 'participants' => $participants,
  1735.                 'total_amount' => $totalAmount,
  1736.                 'start_date' => $startDate,
  1737.                 'end_date' => $endDate,
  1738.                 'theme' => $theme,
  1739.                 'accompagnateur' => $accompagnateur,
  1740.                 'org' => $org,
  1741.             ];
  1742.             
  1743.             // Ajouter les infos spécifiques
  1744.             if ($isPack && $commande) {
  1745.                 $clientEmailContext['commande_id'] = $commande->getId();
  1746.                 $clientEmailContext['commande_numero'] = $commande->getNumComande();
  1747.                 $clientEmailContext['montant_ht'] = $commande->getMontantht();
  1748.                 $clientEmailContext['montant_ttc'] = $commande->getMontantrth();
  1749.                 $clientEmailContext['is_pack'] = true;
  1750.             } else if ($sejour) {
  1751.                 $clientEmailContext['code_sejour'] = $sejour->getCodeSejour();
  1752.                 $clientEmailContext['sejour_id'] = $sejour->getId();
  1753.                 $clientEmailContext['is_pack'] = false;
  1754.             }
  1755.             
  1756.             $clientEmail = (new TemplatedEmail())
  1757.                 ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  1758.                 ->to($emailUser)
  1759.                 ->subject('RIB et Facture Proforma - ' $requestNumber ' - 5sur5 Séjour')
  1760.                 ->htmlTemplate('emails/bank_transfer_request_client.html.twig')
  1761.                 ->context($clientEmailContext);
  1762.             $this->mailer->send($clientEmail);
  1763.             return new JsonResponse([
  1764.                 'success' => true,
  1765.                 'message' => 'Votre demande a été envoyée avec succès ! Vous allez recevoir le RIB et la facture proforma par email.',
  1766.                 'requestNumber' => $requestNumber
  1767.             ]);
  1768.         } catch (\Exception $e) {
  1769.             $this->logger->error('Erreur lors de l\'envoi de la demande de RIB', [
  1770.                 'error' => $e->getMessage(),
  1771.                 'trace' => $e->getTraceAsString()
  1772.             ]);
  1773.             return new JsonResponse([
  1774.                 'success' => false,
  1775.                 'message' => 'Erreur: ' $e->getMessage(),
  1776.                 'error' => $e->getMessage(),
  1777.                 'trace' => $e->getTraceAsString()
  1778.             ], 500);
  1779.         }
  1780.     }
  1781.     /**
  1782.      * @Route("/pack-request-submit", name="pack_request_submit", methods={"POST"})
  1783.      */
  1784.     public function packRequestSubmit(Request $request): JsonResponse
  1785.     {
  1786.         try {
  1787.             $fullname $request->request->get('pack_fullname');
  1788.             $email $request->request->get('pack_email');
  1789.             $phone $request->request->get('pack_phone');
  1790.             $org $request->request->get('pack_org');
  1791.             $packType $request->request->get('pack_type');
  1792.             $message $request->request->get('pack_message');
  1793.             // Validation basique
  1794.             if (empty($fullname) || empty($email) || empty($packType)) {
  1795.                 return new JsonResponse([
  1796.                     'success' => false,
  1797.                     'message' => 'Le nom, l\'email et le type de pack sont obligatoires.'
  1798.                 ], 400);
  1799.             }
  1800.             // Envoyer email à l'équipe
  1801.             $email = (new TemplatedEmail())
  1802.                 ->from(new Address('noreply@5sur5sejour.fr''5sur5 Séjour'))
  1803.                 ->to('contact@5sur5sejour.fr')
  1804.                 ->subject('Demande de Pack Partenaire - ' $fullname)
  1805.                 ->htmlTemplate('emails/pack_request_team.html.twig')
  1806.                 ->context([
  1807.                     'fullname' => $fullname,
  1808.                     'email' => $email,
  1809.                     'phone' => $phone,
  1810.                     'org' => $org,
  1811.                     'packType' => $packType,
  1812.                     'message' => $message
  1813.                 ]);
  1814.             $this->mailer->send($email);
  1815.             // Email de confirmation au client
  1816.             $clientEmail = (new TemplatedEmail())
  1817.                 ->from(new Address('noreply@5sur5sejour.fr''5sur5 Séjour'))
  1818.                 ->to($email)
  1819.                 ->subject('Demande de Pack Partenaire reçue - 5sur5 Séjour')
  1820.                 ->htmlTemplate('emails/pack_request_partner.html.twig')
  1821.                 ->context([
  1822.                     'fullname' => $fullname,
  1823.                     'packType' => $packType
  1824.                 ]);
  1825.             $this->mailer->send($clientEmail);
  1826.             return new JsonResponse([
  1827.                 'success' => true,
  1828.                 'message' => 'Votre demande de pack partenaire a été envoyée avec succès ! Nous vous recontacterons dans les 24 heures.'
  1829.             ]);
  1830.         } catch (\Exception $e) {
  1831.             $this->logger->error('Erreur lors de l\'envoi de la demande de pack', [
  1832.                 'error' => $e->getMessage(),
  1833.                 'trace' => $e->getTraceAsString()
  1834.             ]);
  1835.             return new JsonResponse([
  1836.                 'success' => false,
  1837.                 'message' => 'Une erreur est survenue lors de l\'envoi de la demande. Veuillez réessayer plus tard.'
  1838.             ], 500);
  1839.         }
  1840.     }
  1841.     /**
  1842.      * @Route("/checkout-create-session", name="checkout_create_session", methods={"POST"})
  1843.      */
  1844.     public function checkoutCreateSession(Request $request): JsonResponse
  1845.     {
  1846.         try {
  1847.             $company $request->request->get('company');
  1848.             $contactName $request->request->get('contact_name');
  1849.             $email $request->request->get('email');
  1850.             $phone $request->request->get('phone');
  1851.             $packType $request->request->get('pack_type');
  1852.             $address $request->request->get('address');
  1853.             $city $request->request->get('city');
  1854.             $postalCode $request->request->get('postal_code');
  1855.             $siret $request->request->get('siret');
  1856.             // Validation basique
  1857.             if (empty($company) || empty($contactName) || empty($email) || empty($packType)) {
  1858.                 return new JsonResponse([
  1859.                     'success' => false,
  1860.                     'message' => 'Les champs obligatoires doivent être remplis.'
  1861.                 ], 400);
  1862.             }
  1863.             // Envoyer email à l'équipe
  1864.             $email = (new TemplatedEmail())
  1865.                 ->from(new Address('noreply@5sur5sejour.fr''5sur5 Séjour'))
  1866.                 ->to('contact@5sur5sejour.fr')
  1867.                 ->subject('Nouvelle souscription en ligne - ' $company)
  1868.                 ->htmlTemplate('emails/checkout_request_team.html.twig')
  1869.                 ->context([
  1870.                     'company' => $company,
  1871.                     'contactName' => $contactName,
  1872.                     'email' => $email,
  1873.                     'phone' => $phone,
  1874.                     'packType' => $packType,
  1875.                     'address' => $address,
  1876.                     'city' => $city,
  1877.                     'postalCode' => $postalCode,
  1878.                     'siret' => $siret
  1879.                 ]);
  1880.             $this->mailer->send($email);
  1881.             // Email de confirmation au client
  1882.             $clientEmail = (new TemplatedEmail())
  1883.                 ->from(new Address('noreply@5sur5sejour.fr''5sur5 Séjour'))
  1884.                 ->to($email)
  1885.                 ->subject('Souscription reçue - 5sur5 Séjour')
  1886.                 ->htmlTemplate('emails/checkout_request_client.html.twig')
  1887.                 ->context([
  1888.                     'company' => $company,
  1889.                     'contactName' => $contactName,
  1890.                     'packType' => $packType
  1891.                 ]);
  1892.             $this->mailer->send($clientEmail);
  1893.             return new JsonResponse([
  1894.                 'success' => true,
  1895.                 'message' => 'Votre souscription a été enregistrée avec succès ! Nous vous recontacterons dans les 24 heures pour finaliser l\'activation.'
  1896.             ]);
  1897.         } catch (\Exception $e) {
  1898.             $this->logger->error('Erreur lors de l\'enregistrement de la souscription', [
  1899.                 'error' => $e->getMessage(),
  1900.                 'trace' => $e->getTraceAsString()
  1901.             ]);
  1902.             return new JsonResponse([
  1903.                 'success' => false,
  1904.                 'message' => 'Une erreur est survenue lors de l\'enregistrement. Veuillez réessayer plus tard.'
  1905.             ], 500);
  1906.         }
  1907.     }
  1908.     /**
  1909.      * @Route("/quote-request", name="quote_request", methods={"POST"})
  1910.      */
  1911.     public function quoteRequest(Request $request): JsonResponse
  1912.     {
  1913.         try {
  1914.             $orgType $request->request->get('org_type');
  1915.             $orgName $request->request->get('org_name');
  1916.             $contactName $request->request->get('contact_name');
  1917.             $email $request->request->get('email');
  1918.             $phone $request->request->get('phone');
  1919.             $packType $request->request->get('pack_type');
  1920.             $address $request->request->get('address');
  1921.             $city $request->request->get('city');
  1922.             $postalCode $request->request->get('postal_code');
  1923.             $message $request->request->get('message');
  1924.             // Validation basique
  1925.             if (empty($orgType) || empty($orgName) || empty($contactName) || empty($email) || empty($packType)) {
  1926.                 return new JsonResponse([
  1927.                     'success' => false,
  1928.                     'message' => 'Les champs obligatoires doivent être remplis.'
  1929.                 ], 400);
  1930.             }
  1931.             // Envoyer email à l'équipe
  1932.             $email = (new TemplatedEmail())
  1933.                 ->from(new Address('noreply@5sur5sejour.fr''5sur5 Séjour'))
  1934.                 ->to('contact@5sur5sejour.fr')
  1935.                 ->subject('Demande de devis - ' $orgName)
  1936.                 ->htmlTemplate('emails/quote_request_team.html.twig')
  1937.                 ->context([
  1938.                     'orgType' => $orgType,
  1939.                     'orgName' => $orgName,
  1940.                     'contactName' => $contactName,
  1941.                     'email' => $email,
  1942.                     'phone' => $phone,
  1943.                     'packType' => $packType,
  1944.                     'address' => $address,
  1945.                     'city' => $city,
  1946.                     'postalCode' => $postalCode,
  1947.                     'message' => $message
  1948.                 ]);
  1949.             $this->mailer->send($email);
  1950.             // Email de confirmation au client
  1951.             $clientEmail = (new TemplatedEmail())
  1952.                 ->from(new Address('noreply@5sur5sejour.fr''5sur5 Séjour'))
  1953.                 ->to($email)
  1954.                 ->subject('Demande de devis reçue - 5sur5 Séjour')
  1955.                 ->htmlTemplate('emails/quote_request_client.html.twig')
  1956.                 ->context([
  1957.                     'orgName' => $orgName,
  1958.                     'contactName' => $contactName,
  1959.                     'packType' => $packType
  1960.                 ]);
  1961.             $this->mailer->send($clientEmail);
  1962.             return new JsonResponse([
  1963.                 'success' => true,
  1964.                 'message' => 'Votre demande de devis a été envoyée avec succès ! Nous vous recontacterons dans les 24 heures.'
  1965.             ]);
  1966.         } catch (\Exception $e) {
  1967.             $this->logger->error('Erreur lors de l\'envoi de la demande de devis', [
  1968.                 'error' => $e->getMessage(),
  1969.                 'trace' => $e->getTraceAsString()
  1970.             ]);
  1971.             return new JsonResponse([
  1972.                 'success' => false,
  1973.                 'message' => 'Une erreur est survenue lors de l\'envoi de la demande. Veuillez réessayer plus tard.'
  1974.             ], 500);
  1975.         }
  1976.     }
  1977.     /**
  1978.      * @Route("/creation-simple/send-rib-codes", name="app_creation_simple_send_rib_codes", methods={"POST","GET"})
  1979.      */
  1980.     public function sendRibCodes(Request $requestEntityManagerInterface $em): JsonResponse
  1981.     {
  1982.         if ($request->isMethod('GET')) {
  1983.             return new JsonResponse([
  1984.                 'success' => false,
  1985.                 'message' => 'Cette URL est réservée aux requêtes sécurisées. Merci d\'utiliser le formulaire de création de séjour.'
  1986.             ], 405);
  1987.         }
  1988.         try {
  1989.             $data json_decode($request->getContent(), true);
  1990.             $sejourId $data['sejour_id'] ?? null;
  1991.             $billingEmail $data['billing_email'] ?? null;
  1992.             $billingContact $data['billing_contact'] ?? null;
  1993.             if (!$sejourId || !$billingEmail) {
  1994.                 return new JsonResponse([
  1995.                     'success' => false,
  1996.                     'message' => 'Données manquantes'
  1997.                 ], 400);
  1998.             }
  1999.             $sejour $em->getRepository(\App\Entity\Sejour::class)->find($sejourId);
  2000.             if (!$sejour) {
  2001.                 return new JsonResponse([
  2002.                     'success' => false,
  2003.                     'message' => 'Séjour non trouvé'
  2004.                 ], 404);
  2005.             }
  2006.             $commande $em->getRepository(Commande::class)->findOneBy(['idSejour' => $sejour]);
  2007.             if (!$commande) {
  2008.                 return new JsonResponse([
  2009.                     'success' => false,
  2010.                     'message' => 'Commande non trouvée'
  2011.                 ], 404);
  2012.             }
  2013.             $user $sejour->getIdPartenaire();
  2014.             if (!$user) {
  2015.                 return new JsonResponse([
  2016.                     'success' => false,
  2017.                     'message' => 'Utilisateur non trouvé'
  2018.                 ], 404);
  2019.             }
  2020.             // Envoyer email avec RIB + codes séjour
  2021.             $email = (new TemplatedEmail())
  2022.                 ->from(new Address('info@5sur5sejour.com''5sur5 Séjour'))
  2023.                 ->to($billingEmail)
  2024.                 ->subject('RIB et codes séjour - ' $sejour->getCodeSejour())
  2025.                 ->htmlTemplate('emails/sejour_simple/rib_codes.html.twig')
  2026.                 ->context([
  2027.                     'sejour' => $sejour,
  2028.                     'commande' => $commande,
  2029.                     'user' => $user,
  2030.                     'billingContact' => $billingContact
  2031.                 ]);
  2032.             $this->mailer->send($email);
  2033.             // Envoyer aussi les codes à l'accompagnateur
  2034.             $accompagnateur $sejour->getIdAcommp();
  2035.             if ($accompagnateur && $accompagnateur->getReponseemail()) {
  2036.                 $this->UserService->EnvoyerEmailAcommpatActivationNewMail($sejour$accompagnateur);
  2037.             }
  2038.             return new JsonResponse([
  2039.                 'success' => true,
  2040.                 'message' => 'RIB et codes séjour envoyés avec succès'
  2041.             ]);
  2042.         } catch (\Exception $e) {
  2043.             $this->logger->error('Erreur lors de l\'envoi RIB + codes', [
  2044.                 'error' => $e->getMessage(),
  2045.                 'trace' => $e->getTraceAsString()
  2046.             ]);
  2047.             return new JsonResponse([
  2048.                 'success' => false,
  2049.                 'message' => 'Une erreur est survenue lors de l\'envoi'
  2050.             ], 500);
  2051.         }
  2052.     }
  2053.     /**
  2054.      * @Route("/creation-simple/checkout", name="app_creation_simple_checkout", methods={"GET"})
  2055.      */
  2056.     public function checkoutSejourSimple(Request $requestEntityManagerInterface $em): Response
  2057.     {
  2058.         $sejourId $request->query->get('sejour_id');
  2059.         if (!$sejourId) {
  2060.             return $this->redirectToRoute('app_creation_simple_creer');
  2061.         }
  2062.         $sejour $em->getRepository(\App\Entity\Sejour::class)->find($sejourId);
  2063.         if (!$sejour) {
  2064.             return $this->redirectToRoute('app_creation_simple_creer');
  2065.         }
  2066.         $commande $em->getRepository(Commande::class)->findOneBy(['idSejour' => $sejour]);
  2067.         if (!$commande) {
  2068.             return $this->redirectToRoute('app_creation_simple_creer');
  2069.         }
  2070.         // Stocker la commande en session pour Payplug
  2071.         $session $request->getSession();
  2072.         $session->set('commandeActual'$commande->getId());
  2073.         // Rediriger vers Payplug (route dédiée aux séjours simples, sans authentification requise)
  2074.         return $this->redirectToRoute('sejour_simple_payplug_chargement_form');
  2075.     }
  2076. }