src/Controller/ReservationController.php line 641

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Client;
  4. use App\Entity\Client\BillingInfos;
  5. use App\Entity\Product\Famille;
  6. use App\Entity\RDV;
  7. use App\Entity\RDVProduct;
  8. use App\Entity\Salon;
  9. use App\Entity\Site;
  10. use App\Form\ClientType;
  11. use App\Form\RDVType;
  12. use App\Repository\ClientRepository;
  13. use App\Repository\CompanyRepository;
  14. use App\Repository\FamilleRepository;
  15. use App\Repository\ProductRepository;
  16. use App\Repository\ProductServiceRepository;
  17. use App\Repository\RDVProductRepository;
  18. use App\Repository\RDVRepository;
  19. use App\Repository\SalonRepository;
  20. use App\Repository\SessionSalonRepository;
  21. use App\Repository\SousFamilleRepository;
  22. use App\Service\CreateUserService;
  23. use App\Service\MailService;
  24. use App\Service\PaytweakService;
  25. use App\Traits\RDVManagerTrait;
  26. use Doctrine\Persistence\ManagerRegistry;
  27. use Symfony\Component\HttpFoundation\Response;
  28. use Symfony\Component\Routing\Annotation\Route;
  29. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  30. use Symfony\Component\HttpFoundation\Request;
  31. /**
  32.  * @Route("/reservation")
  33.  */
  34. class ReservationController extends AbstractController
  35. {
  36.     use RDVManagerTrait;
  37.     /**
  38.      * @Route("/", name="rdv_index")
  39.      */
  40.     public function index(SalonRepository $salonRepository): Response
  41.     {
  42.         return $this->render('reservation/index.html.twig', [
  43.             'types' => Site::getSiteTypes(),
  44.             'services' => Salon::getServices(),
  45.             'salons' => $salonRepository->findSalonsByTypeAndService(Site::TYPE_SSRSalon::SERVICE_COIFFURE),
  46.         ]);
  47.     }
  48.     /**
  49.      * @Route("/{salon}", name="rdv_category_selection", methods={"GET"})
  50.      */
  51.     public function categorySelection(Salon $salonFamilleRepository $familleRepository): Response
  52.     {
  53.         $familles $familleRepository->findBy(['isReservation' => true]);
  54.         $typeSalon $salon->getService();
  55.         foreach ($familles as $key => $famille) {
  56.             if (preg_match('/esthétique|esthetique/i'$famille->getName()) && $typeSalon === 'coiffure') {
  57.                 unset($familles[$key]);
  58.             }
  59.             if (preg_match('/coiffure/i'$famille->getName()) && $typeSalon === 'esthetique') {
  60.                 unset($familles[$key]);
  61.             }
  62.         }
  63.         return $this->render('reservation/category_selection.html.twig', [
  64.             'salon' => $salon,
  65.             'familles' => $familles
  66.         ]);
  67.     }
  68.     /**
  69.      * @Route("/{salon}/{famille}", name="rdv_product_selection")
  70.      */
  71.     public function productSelection(
  72.         Salon $salon,
  73.         Famille $famille,
  74.         ProductRepository $productRepository,
  75.         ProductServiceRepository $productServiceRepository,
  76.         SousFamilleRepository $sousFamilleRepository,
  77.         Request $request,
  78.         ManagerRegistry $doctrine,
  79.         PaytweakService $paytweakService,
  80.         ClientRepository $clientRepository,
  81.         SessionSalonRepository $sessionSalonRepository,
  82.         RDVRepository $rdvRepository
  83.     ): Response {
  84.         $typeSite $salon->getSite()->getType();
  85.         $products $productRepository->getProductsByFamily($famille);
  86.         $productIds array_map(function ($e) {
  87.             return $e->getId();
  88.         }, $products);
  89.         $sousFamilleIds array_map(function ($e) {
  90.             return $e->getSousFamille()->getId();
  91.         }, $products);
  92.         $service $this->serviceName(strtolower($famille->getName()));
  93.         $productServices $productServiceRepository->findByProductIds($productIds);
  94.         $rdv = new RDV();
  95.         $form $this->createForm(RDVType::class, $rdv, [
  96.             'view' => 'client',
  97.             'famille' => $famille,
  98.             'productIds' => $productIds
  99.         ]);
  100.         $form->handleRequest($request);
  101.         if ($form->isSubmitted() && $form->isValid()) {
  102.             /** @var array $params */
  103.             $params $request->request->get('rdv');
  104.             $session $request->getSession();
  105.             $session->clear();
  106.             $session->set('recurrence'$params['recurrence']);
  107.             $session->set('civilite'$params['civilite']);
  108.             $session->set('lastname'$params['lastname']);
  109.             $session->set('firstname'$params['firstname']);
  110.             $session->set('email'$params['email']);
  111.             $session->set('hasAddService'$params['hasAddService']);
  112.             $session->set('comment'$params['comment']);
  113.             $session->set('isSession'true);
  114.             foreach ($params['products'] as $productId) {
  115.                 $product $productRepository->findOneById((int)$productId);
  116.                 if ($product->getSousFamille()->isOneChoice()) { // radio
  117.                     $session->set('sousfamille_' $product->getSousFamille()->getId(), (int) $productId);
  118.                 } else { //checkbox
  119.                     $session->set('product_' $productId, (int) $productId);
  120.                 }
  121.             }
  122.             if (empty($params['start'])) {
  123.                 $this->addFlash('danger''Une erreur s\'est produite lors que vous êtes retourné en arrière, veuillez réessayer');
  124.                 return $this->redirectToRoute('rdv_product_selection', [
  125.                     'salon' => $salon->getId(),
  126.                     'famille' => $famille->getId(),
  127.                 ]);
  128.             }
  129.             // check if date available
  130.             $isDateAvailable $this->checkDateAvailability($params['start'], $rdvRepository$salon);
  131.             if ($isDateAvailable === false) {
  132.                 $this->addFlash('danger''La date n\'est pas disponible, veuillez réessayer');
  133.                 return $this->redirectToRoute('rdv_product_selection', [
  134.                     'salon' => $salon->getId(),
  135.                     'famille' => $famille->getId(),
  136.                 ]);
  137.             }
  138.             $clientExist null;
  139.             $orderIdPaytweak null;
  140.             $paymentLink false;
  141.             $em $doctrine->getManager();
  142.             // save the product for the rdv
  143.             if (!empty($form->getExtraData())) {
  144.                 $products $form->getExtraData()['products'];
  145.                 $rdvProducts = [];
  146.                 foreach ($products as $productId) {
  147.                     $product $productRepository->findOneById((int)$productId);
  148.                     $rdvProduct = new RDVProduct();
  149.                     $rdvProduct->setProduct($product);
  150.                     $rdvProduct->setRdv($rdv);
  151.                     $rdvProducts[] = $rdvProduct;
  152.                 }
  153.                 $clientExist $clientRepository->findOneBy([
  154.                     'lastname' => $params['lastname'],
  155.                     'firstname' => $params['firstname'],
  156.                     'civilite' => $params['civilite'],
  157.                     'site' => $salon->getSite(),
  158.                 ]);
  159.                 // check also
  160.                 if($clientExist){
  161.                     /** @var RDV $lastRDV */
  162.                     $lastRDV $this->RDVManager->getRepository()->findOneByClientAndToken($clientExist);
  163.                     if($lastRDV){
  164.                         $paymentLink $lastRDV->getPaymentLink();
  165.                         $path parse_url($paymentLinkPHP_URL_PATH);
  166.                         $orderIdPaytweak basename($path);
  167.                     }
  168.                 }
  169.                 $rdv->setClient($clientExist);
  170.                 /** @var SessionSalon $sessionSalon */
  171.                 $date = new \DateTime($params['start']);
  172.                 $sessionSalon $sessionSalonRepository->findSessionBySalonAndDate($salon$date);
  173.                 $end = clone $date;
  174.                 $sessionLength $typeSite === Site::TYPE_EHPAD '+15 minutes' '+30 minutes';
  175.                 $end->modify($sessionLength);
  176.                 $rdv->setStart($date);
  177.                 $rdv->setEnd($end);
  178.                 $rdv->setIntervenant($sessionSalon[0]->getIntervenant());
  179.                 $rdv->setRdvProducts($rdvProducts);
  180.                 $rdv->setStatus(RDV::STATUS_NON_PAYE);
  181.                 $rdv->setSalon($salon);
  182.                 $rdv->setIsPlatform(true);
  183.                 $em->persist($rdv);
  184.                 $em->flush();
  185.             }
  186.             else {
  187.                 $this->addFlash('danger''Aucun forfait selectionné');
  188.                 return $this->redirectToRoute('rdv_product_selection', [
  189.                     'salon' => $salon->getId(),
  190.                     'famille' => $famille->getId(),
  191.                 ]);
  192.             }
  193.             // api call for Paytweak
  194.             if($clientExist && $paymentLink){
  195.             }
  196.             else {
  197.                 $response $paytweakService->createLink($orderIdPaytweak);
  198.                 if ($response['code'] !== 'OK') {
  199.                     // delete rdv if api KO
  200.                     $em->remove($rdv);
  201.                     $em->flush();
  202.                     $this->addFlash('danger''Une erreur s\'est produite, veuillez réessayer');
  203.                     return $this->redirectToRoute('rdv_product_selection', [
  204.                         'salon' => $salon->getId(),
  205.                         'famille' => $famille->getId(),
  206.                     ]);
  207.                 }
  208.                 else { // for payment
  209.                     $rdv->setOrderId($response['order_id']);
  210.                     $rdv->setPaymentLink($response['url']);
  211.                     $em->persist($rdv);
  212.                     $em->flush();
  213.                 }
  214.             }
  215.             // redirect to payment if client is fully authenticated
  216.             if ($clientExist) {
  217.                 return $this->redirectToRoute('rdv_summary', [
  218.                     'salon' => $salon->getId(),
  219.                     'famille' => $famille->getId(),
  220.                     'rdv' => $rdv,
  221.                     'alreadyPaid' => !!$paymentLink
  222.                 ]);
  223.             } else {
  224.                 $this->addFlash('info''Veuillez remplir votre fiche client avant de procéder au paiement');
  225.                 $session $request->getSession();
  226.                 $session->set('civilite'$params['civilite']);
  227.                 $session->set('lastname'$params['lastname']);
  228.                 $session->set('firstname'$params['firstname']);
  229.                 $session->set('email'$params['email']);
  230.                 return $this->redirectToRoute('new_client', [
  231.                     'salon' => $salon->getId(),
  232.                     'famille' => $famille->getId(),
  233.                     'rdv' => $rdv->getId(),
  234.                 ]);
  235.             }
  236.         }
  237.         $datesCalendar $this->prepareDatesCalendar($sessionSalonRepository$rdvRepository$service$salon); // available dates for calendar picker
  238.         $halfHour in_array($typeSite, [Site::TYPE_SSRSite::TYPE_RESIDENCE]); // 15 or 30 min
  239.         return $this->render('reservation/product_selection.html.twig', [
  240.             'salon' => $salon->getId(),
  241.             'products' => $products,
  242.             'famille' => $famille,
  243.             'sousFamilles' => $sousFamilleRepository->findByFamille($famille),
  244.             'productServices' => $productServices,
  245.             'form' => $form->createView(),
  246.             'sousFamilleIds' => $sousFamilleIds,
  247.             'service' => $service,
  248.             'minuteIncrement' => $halfHour 30 15,
  249.             'maxTime' => $halfHour '17:30' '17:45',
  250.             'availableDateTime' => $datesCalendar['availableDateTime'],
  251.             'datesToDisable' => $datesCalendar['datesToDisable']
  252.         ]);
  253.     }
  254.     /**
  255.      * @Route("/{salon}/{famille}/{rdv}/client/new", name="new_client")
  256.      */
  257.     public function newClient(
  258.         Salon $salon,
  259.         Famille $famille,
  260.         RDV $rdv,
  261.         Request $request,
  262.         ManagerRegistry $doctrine,
  263.         CreateUserService $createUserService,
  264.         ClientRepository $clientRepository,
  265.         CompanyRepository $companyRepository
  266.     ): Response {
  267.         $client = new Client();
  268.         $form $this->createForm(ClientType::class, $client, ['isReservation' => true]);
  269.         $form->handleRequest($request);
  270.         if ($form->isSubmitted() && $form->isValid()) {
  271.             if ($rdv->getClient() !== null) { // avoid creating multiple instances
  272.                 return $this->redirectToRoute('rdv_summary', [
  273.                     'salon' => $salon->getId(),
  274.                     'famille' => $famille->getId(),
  275.                     'rdv' => $rdv,
  276.                 ]);
  277.             }
  278.             $em $doctrine->getManager();
  279.             // create new User
  280.             $createUserService->checkAndAddUser(
  281.                 $client,
  282.                 $doctrine
  283.             );
  284.             // check if client is already created
  285.             $clientExists $clientRepository->findOneBy([
  286.                 'civilite' => $client->getCivilite(),
  287.                 'lastname' => $client->getLastname(),
  288.                 'firstname' => $client->getFirstname(),
  289.                 'site' => $salon->getSite(),
  290.             ]);
  291.             // create new Client if don't exist
  292.             if ($clientExists === null) {
  293.                 // new billing infos
  294.                 $billingInfos = new BillingInfos();
  295.                 $company $companyRepository->findOneBy(['mail' => 'contact@silverbeaute.com']);
  296.                 $billingInfos->setCompany($company);
  297.                 $billingInfos->setBillingMode(BillingInfos::BILLING_MODE_TTC);
  298.                 $billingInfos->setAccount('411' $client->getLastname());
  299.                 $billingInfos->setEmail($client->getEmail());
  300.                 $billingInfos->setSendMode(BillingInfos::SEND_MODE_EMAIL);
  301.                 $em->persist($billingInfos);
  302.                 $em->flush();
  303.                 $client->setBillingInfos($billingInfos);
  304.                 $client->setSite($salon->getSite());
  305.                 $em->persist($client);
  306.                 $em->flush();
  307.                 $client->setIdentifier($client->getId() . ' ' $client->getLastname());
  308.                 $em->persist($client);
  309.                 $em->flush();
  310.                 $rdv->setClient($client); // link client with rdv
  311.             } else {
  312.                 $rdv->setClient($clientExists);
  313.             }
  314.             $em->persist($rdv);
  315.             $em->flush();
  316.             // redirect to summary page after new client is created
  317.             return $this->redirectToRoute('rdv_summary', [
  318.                 'salon' => $salon->getId(),
  319.                 'famille' => $famille->getId(),
  320.                 'rdv' => $rdv,
  321.             ]);
  322.         }
  323.         return $this->render('reservation/new_client.html.twig', [
  324.             'form' => $form->createView(),
  325.         ]);
  326.     }
  327.     /**
  328.      * @Route("/{salon}/{famille}/{rdv}/summary/{alreadyPaid}", name="rdv_summary")
  329.      */
  330.     public function summary(
  331.         Salon $salon,
  332.         Famille $famille,
  333.         RDV $rdv,
  334.         RDVProductRepository $RdvProductRepository,
  335.         Request $request,
  336.         $alreadyPaid null
  337.     ): Response {
  338.         $total 0;
  339.         $products = [];
  340.         $rdvProducts $RdvProductRepository->findBy(['rdv' => $rdv]);
  341.         foreach ($rdvProducts as $rdvProduct) {
  342.             $product $rdvProduct->getProduct();
  343.             $products[] = $product;
  344.             $total += $product->getPriceSellTTCA();
  345.         }
  346.         $session $request->getSession();
  347.         return $this->render('reservation/summary.html.twig', [
  348.             'salon' => $salon,
  349.             'famille' => $famille,
  350.             'products' => $products,
  351.             'total' => $total,
  352.             'rdv' => $rdv,
  353.             'email' => $session->get('email'),
  354.             'alreadyPaid' => $alreadyPaid
  355.         ]);
  356.     }
  357.     /**
  358.      * Page confirmation prepayment
  359.      * @Route("/confirmation/paiement/success", name="rdv_confirmation_payment")
  360.      */
  361.     public function confirmationPayment(
  362.         Request $request,
  363.         RDVRepository $rdvRepository
  364.     ): Response {
  365.         $linkId $request->query->get('id');
  366.         $rdv $rdvRepository->findRdvWithLinkId($linkId);
  367.         return $this->render('reservation/confirmation_payment.html.twig', [
  368.             'rdv' => $rdv,
  369.         ]);
  370.     }
  371.     /**
  372.      * @Route("/search/for/get-salons", name="get_salons")
  373.      */
  374.     public function getSalons(Request $requestSalonRepository $salonRepository): Response
  375.     {
  376.         $type $request->query->get('type');
  377.         $salon $request->query->get('salon');
  378.         $service $request->query->get('service');
  379.         $salons $salonRepository->findSalonsByTypeServiceSalonText($type$service$salon);
  380.         return $this->render('reservation/list_salons.html.twig', [
  381.             'salons' => $salons,
  382.         ]);
  383.     }
  384.     /**
  385.      * @Route("/search/for/get-salon-availability", name="get_salon_availability")
  386.      */
  387.     public function getSalonAvailability(
  388.         Request $request,
  389.         SessionSalonRepository $sessionSalonRepository,
  390.         SalonRepository $salonRepository,
  391.         RDVRepository $rdvRepository
  392.     ) {
  393.         $messageDates = [];
  394.         $isDateAvailable false;
  395.         $service str_replace('é''e'$request->query->get('service'));
  396.         $salon $salonRepository->find((int) $request->query->get('salonId'));
  397.         // if no date available, then give the future dates availables
  398.         $limit 5;
  399.         $datesAvailable $this->getAvailability(
  400.             $sessionSalonRepository,
  401.             $rdvRepository,
  402.             $service,
  403.             $salon,
  404.             $limit
  405.         );
  406.         // format array result
  407.         $tabDates = [];
  408.         if (!empty($datesAvailable)) {
  409.             foreach ($datesAvailable as $key => $dateAvailable) {
  410.                 $tabDates[$key] = $dateAvailable['minTime'];
  411.             }
  412.         }
  413.         if (count($tabDates) > 0) {
  414.             $messageDates $tabDates;
  415.             $isDateAvailable true;
  416.         }
  417.         return $this->json([
  418.             'template' => $this->render('reservation/dates_available.html.twig', [
  419.                 'isDateAvailable' => $isDateAvailable,
  420.                 'dates' => $messageDates
  421.             ])->getContent(),
  422.         ]);
  423.     }
  424.     /**
  425.      * @Route("/search/for/get-intervenant-date", name="get_intervenant_date")
  426.      */
  427.     public function getIntervenantByDateRdv(
  428.         Request $request,
  429.         SessionSalonRepository $sessionSalonRepository,
  430.         SalonRepository $salonRepository
  431.     ) {
  432.         $salon $salonRepository->find((int) $request->query->get('salonId'));
  433.         $date = new \DateTime($request->query->get('date'));
  434.         $sessionSalon $sessionSalonRepository->findSessionBySalonAndDate($salon$date);
  435.         $intervenant $sessionSalon[0]->getIntervenant();
  436.         return $this->json([
  437.             'intervenant' => $intervenant->getFullname(),
  438.         ]);
  439.     }
  440.     /**
  441.      * find if the given date is available
  442.      * @param string $dateStr
  443.      * @param RDVRepository $rdvRepository
  444.      * @param Salon $salon
  445.      *
  446.      * @return boolean
  447.      */
  448.     private function checkDateAvailability($dateStr$rdvRepository$salon)
  449.     {
  450.         $givenDate = new \DateTime($dateStr);
  451.         $now = new \DateTime('now');
  452.         $rdvDatesTaken $this->getRdvDatesTaken($rdvRepository$salon);
  453.         if ($givenDate <= $now) { // if the date is in the past
  454.             return false;
  455.         }
  456.         if (in_array($givenDate$rdvDatesTaken)) {
  457.             return false;
  458.         }
  459.         return true;
  460.     }
  461.     /**
  462.      * Get active RDV by salon and return dates
  463.      * @param RDVRepository $rdvRepository
  464.      * @param Salon $salon
  465.      *
  466.      * @return array
  467.      */
  468.     private function getRdvDatesTaken($rdvRepository$salon): array
  469.     {
  470.         // get active rdvs
  471.         $rdvs $rdvRepository->findForRdvWithSalonAndStatus($salon);
  472.         $rdvDatesTaken = [];
  473.         foreach ($rdvs as $rdv) {
  474.             $rdvDatesTaken[] = $rdv->getStart();
  475.         }
  476.         return $rdvDatesTaken;
  477.     }
  478.     /**
  479.      * Get dates available for a salon
  480.      * @param SessionSalonRepository $sessionSalonRepository
  481.      * @param RDVRepository $rdvRepository
  482.      * @param string $service
  483.      * @param Salon $salon
  484.      * @param int $limit
  485.      *
  486.      * @return array
  487.      */
  488.     private function getAvailability(
  489.         $sessionSalonRepository,
  490.         $rdvRepository,
  491.         $service,
  492.         $salon,
  493.         $limit null
  494.     ): array {
  495.         $typeSite $salon->getSite() ? $salon->getSite()->getType()  : null;
  496.         $isEhpad $typeSite === Site::TYPE_EHPAD true false;
  497.         $rdvDatesTaken $this->getRdvDatesTaken($rdvRepository$salon);
  498.         $sessionSalons $sessionSalonRepository->findSalonAvailability($salon$service''$limit);
  499.         $datesAvailable = [];
  500.         $lengthSession $isEhpad 'PT15M' 'PT30M';
  501.         // init opening/closing time
  502. //        $openingTimeStr = Salon::DEFAULT_OPENING_TIME;
  503. //        $closingTimeStr = Salon::DEFAULT_CLOSING_TIME;
  504. //
  505. //        // get salon times
  506. //        if ($salon->getOpeningTime() && $salon->getClosingTime()) {
  507. //            $openingTimeStr = $salon->getOpeningTime()->format('H:i:s');
  508. //            $closingTimeStr = $salon->getClosingTime()->format('H:i:s');
  509. //        }
  510.         foreach ($sessionSalons as $sessionSalon) {
  511.             // Get all session in a day
  512.             $timezone = new \DateTimeZone('Europe/Paris');
  513.             $period = new \DatePeriod(
  514.                 new \DateTime($sessionSalon->getStart()->format('d-m-Y H:i:s' ),$timezone),
  515.                 new \DateInterval($lengthSession),
  516.                 new \DateTime($sessionSalon->getEnd() ? $sessionSalon->getEnd()->format('d-m-Y H:i:s') : $sessionSalon->getStart()->format('d-m-Y 18:00:00' ),$timezone)
  517.             );
  518.             // save available spots
  519.             $rdvAvailableBySessionSalon = [];
  520.             $now = new \DateTime('now'$timezone);
  521.             foreach ($period as $p) {
  522.                 if ($p >= $now && !in_array($p$rdvDatesTaken)) {
  523.                     $rdvAvailableBySessionSalon[] = $p->format('H:i');
  524.                 }
  525.             }
  526.             $datesAvailable[$sessionSalon->getStart()->format('d-m-Y')]['minTime'] = $rdvAvailableBySessionSalon;
  527.         }
  528.         return $datesAvailable;
  529.     }
  530.     /**
  531.      * @Route("/search/for/get-additionnal-products", name="get_additionnal_products")
  532.      */
  533.     public function getAdditionnalProducts(Request $requestProductServiceRepository $productServiceRepository)
  534.     {
  535.         $productId $request->query->get('productId');
  536.         if ($productId !== '') {
  537.             $productServices $productServiceRepository->findBy(['product' => $productId]);
  538.         }
  539.         return $this->render('reservation/additionnal_services_popup.html.twig', [
  540.             'productServices' => $productServices ?? []
  541.         ]);
  542.     }
  543.     /**
  544.      * Return text if coiffure or esthétique
  545.      * @param string $name
  546.      *
  547.      * @return string
  548.      */
  549.     private function serviceName($name): string
  550.     {
  551.         if (strpos($name'coiffure') !== false) {
  552.             $text 'coiffure';
  553.         } else if (strpos($name'esthétique') !== false) {
  554.             $text 'esthétique';
  555.         } else {
  556.             $text '';
  557.         }
  558.         return $text;
  559.     }
  560.     /**
  561.      * @Route("/docs/privacy-policy/politique-de-confidentialite", name="privacy_policy")
  562.      */
  563.     public function privacyPolicy(): Response
  564.     {
  565.         return $this->render('reservation/privacy_policy.html.twig');
  566.     }
  567.     /**
  568.      * send mail confirmation to client
  569.      * @Route("/search/for/send-confirmation-rdv", name="send_confirmation_rdv")
  570.      */
  571.     public function sendConfirmationRdv(
  572.         Request $request,
  573.         MailService $mailService,
  574.         FamilleRepository $familleRepository,
  575.         RDVRepository $rdvRepository
  576.     ) {
  577.         $famille $familleRepository->findOneById((int)$request->query->get('familleId'));
  578.         $rdv $rdvRepository->findOneById((int)$request->query->get('rdvId'));
  579.         $typeService strpos(strtolower($famille->getName()), 'coiffure') !== false 'de coiffure' 'd’esthétique';
  580.         $mailService->sendConfirmationRdv(
  581.             $request->query->get('email'),
  582.             [
  583.                 'rdv' => $rdv,
  584.                 'client' => $rdv->getClient(),
  585.                 'typeService' => $typeService,
  586.             ]
  587.         );
  588.         return $this->json($rdv->getPaymentLink());
  589.     }
  590.     /**
  591.      * Prepare dates for calendar
  592.      * @param mixed $sessionSalonRepository
  593.      * @param mixed $rdvRepository
  594.      * @param mixed $service
  595.      * @param mixed $salon
  596.      *
  597.      * @return array
  598.      */
  599.     private function prepareDatesCalendar($sessionSalonRepository$rdvRepository$service$salon): array
  600.     {
  601.         // available dates for calendar picker
  602.         $availableDates $this->getAvailability($sessionSalonRepository$rdvRepository$service$salon);
  603.         $availableDatetimeFormatted = [];
  604.         $availableDatetimeList = [];
  605.         $datesToDisable = [];
  606.         // convert format date
  607.         foreach ($availableDates as $key => $availableDate) {
  608.             $formattedDate = new \DateTime($key);
  609.             $availableDatetimeFormatted[$formattedDate->format('d-m-Y')] = $availableDate;
  610.             $availableDatetimeList[] = $formattedDate->format('d-m-Y');
  611.         }
  612.         // get disabled dates
  613.         $now = new \DateTime('now');
  614.         $end = clone $now;
  615.         $period = new \DatePeriod(
  616.             $now,
  617.             new \DateInterval('P1D'),
  618.             $end->modify('+12 month')
  619.         );
  620.         foreach ($period as $date) {
  621.             if (!in_array($date->format('d-m-Y'), $availableDatetimeList)) {
  622.                 $datesToDisable[] = $date->format('d-m-Y');
  623.             }
  624.         }
  625.         return [
  626.             'availableDateTime' => json_encode($availableDatetimeFormatted),
  627.             'datesToDisable' => json_encode($datesToDisable),
  628.         ];
  629.     }
  630.     /**
  631.      * @Route("/docs/cgv/politique-de-confidentialite", name="general_terms_conditions")
  632.      */
  633.     public function generalTermsAndConditions(): Response
  634.     {
  635.         return $this->render('reservation/general_terms_conditions.html.twig');
  636.     }
  637. }