feat: always load fresh api data when starting to edit booking

This commit is contained in:
Björn Fromme
2026-03-16 12:02:28 +01:00
parent a23ff6d119
commit fba3becb06
5 changed files with 28 additions and 7 deletions
@@ -233,7 +233,8 @@ class BookingDataProcessor
$participant->transportationInbound = $travel->transportationServices[$participant->transportationInbound->id]; $participant->transportationInbound = $travel->transportationServices[$participant->transportationInbound->id];
} }
// Enrich pickup // Enrich pickup (only outbound - API limitation: pickups are only supported when
// outbound transportation is bus; inbound-only bus bookings cannot have pickups)
if (null !== $participant->pickup && isset($travel->pickupsOutbound[$participant->pickup->id])) { if (null !== $participant->pickup && isset($travel->pickupsOutbound[$participant->pickup->id])) {
$participant->pickup = $travel->pickupsOutbound[$participant->pickup->id]; $participant->pickup = $travel->pickupsOutbound[$participant->pickup->id];
} }
+2 -1
View File
@@ -136,7 +136,8 @@ class Booking
* Retrieves pickup service for a specific participant. * Retrieves pickup service for a specific participant.
* *
* Finds the pickup service assigned to the specified participant * Finds the pickup service assigned to the specified participant
* from the outbound pickup services. * from the outbound pickup services. The API only supports pickups
* when outbound transportation is bus.
* *
* @param int $participantIndex The participant index to search for * @param int $participantIndex The participant index to search for
* *
@@ -59,6 +59,22 @@ class IndexController extends AbstractController
) { ) {
} }
/**
* Entry point for editing a booking from the booking list.
*
* Clears any existing session data and API cache to ensure fresh data
* is loaded, then redirects to the main edit page.
*/
#[Route('/bookings/{id}/edit/start', name: 'app_booking_edit_start', requirements: ['id' => '\d+'])]
#[IsGranted('ROLE_USER')]
public function start(int $id, Request $request): Response
{
$this->bookingService->clearBookingDto($request, BookingDto::MODE_EDIT);
$this->dataLoader->invalidateBookingCache($id);
return $this->redirectToRoute('app_booking_edit', ['id' => $id]);
}
/** /**
* Display participant cards overview. * Display participant cards overview.
*/ */
+7 -4
View File
@@ -54,11 +54,14 @@ class BookingEditDataLoaderService
} }
/** /**
* Loads booking data from session or initializes from API on first load. * Loads booking data from session or initializes from API.
* *
* Validates that any cached session data matches the requested booking ID. * Uses session data if available and valid (same booking ID). This preserves
* If a different booking is in session, it is cleared and fresh data is loaded. * participant edits between form submissions within the same edit session.
* If a draft exists for this user and booking, it is automatically applied. *
* If no session data exists, loads fresh data from API. If a draft exists,
* it is automatically applied on top of the fresh API data to restore
* pending user edits.
* *
* @param Request $request The HTTP request * @param Request $request The HTTP request
* @param int $bookingId The booking ID to load * @param int $bookingId The booking ID to load
+1 -1
View File
@@ -73,7 +73,7 @@
</table> </table>
<div class="flex space-x-2"> <div class="flex space-x-2">
{% if booking.editable %} {% if booking.editable %}
<a href="{{ path('app_booking_edit', { 'id': booking.id }) }}" <a href="{{ path('app_booking_edit_start', { 'id': booking.id }) }}"
class="button button--primary button--small" class="button button--primary button--small"
title="Buchung bearbeiten"> title="Buchung bearbeiten">
<svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M92.69,216H48a8,8,0,0,1-8-8V163.31a8,8,0,0,1,2.34-5.65L165.66,34.34a8,8,0,0,1,11.31,0L221.66,79a8,8,0,0,1,0,11.31L98.34,213.66A8,8,0,0,1,92.69,216Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="136" y1="64" x2="192" y2="120" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="164" y1="92" x2="68" y2="188" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="95.49" y1="215.49" x2="40.51" y2="160.51" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg> <svg class="w-6 h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><path d="M92.69,216H48a8,8,0,0,1-8-8V163.31a8,8,0,0,1,2.34-5.65L165.66,34.34a8,8,0,0,1,11.31,0L221.66,79a8,8,0,0,1,0,11.31L98.34,213.66A8,8,0,0,1,92.69,216Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="136" y1="64" x2="192" y2="120" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="164" y1="92" x2="68" y2="188" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><line x1="95.49" y1="215.49" x2="40.51" y2="160.51" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>