src/Controller/ReservationController.php line 59

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Payment\CarteBancaire;
  4. use App\Entity\Payment\CarteCadeauPayment;
  5. use App\Entity\Payment\Cash;
  6. use App\Entity\Payment\Cheque;
  7. use App\Entity\Payment\EmptyPayment;
  8. use App\Entity\Payment\Offert;
  9. use App\Entity\Privatisation;
  10. use App\Entity\Reservation;
  11. use App\Entity\Service;
  12. use App\Entity\ServiceResa;
  13. use App\Entity\Token;
  14. use App\Entity\WaitlistEntry;
  15. use App\Repository\WaitlistEntryRepository;
  16. use App\Form\Payment\CarteBancaireType;
  17. use App\Form\Payment\CashType;
  18. use App\Form\Payment\ChequeType;
  19. use App\Form\Payment\OffertType;
  20. use App\Form\PrivatisationType;
  21. use App\Form\ReservationAdminType;
  22. use App\Form\TokenReservationType;
  23. use App\Repository\ExtraRepository;
  24. use App\Service\CarteCadeauService;
  25. use App\Service\CodeService;
  26. use App\Service\ExtraReservationService;
  27. use App\Service\PaymentService;
  28. use App\Service\PayplugService;
  29. use App\Service\PrivatisationService;
  30. use App\Service\ReservationService;
  31. use App\Service\TokenService;
  32. use DateTime;
  33. use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  34. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  35. use PhpOffice\PhpSpreadsheet\Style\Fill;
  36. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  37. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  38. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  39. use Symfony\Component\HttpFoundation\JsonResponse;
  40. use Symfony\Component\HttpFoundation\Request;
  41. use Symfony\Component\HttpFoundation\Response;
  42. use Symfony\Component\HttpFoundation\StreamedResponse;
  43. use Symfony\Component\Routing\Annotation\Route;
  44. use Symfony\Contracts\Translation\TranslatorInterface;
  45. class ReservationController extends AbstractController
  46. {
  47.     public function __construct(private ReservationService      $reservationService,
  48.                                 private ExtraReservationService $extraReservationService,
  49.                                 private TokenService $tokenService,
  50.                                 private TranslatorInterface $translator,
  51.                                 private CarteCadeauService $carteCadeauService,
  52.     )
  53.     {}
  54.     #[Route(path'/reservation'name'reservation_tunnel')]
  55.     public function tunnel(Request $requestWaitlistEntryRepository $waitlistEntryRepository)
  56.     {
  57.         $token = new Token();
  58.         $this->extraReservationService->generateExtraReservations($token);
  59.         $form $this->createForm(TokenReservationType::class, $token);
  60.         $waitlistData null;
  61.         $waitlistToken $request->query->get('waitlist');
  62.         if ($waitlistToken) {
  63.             $waitlistEntry $waitlistEntryRepository->findOneByToken($waitlistToken);
  64.             if ($waitlistEntry && !$waitlistEntry->isExpired()) {
  65.                 $waitlistData = [
  66.                     'solo' => $waitlistEntry->getSolo(),
  67.                     'duo' => $waitlistEntry->getDuo(),
  68.                     'offer' => $waitlistEntry->getOffer(),
  69.                     'desiredDate' => $waitlistEntry->getDesiredDate()->format('Y-m-d'),
  70.                 ];
  71.             }
  72.         }
  73.         return $this->renderForm('reservation/tunnel/tunnel.html.twig', [
  74.             'token' => $token,
  75.             'form' => $form,
  76.             'paymentUrl' => $this->generateUrl('reservation_payment', ['tokenValue' => $token->getValue()]),
  77.             'waitlistData' => $waitlistData,
  78.         ]);
  79.     }
  80.     #[Route(path'/reservation/modifier/{tokenValue}'name'reservation_update')]
  81.     public function updateReservation(ReservationService $reservationServiceTokenService $tokenServiceExtraReservationService $extraReservationServicestring $tokenValue)
  82.     {
  83.         $token $tokenService->findOneByValue($tokenValue);
  84.         if (!$token) {
  85.             $this->addFlash(
  86.                 'error',
  87.                 'Réservation non trouvée'
  88.             );
  89.             return $this->redirectToRoute('reservation_tunnel');
  90.         }
  91.         $reservation $token->getReservation() ?? $this->reservationService->findOneByToken($token);
  92.         // Si la réservation est dans moins de 48 heures, on retourne une erreur
  93.         if ($reservation->getDate() < (new \DateTime())->modify('+48 hours')) {
  94.             $this->addFlash(
  95.                 'error',
  96.                 'Vous ne pouvez pas modifier une réservation moins de 48h avant la date de celle-ci'
  97.             );
  98.             return $this->redirectToRoute('reservation_tunnel');
  99.         }
  100.         // Vérifier si le client a déjà modifié la réservation 3 fois
  101.         if (!$reservation->canClientEdit()) {
  102.             $this->addFlash(
  103.                 'error',
  104.                 'Vous avez atteint le nombre maximum de modifications autorisées pour cette réservation'
  105.             );
  106.             return $this->redirectToRoute('reservation_tunnel');
  107.         }
  108.         foreach ($reservation->getUsedCarteCadeaux() as $code) {
  109.             if ($code->isExpired()) {
  110.                 $this->addFlash(
  111.                     'error',
  112.                     'Vous ne pouvez pas modifier une réservation dont la carte cadeau utilisée est périmée'
  113.                 );
  114.                 return $this->redirectToRoute('reservation_tunnel');
  115.             }
  116.         }
  117.         $newToken = new Token;
  118.         $tokenService->copyReservationToToken($reservation$newToken);
  119.         $extraReservationService->generateExtraReservations($newTokenfalse);
  120.         $formReservation $this->createForm(TokenReservationType::class, $newToken);
  121.         $priceAlreadyPaid $reservationService->computePrice($reservation);
  122.         return $this->renderForm('reservation/tunnel/tunnel.html.twig', [
  123.             'edit' => true,
  124.             'token' => $token,
  125.             'form' => $formReservation,
  126.             'priceOffered' => $priceAlreadyPaid,
  127.             'paymentUrl' => $this->generateUrl('reservation_payment', ['tokenValue' => $token->getValue()]),
  128.             'reservationId' => $reservation->getId(),
  129.         ]);
  130.     }
  131.     #[Route(path'/reservation/payment/{tokenValue}'name'reservation_payment')]
  132.     public function createPayment(Request $requestReservationService $reservationServiceTokenService $tokenServiceExtraReservationService $extraReservationServicePayplugService $payplugServicePaymentService $paymentServicestring $tokenValue null)
  133.     {
  134.         $token = new Token;
  135.         $extraReservationService->generateExtraReservations($token);
  136.         $formReservation $this->createForm(TokenReservationType::class, $token);
  137.         $formReservation->handleRequest($request);
  138.         $originalToken $tokenService->findOneByValue($tokenValue);
  139.         $reservation $reservationService->findOneByToken($originalToken);
  140.         if ( $reservation && !$reservationService->isValidSlot($reservation) ) {
  141.             return new JsonResponse([
  142.                 'action' => 'error',
  143.                 'message' => "Le créneau demandé n'est pas disponible"
  144.             ]);
  145.         }
  146.         if ( !$reservation && !$tokenService->isValidReservation($token)) {
  147.             return new JsonResponse([
  148.                 'action' => 'error',
  149.                 'message' => "Le créneau demandé n'est pas disponible"
  150.             ]);
  151.         }
  152.         $tokenService->save($token);
  153.         if ($originalToken) {
  154.             $reservation $reservationService->findOneByToken($originalToken);
  155.             $token->setReservation($reservation);
  156.             if($paymentService->hasToPayTheDifference($reservation$token)) {
  157.                 $payment $payplugService->generatePayementWithUpdateReservation($token$reservation);
  158.             } else {
  159.                 $reservationService->copyTokenToReservation($token$reservation);
  160.                 $reservationService->associateBains($reservation$reservation->getSolo() + $reservation->getDuo());
  161.                 $reservationService->save($reservation);
  162.                 $payment = new EmptyPayment;
  163.                 $payment->setDatePayment(new DateTime());
  164.                 $payment->setToken($token);
  165.                 $tokenService->save($token);
  166.                 $paymentService->save($payment);
  167.                 return new JsonResponse([
  168.                     'action' => 'redirect',
  169.                     'url' => $this->generateUrl('reservation_confirmed_paiement', ['payment' => $payment->getId()])
  170.                 ]);
  171.             }
  172.         } else {
  173.             $payment $payplugService->generatePayment($token'reservation');
  174.         }
  175.         $token->setPaymentid($payment->id);
  176.         $tokenService->save($token);
  177.         return new JsonResponse([
  178.             'action' => 'payment',
  179.             'url' => $payment->hosted_payment->payment_url
  180.         ]);
  181.     }
  182.     #[Route(path'/reservation/carte-cadeau'name'reservation_carte_cadeau_tunnel')]
  183.     public function tunnelCarteCadeau(Request $requestTokenService $tokenServiceCodeService $codeServiceExtraReservationService $extraReservationService): Response
  184.     {
  185.         $codeValue  $request->query->get('code') ?? $request->get('code');
  186.         if (!$codeValue) {
  187.             return $this->render('reservation/tunnel/ask-code.html.twig');
  188.         }
  189.         $code       $codeService->findOneByValue($codeValue);
  190.         if (!$code) {
  191.             return $this->render('reservation/tunnel/ask-code.html.twig', [
  192.                 "error" => $codeValue "Ce code n'existe pas !" false
  193.             ]);
  194.         }
  195.         $token $code->getToken();
  196.         if (!$this->tokenService->isAlreadyPaid($token)) {
  197.             return $this->render('reservation/tunnel/ask-code.html.twig', [
  198.                 "error" => "Cette carte cadeau n'a pas complètement été réglée !"
  199.             ]);
  200.         }
  201.         if($code->getUsed()) {
  202.             return $this->render('reservation/tunnel/ask-code.html.twig', [
  203.                 "error" => "Ce code a déjà été utilisé !"
  204.             ]);
  205.         }
  206.         if($code->isExpired()) {
  207.             return $this->redirectToRoute('carte_cadeau_extend_validity', ['id' => $code->getToken()->getId()]);
  208.         }
  209.         $services_formated = [];
  210.         foreach($token->getExtraReservations() as $oldExtraReservation) {
  211.             foreach($oldExtraReservation->getOptionQuantityReservations() as $optionQuantityReservation) {
  212.                 if($optionQuantityReservation->getQuantity()) {
  213.                     $services_formated[] = [
  214.                         "name" => $optionQuantityReservation->getOptionQuantity()->getExtra()->getLabel().' '.$optionQuantityReservation->getOptionQuantity()->getLabel(),
  215.                         "quantity" => $optionQuantityReservation->getQuantity(),
  216.                     ];
  217.                 }
  218.             }
  219.             foreach($oldExtraReservation->getOptionSelectReservations() as $optionSelectReservation) {
  220.                 $services_formated[] = [
  221.                     "name" => $optionSelectReservation->getOptionSelect()->getLabel(),
  222.                     "quantity" => $optionSelectReservation->getOptionSelectItem()->getLabel(),
  223.                 ];
  224.             }
  225.         }
  226.         foreach($token->getCustomExtras() as $customExtra) {
  227.             $services_formated[] = [
  228.                 "name" => $customExtra->getLabel() . ' (' . ($customExtra->getPrice() / 100) . '€)',
  229.                 "quantity" => $customExtra->getQuantity(),
  230.             ];
  231.         }
  232.         $price $tokenService->computeRedemptionValue($token);
  233.         $extraReservationService->generateExtraReservations($token);
  234.         $token->setContact(null);
  235.         $formToken $this->createForm(TokenReservationType::class, $token);
  236.         return $this->render('reservation/tunnel/tunnel.html.twig', [
  237.             'token' => $token,
  238.             'code' => $code->getValue(),
  239.             'form' => $formToken->createView(),
  240.             'priceOffered' => $price,
  241.             'services' => $services_formated,
  242.             'paymentUrl' => $this->generateUrl('reservation_carte_cadeau_payment'),
  243.         ]);
  244.     }
  245.     #[Route(path'/reservation/carte-cadeau/payment'name'reservation_carte_cadeau_payment')]
  246.     public function createCarteCadeauPayment(Request $requestTokenService $tokenServiceReservationService $reservationServicePayplugService $payplugServiceCodeService $codeService)
  247.     {
  248.         $token = new Token;
  249.         $this->extraReservationService->generateExtraReservations($token);
  250.         $formReservation $this->createForm(TokenReservationType::class, $token);
  251.         $formReservation->handleRequest($request);
  252.         $code $codeService->findOneByValue($request->request->get('code'));
  253.         if($code->getUsed()) {
  254.             return new JsonResponse([
  255.                 'action' => 'error',
  256.                 'message' => 'Code déjà utilisé'
  257.                 ]);
  258.         }
  259.         $tokenCarteCadeau $tokenService->findOneByCodePromo($code);
  260.         $token->setCodePromo($code);
  261.         $price $tokenService->computePrice($token);
  262.         $priceOffered $tokenService->computeRedemptionValue($tokenCarteCadeau);
  263.         if($price $priceOffered) {
  264.             $payment $payplugService->generatePaymentWithCarteCadeau($token$tokenCarteCadeau);
  265.             $token->setPaymentid($payment->id);
  266.             return new JsonResponse([
  267.                 'action' => 'payment',
  268.                 'url' => $payment->hosted_payment->payment_url
  269.             ]);
  270.         }
  271.         $reservation = new Reservation;
  272.         $reservationService->copyTokenToReservation($token$reservation);
  273.         $reservationService->associateBains($reservation$reservation->getSolo() + $reservation->getDuo());
  274.         $reservation->setToken($token->getValue());
  275.         $reservation->addToken($token);
  276.         $reservation->setResteAPayer($reservationService->computePrice($reservation));
  277.         $firstTokenCodePromo $tokenService->findOneByCodePromo($code->getValue());
  278.         if ( !$firstTokenCodePromo ) {
  279.             $this->addFlash('error''Carte cadeau invalide');
  280.             return $this->redirectToRoute('reservation_tunnel');
  281.         }
  282.         $paymentCarteCadeau = new CarteCadeauPayment();
  283.         $paymentCarteCadeau->setDatePayment(new \DateTime());
  284.         $paymentCarteCadeau->setReservation($reservation);
  285.         $paymentCarteCadeau->setCartecadeau($firstTokenCodePromo->getCodePromo());
  286.         $paymentCarteCadeau->setAmount($tokenService->computeRedemptionValue($firstTokenCodePromo));
  287.         $code->setUsed(true);
  288.         if ( !$reservationService->isValidSlot($reservation) ) {
  289.             return new JsonResponse([
  290.                 'action' => 'error',
  291.                 'message' => "Le créneau demandé n'est plus disponible"
  292.             ]);
  293.         }
  294.         $reservationService->addPayment($reservation$paymentCarteCadeau$tokenService);
  295.         $reservationService->confirm($reservation);
  296.         $reservationService->save($reservation);
  297.         $reservationService->sendNotificationToClient($reservation);
  298.         return new JsonResponse([
  299.             'action' => 'redirect',
  300.             'url' => $this->generateUrl('reservation_carte_cadeau_confirmed', ['reservation' => $reservation->getId()])
  301.         ]);
  302.     }
  303.     #[Route(path'/reservation/carte-cadeau/confirmed/{reservation}'name'reservation_carte_cadeau_confirmed')]
  304.     public function confirmedReservation(Reservation $reservation)
  305.     {
  306.         if ($reservation->getConfirmed()) {
  307.             return $this->render('reservation/confirmation.html.twig', [
  308.                 'reservation' => $reservation,
  309.             ]);
  310.         } else {
  311.             return $this->render('reservation/confirmation.html.twig', [
  312.                 'reservation' => $reservation,
  313.                 'message' => "Le paiement n'a pas été validé, veuillez réessayer avec un autre moyen de paiement."
  314.             ]);
  315.         }
  316.     }
  317.     #[Route(path'/reservation/invalidDays'name'reservation_invalid_days')]
  318.     public function invalidDays(Request $requestReservationService $reservationService)
  319.     {
  320.         $baths $request->request->get('baths');
  321.         $duration $request->request->get('duration');
  322.         $participants $request->request->get('participants');
  323.         $entityType $request->request->get('entityType');
  324.         $entityId $request->request->get('entityId');
  325.         $originalTime $request->request->get('originalTime');
  326.         $originalDate $request->request->get('originalDate');
  327.         $invalidSlots $reservationService->getInvalidDays(
  328.             $baths,
  329.             $duration,
  330.             $participants,
  331.             $entityType,
  332.             $entityId,
  333.             $originalTime,
  334.             $originalDate
  335.         );
  336.         return new JsonResponse($invalidSlots);
  337.     }
  338.     #[Route(path'/reservation/validSlot'name'reservation_valid_slots')]
  339.     public function validSlotByDay(Request $requestReservationService $reservationService)
  340.     {
  341.         $baths $request->request->get('baths');
  342.         $participants $request->request->get('participants');
  343.         $duration $request->request->get('duration');
  344.         $date $request->request->get('date');
  345.         $entityType $request->request->get('entityType');
  346.         $entityId $request->request->get('entityId');
  347.         $originalTime $request->request->get('originalTime');
  348.         $originalDate $request->request->get('originalDate');
  349.         $validSlots $reservationService->getValidSlotByDay(
  350.             $baths,
  351.             $duration,
  352.             new DateTime($date),
  353.             $participants,
  354.             $entityType,
  355.             $entityId,
  356.             $originalTime,
  357.             $originalDate
  358.         );
  359.         $format = [];
  360.         foreach ($validSlots as $slot) {
  361.             $format[] = [
  362.                 "start" => $slot,
  363.                 "end" => $slot,
  364.             ];
  365.         }
  366.         return new JsonResponse($format);
  367.     }
  368.     #[Route(path'/reservation/waitlist'name'reservation_waitlist'methods: ['POST'])]
  369.     public function waitlistRegister(Request $requestWaitlistEntryRepository $waitlistEntryRepository): JsonResponse
  370.     {
  371.         $email trim($request->request->get('email'''));
  372.         $firstName trim($request->request->get('firstName'''));
  373.         $lastName trim($request->request->get('lastName'''));
  374.         $phone trim($request->request->get('phone'''));
  375.         $comment trim($request->request->get('comment'''));
  376.         $desiredDate $request->request->get('desiredDate''');
  377.         $solo = (int) $request->request->get('solo'0);
  378.         $duo = (int) $request->request->get('duo'0);
  379.         $offer $request->request->get('offer''60');
  380.         $isCarteCadeau $request->request->get('isCarteCadeau''0') === '1';
  381.         if (!$email || !$firstName || !$lastName || !$desiredDate) {
  382.             return new JsonResponse(['success' => false'message' => 'Champs requis manquants'], 400);
  383.         }
  384.         if (!filter_var($emailFILTER_VALIDATE_EMAIL)) {
  385.             return new JsonResponse(['success' => false'message' => 'Email invalide'], 400);
  386.         }
  387.         if (($solo $duo) < || ($solo $duo) > 4) {
  388.             return new JsonResponse(['success' => false'message' => 'Nombre de bains invalide'], 400);
  389.         }
  390.         if (!in_array($offer, ['60''90'], true)) {
  391.             return new JsonResponse(['success' => false'message' => 'Offre invalide'], 400);
  392.         }
  393.         $date \DateTime::createFromFormat('Y-m-d'$desiredDate);
  394.         if (!$date) {
  395.             return new JsonResponse(['success' => false'message' => 'Format de date invalide'], 400);
  396.         }
  397.         if ($date < new \DateTime('today')) {
  398.             return new JsonResponse(['success' => false'message' => 'La date doit être dans le futur'], 400);
  399.         }
  400.         $existing $waitlistEntryRepository->findOneBy([
  401.             'email' => $email,
  402.             'desiredDate' => $date,
  403.             'expired' => false,
  404.         ]);
  405.         if ($existing) {
  406.             return new JsonResponse([
  407.                 'success' => true,
  408.                 'message' => 'Vous êtes déjà inscrit(e) pour cette date. Nous vous préviendrons si un créneau se libère.'
  409.             ]);
  410.         }
  411.         $entry = new WaitlistEntry();
  412.         $entry->setEmail($email);
  413.         $entry->setFirstName($firstName);
  414.         $entry->setLastName($lastName);
  415.         $entry->setDesiredDate($date);
  416.         $entry->setSolo($solo);
  417.         $entry->setDuo($duo);
  418.         $entry->setOffer($offer);
  419.         $entry->setIsCarteCadeau($isCarteCadeau);
  420.         if ($phone) {
  421.             $entry->setPhone($phone);
  422.         }
  423.         if ($comment) {
  424.             $entry->setComment($comment);
  425.         }
  426.         $waitlistEntryRepository->save($entrytrue);
  427.         return new JsonResponse([
  428.             'success' => true,
  429.             'message' => 'C\'est noté ! Nous vous préviendrons par email si un créneau se libère le ' $entry->getDesiredDateFormatted() . '.'
  430.         ]);
  431.     }
  432. }