fix: refresh live room availability during create flow

This commit is contained in:
Björn Fromme committed 2026-07-14 11:25:23 +02:00
1 parent a73e8a593f
commit cdce7d57e0
26 files changed
+1976 -54

No files matched your search

+75 -8
View File
@@ -21,9 +21,11 @@ class BookingSessionManager
{
public const BOOKING_CREATE_KEY = 'booking_create';
public const BOOKING_CREATE_BASELINE_KEY = 'booking_create_baseline_snapshot';
public const BOOKING_CREATE_AVAILABILITY_REFRESHED_AT_KEY = 'booking_create_availability_refreshed_at';
public const BOOKING_EDIT_KEY = 'booking_edit';
public const RETURN_URL_KEY = 'booking_return_url';
public const DEFAULT_RETURN_URL = 'https://www.ep-reisen.de';
private const CREATE_AVAILABILITY_REFRESH_INTERVAL = 600;
public function __construct(
private readonly TravelDataProvider $travelDataService,
@@ -51,22 +53,32 @@ class BookingSessionManager
/**
* Gets or creates the baseline room selection snapshot for change detection.
*
* @return array<int, array{int, int}>
* @return array<int, array{int, int, float}>
*/
public function getOrCreateBaselineSnapshot(Request $request, BookingDto $bookingCreateDto): array
{
$baselineKey = self::BOOKING_CREATE_BASELINE_KEY;
if (!$request->getSession()->has($baselineKey) || $request->query->has('reset_baseline')) {
$baseline = $bookingCreateDto->createRoomSelectionSnapshot();
$request->getSession()->set($baselineKey, $baseline);
return $baseline;
return $this->saveBaselineSnapshot($request, $bookingCreateDto);
}
return $request->getSession()->get($baselineKey);
}
/**
* Stores the current room selection snapshot in the session.
*
* @return array<int, array{int, int, float}>
*/
public function saveBaselineSnapshot(Request $request, BookingDto $bookingCreateDto): array
{
$baseline = $bookingCreateDto->createRoomSelectionSnapshot();
$request->getSession()->set(self::BOOKING_CREATE_BASELINE_KEY, $baseline);
return $baseline;
}
/**
* Clears the baseline snapshot from the session.
*/
@@ -97,7 +109,12 @@ class BookingSessionManager
}
$bookingDto = $session->get($sessionKey);
$this->hydrate($bookingDto);
$shouldCheck = BookingDto::MODE_CREATE === $mode && $this->shouldRefreshCreateAvailability($request);
$hydrated = $this->hydrate($bookingDto, $shouldCheck);
if (BookingDto::MODE_CREATE === $mode && true === $shouldCheck && true === $hydrated) {
$this->markCreateAvailabilityRefreshed($request);
}
return $bookingDto;
}
@@ -111,6 +128,39 @@ class BookingSessionManager
$request->getSession()->remove($sessionKey);
}
public function refreshCreateAvailability(
Request $request,
BookingDto $bookingDto,
bool $forceRefresh = false,
): BookingAvailabilityRefreshResult {
$beforeSnapshot = $bookingDto->createRoomSelectionSnapshot();
$availabilityRefreshed = $this->travelDataService->enrichWithFreshAvailabilities(
$bookingDto->travel,
true,
$forceRefresh,
refreshRooms: true,
);
$roomSelectionQuantityReset = $bookingDto->syncRoomSelectionsWithAvailableRooms();
$afterSnapshot = $bookingDto->createRoomSelectionSnapshot();
if (true === $roomSelectionQuantityReset) {
$bookingDto->resetParticipantAssignments();
}
$this->saveBookingDto($request, $bookingDto, BookingDto::MODE_CREATE);
if (true === $forceRefresh && true === $availabilityRefreshed) {
$this->markCreateAvailabilityRefreshed($request);
}
return new BookingAvailabilityRefreshResult(
availabilityRefreshed: $availabilityRefreshed,
roomSelectionQuantityReset: $roomSelectionQuantityReset,
roomSelectionSnapshotChanged: $beforeSnapshot !== $afterSnapshot,
hasAvailableRooms: [] !== $bookingDto->travel->getAvailableRooms(),
);
}
/**
* Clears all booking-related session data except the return URL.
*/
@@ -119,6 +169,7 @@ class BookingSessionManager
$session = $request->getSession();
$session->remove(self::BOOKING_CREATE_KEY);
$session->remove(self::BOOKING_CREATE_BASELINE_KEY);
$session->remove(self::BOOKING_CREATE_AVAILABILITY_REFRESHED_AT_KEY);
}
/**
@@ -154,7 +205,20 @@ class BookingSessionManager
/**
* Restores the full Travel object after session deserialization.
*/
private function hydrate(BookingDto $bookingDto): void
public function markCreateAvailabilityRefreshed(Request $request): void
{
$request->getSession()->set(self::BOOKING_CREATE_AVAILABILITY_REFRESHED_AT_KEY, time());
}
private function shouldRefreshCreateAvailability(Request $request): bool
{
$lastRefreshedAt = (int) $request->getSession()->get(self::BOOKING_CREATE_AVAILABILITY_REFRESHED_AT_KEY, 0);
return 0 === $lastRefreshedAt
|| (time() - $lastRefreshedAt) >= self::CREATE_AVAILABILITY_REFRESH_INTERVAL;
}
private function hydrate(BookingDto $bookingDto, bool $forceRefresh = false): bool
{
$travel = $this->travelDataService->getTravelData(
$bookingDto->travel->id,
@@ -162,13 +226,16 @@ class BookingSessionManager
);
if (null === $travel) {
return;
return false;
}
$availabilityRefreshed = $this->travelDataService->enrichWithFreshAvailabilities($travel, true, $forceRefresh, refreshRooms: true);
$bookingDto->travel = $travel;
if (null !== $bookingDto->booking) {
$bookingDto->booking->travelData = $travel;
}
return $availabilityRefreshed;
}
}