fix: fetch fresh room prices from api to avoid calculation mismatch

This commit is contained in:
Björn Fromme
2026-03-16 12:02:28 +01:00
parent cef9be92f3
commit f28227384d
3 changed files with 67 additions and 1 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ Authorization: Bearer {{$auth.token("oauth2_api")}}
### API hotel availability remote ### API hotel availability remote
# @no-cookie-jar # @no-cookie-jar
GET {{base_url}}/api/travels/11603/152546/2026-01-03/availability GET {{base_url}}/api/travels/11606/152546/2026-01-24/availability
Accept: application/json Accept: application/json
Authorization: Bearer {{$auth.token("oauth2_api")}} Authorization: Bearer {{$auth.token("oauth2_api")}}
+4
View File
@@ -247,6 +247,10 @@ class BookingService
$this->travelDataService->patchAvailabilities($travelData, $availabilities); $this->travelDataService->patchAvailabilities($travelData, $availabilities);
} }
// Fetch and patch room prices from API to ensure consistency with booking validation
// This prevents price mismatch errors when XML export has stale prices
$this->travelDataService->patchRoomPricesFromApi($travelData);
// Get bookable rooms (Frei or Anfrage with available > 0) // Get bookable rooms (Frei or Anfrage with available > 0)
$availableRooms = $travelData->getAvailableRooms(); $availableRooms = $travelData->getAvailableRooms();
+62
View File
@@ -629,6 +629,68 @@ class TravelDataService
} }
} }
/**
* Fetches room prices from the API and patches them onto the travel object.
*
* This ensures room prices match between local calculation and API validation,
* preventing price mismatch errors during booking submission. The API call
* takes approximately 4 seconds but is only needed once at booking start.
*
* @param Travel $travel The travel object to update with fresh room prices
*/
public function patchRoomPricesFromApi(Travel $travel): void
{
if (null === $travel->dateTo || null === $travel->hotelId) {
$this->logger->warning('Cannot fetch room prices: missing dateTo or hotelId', [
'travelId' => $travel->id,
]);
return;
}
try {
$result = $this->apiClient->getHotelAvailability($travel->id, $travel->hotelId, $travel->dateTo);
if ($result instanceof Notification) {
$this->logger->warning('API returned notification for room availability', [
'travelId' => $travel->id,
'message' => $result->message,
]);
return;
}
$apiRooms = $result->getItems();
$patchedCount = 0;
foreach ($travel->rooms as $room) {
if (isset($apiRooms[$room->id]) && null !== $apiRooms[$room->id]->price) {
$oldPrice = $room->price;
$room->price = $apiRooms[$room->id]->price;
if ($oldPrice !== $room->price) {
$patchedCount++;
$this->logger->debug('Patched room price', [
'roomId' => $room->id,
'oldPrice' => $oldPrice,
'newPrice' => $room->price,
]);
}
}
}
$this->logger->info('Successfully patched room prices from API', [
'travelId' => $travel->id,
'patchedCount' => $patchedCount,
]);
} catch (ApiClientException $e) {
$this->logger->error('Failed to fetch room prices from API', [
'travelId' => $travel->id,
'error' => $e->getMessage(),
]);
}
}
/** /**
* Enrich travel data with additional information. * Enrich travel data with additional information.
* *