resolveDto($request, false); if ($dto instanceof Response) { return $dto; } $accommodation = $this->loadAccommodationOrFail($dto); $services = $this->bookingService->loadAvailableServices($dto, $accommodation); $ctx = new AccommodationBookingContext( accommodation: $accommodation, hotelCmsData: $this->bookingService->loadHotelCmsData($accommodation), boardServices: $services['boardServices'], additionalServices: $services['additionalServices'], priceBreakdown: $dto->priceBreakdown ?: null, ); $form = $this->createForm(AccommodationStep3Type::class, $dto); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $submitBookingClicked = false; // booking or inquiry status depends on clicked button if (true === $form->has('submitBooking')) { $submitBookingButton = $form->get('submitBooking'); $submitBookingClicked = $submitBookingButton instanceof ClickableInterface && true === $submitBookingButton->isClicked(); } // Booking is only offered via the confirmation modal; a forced-inquiry DTO // can never actually reach this branch since submitBooking is disabled for it. if (true === $submitBookingClicked && false === $dto->isInquiry) { $dto->forceInquiry = false; $this->sessionManager->save($request, $dto); $confirmationForm = $this->createForm(AccommodationStep3ConfirmationType::class, $dto); return $this->render('groups/booking/step_3.html.twig', [ 'dto' => $dto, 'ctx' => $ctx, 'form' => $form, 'confirmationForm' => $confirmationForm, ]); } $dto->forceInquiry = true; $this->persistBooking($request, $dto, $accommodation, $services); return $this->redirectToRoute('app_groups_booking_success'); } return $this->render('groups/booking/step_3.html.twig', [ 'dto' => $dto, 'ctx' => $ctx, 'form' => $form, ]); } #[Route('/groups/booking/step-3/confirm', name: 'app_groups_booking_step_3_confirm', methods: ['POST'])] public function confirm(Request $request): Response { $dto = $this->resolveDto($request, true); if ($dto instanceof Response) { return $dto; } $accommodation = $this->loadAccommodationOrFail($dto); $confirmationForm = $this->createForm(AccommodationStep3ConfirmationType::class, $dto); $confirmationForm->handleRequest($request); if ($confirmationForm->isSubmitted() && $confirmationForm->isValid() && false === $dto->isInquiry) { $services = $this->bookingService->loadAvailableServices($dto, $accommodation); $this->persistBooking($request, $dto, $accommodation, $services); return $this->htmxRedirect($request, $this->generateUrl('app_groups_booking_success')); } return $this->render('groups/booking/_step3_confirmation_modal.html.twig', [ 'confirmationForm' => $confirmationForm, ]); } /** * Loads the session DTO and checks step access, returning an early * response (session failure or step-access redirect) if either fails. */ private function resolveDto(Request $request, bool $htmx): AccommodationBookingDto|Response { try { $dto = $this->sessionManager->getOrFail($request); } catch (AccommodationSessionNotFoundException $e) { return $this->createFailureResponse($e, $htmx); } if ($redirect = $this->validateStepAccess($dto, 3)) { return $redirect; } return $dto; } private function loadAccommodationOrFail(AccommodationBookingDto $dto): Accommodation { $accommodation = $this->bookingService->loadAccommodation($dto->accommodationId); if (null === $accommodation) { throw $this->createNotFoundException(); } return $accommodation; } /** * @param array{boardServices: array, additionalServices: array} $services */ private function persistBooking(Request $request, AccommodationBookingDto $dto, Accommodation $accommodation, array $services): void { $prices = $this->bookingService->loadPrices($dto, $accommodation); $booking = $this->bookingService->persist($dto, $accommodation, $prices, $services); $this->bookingService->issueAccessLinkForDirectBooking($booking); $this->bookingService->sendNotificationEmail($booking, $dto->priceBreakdown); $this->bookingService->sendCustomerConfirmationEmail($booking); $this->addFlash('groups_booking_result', $booking->isInquiry() ? 'inquiry' : 'booking'); $this->sessionManager->clear($request); } }