getOrCreateBookingCreateDto($this->bookingService, $request); if ($result instanceof Response) { return $result; } $bookingCreateDto = $result; // Validate step access if ($redirect = $this->validateStepAccess($bookingCreateDto, 3)) { return $redirect; } $form = $this->createForm(BookingCreateStep3Type::class, $bookingCreateDto, [ 'attr' => [ 'hx-post' => $this->generateUrl('app_booking_create_step_3'), 'hx-target' => '#form-wrapper', 'hx-select' => '#form-wrapper', 'hx-swap' => 'outerHTML', ], ]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { try { // Validate booking data with API (inquiry) $inquiryResponse = $this->apiClient->createBookingInquiry($bookingCreateDto); if ($inquiryResponse instanceof Notification) { $this->logger->error('Booking inquiry failed', [ 'message' => $inquiryResponse->message, ]); $this->addFlash('error', 'Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.'); return $this->render('booking/create_step_3.html.twig', [ 'bookingCreateDto' => $bookingCreateDto, 'form' => $form->createView(), ...$this->getSummaryVariables($bookingCreateDto), ]); } if (false === $inquiryResponse->isInquiryValid()) { $this->logger->error('Booking inquiry validation failed', [ 'status' => $inquiryResponse->status, ]); $this->addFlash('error', 'Buchung konnte nicht validiert werden.'); return $this->render('booking/create_step_3.html.twig', [ 'bookingCreateDto' => $bookingCreateDto, 'form' => $form->createView(), ...$this->getSummaryVariables($bookingCreateDto), ]); } // Validate price match (exact comparison) $apiTotal = $inquiryResponse->totalPrice ?? 0.0; $calculatedTotal = $this->priceCalculator->calculateGrandTotal($bookingCreateDto); if ($apiTotal !== $calculatedTotal) { $this->logger->error('Price mismatch detected - payload incomplete', [ 'apiTotal' => $apiTotal, 'calculatedTotal' => $calculatedTotal, 'difference' => abs($apiTotal - $calculatedTotal), ]); $this->addFlash('error', 'Ein technischer Fehler ist aufgetreten.'); return $this->render('booking/create_step_3.html.twig', [ 'bookingCreateDto' => $bookingCreateDto, 'form' => $form->createView(), ...$this->getSummaryVariables($bookingCreateDto), ]); } // Validation successful - proceed to confirmation step $bookingCreateDto->currentStep = 4; $this->bookingService->saveBookingCreateDto($request, $bookingCreateDto); return $this->hxRedirect($request, $this->generateUrl('app_booking_create_step_4')); } catch (\Exception $e) { $this->logger->error('Booking inquiry exception', [ 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); $this->addFlash('error', 'Ein technischer Fehler ist aufgetreten.'); return $this->render('booking/create_step_3.html.twig', [ 'bookingCreateDto' => $bookingCreateDto, 'form' => $form->createView(), ...$this->getSummaryVariables($bookingCreateDto), ]); } } return $this->render('booking/create_step_3.html.twig', [ 'bookingCreateDto' => $bookingCreateDto, 'form' => $form->createView(), ...$this->getSummaryVariables($bookingCreateDto), ]); } /** * Handles HTMX refresh when payment method changes. */ #[Route('/bookings/create/payment/refresh', name: 'app_booking_create_step_3_refresh')] public function refresh(Request $request): Response { $result = $this->getOrCreateBookingCreateDto($this->bookingService, $request); if ($result instanceof Response) { return $result; } $bookingCreateDto = $result; $form = $this->createForm(BookingCreateStep3Type::class, $bookingCreateDto, [ 'validation_groups' => false, ]); $form->handleRequest($request); $this->bookingService->saveBookingCreateDto($request, $bookingCreateDto); return $this->render('booking/create_step_3.html.twig', [ 'bookingCreateDto' => $bookingCreateDto, 'form' => $form->createView(), ...$this->getSummaryVariables($bookingCreateDto), ]); } }