fix: properly handle 'veg' services in booking edit flow

This commit is contained in:
Björn Fromme
2026-04-29 11:59:39 +02:00
parent 287c299c41
commit c0c8ad515c
9 changed files with 89 additions and 4 deletions
@@ -105,6 +105,9 @@ class BookingDataProcessor
$participantData->board = $booking $participantData->board = $booking
->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_BOARD); ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_BOARD);
$vegServices = $booking->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_VEG);
$participantData->veg = false === empty($vegServices) ? reset($vegServices) : null;
$participantData->rentals = $booking $participantData->rentals = $booking
->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_RENTALS); ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_RENTALS);
@@ -211,6 +214,11 @@ class BookingDataProcessor
} }
} }
// Enrich veg
if (null !== $participant->veg && isset($travel->additionalServices[$participant->veg->id])) {
$participant->veg = $travel->additionalServices[$participant->veg->id];
}
// Enrich rentals // Enrich rentals
foreach ($participant->rentals as $key => $rental) { foreach ($participant->rentals as $key => $rental) {
if (isset($travel->additionalServices[$rental->id])) { if (isset($travel->additionalServices[$rental->id])) {
@@ -171,8 +171,8 @@ class BookingPayloadBuilder
'@idzimmer' => $room->id, '@idzimmer' => $room->id,
'@kategorie' => $room->category, '@kategorie' => $room->category,
'@idverpflegung' => $room->boardId, '@idverpflegung' => $room->boardId,
'@anreise' => $room->dateFrom ? $room->dateFrom->format('d.m.Y') : null, '@anreise' => $room->dateFrom?->format('d.m.Y'),
'@abreise' => $room->dateTo ? $room->dateTo->format('d.m.Y') : null, '@abreise' => $room->dateTo?->format('d.m.Y'),
'@anzahl' => $room->totalCount, '@anzahl' => $room->totalCount,
'@zuordnung' => implode(',', array_map(fn ($index) => $index + 1, $uniqueMapping)), '@zuordnung' => implode(',', array_map(fn ($index) => $index + 1, $uniqueMapping)),
]; ];
@@ -131,6 +131,11 @@ class ParticipantServiceProcessor
...$participant->rentals, ...$participant->rentals,
]; ];
// Veg is encoded as an additional service in the edit/update payload.
if (null !== $participant->veg) {
$services[] = $participant->veg;
}
// Add ski pass if selected (single service, not an array) // Add ski pass if selected (single service, not an array)
if (null !== $participant->skiPass) { if (null !== $participant->skiPass) {
$services[] = $participant->skiPass; $services[] = $participant->skiPass;
+1
View File
@@ -96,6 +96,7 @@ class BookingChangeTracker
'skiPass' => $participant->skiPass?->id, 'skiPass' => $participant->skiPass?->id,
'courses' => $this->normalizeServiceArray($participant->courses), 'courses' => $this->normalizeServiceArray($participant->courses),
'board' => $this->normalizeServiceArray($participant->board), 'board' => $this->normalizeServiceArray($participant->board),
'veg' => $participant->veg?->id,
'rentals' => $this->normalizeServiceArray($participant->rentals), 'rentals' => $this->normalizeServiceArray($participant->rentals),
'rentalInsurance' => $participant->rentalInsurance?->id, 'rentalInsurance' => $participant->rentalInsurance?->id,
'additionalServices' => $this->normalizeServiceArray($participant->additionalServices), 'additionalServices' => $this->normalizeServiceArray($participant->additionalServices),
+8
View File
@@ -209,6 +209,14 @@ class BookingEditDraftMerger
$participant->board = $this->resolveServiceArray($data['board'], $travel->additionalServices); $participant->board = $this->resolveServiceArray($data['board'], $travel->additionalServices);
} }
// Veg (single service) - merge strategy: only apply if resolves to valid service
if (true === array_key_exists('veg', $data) && null !== $data['veg']) {
$resolved = $this->resolveService($data['veg'], $travel->additionalServices);
if (null !== $resolved) {
$participant->veg = $resolved;
}
}
// Rentals (array) - overwrite strategy: user can deselect all // Rentals (array) - overwrite strategy: user can deselect all
if (true === array_key_exists('rentals', $data) && true === is_array($data['rentals'])) { if (true === array_key_exists('rentals', $data) && true === is_array($data['rentals'])) {
$participant->rentals = $this->resolveServiceArray($data['rentals'], $travel->additionalServices); $participant->rentals = $this->resolveServiceArray($data['rentals'], $travel->additionalServices);
+5
View File
@@ -93,6 +93,11 @@ class BookingEditSubmitGuard
$changed = true; $changed = true;
} }
if (false === $this->isSameService($participant->veg, $baseline->veg)) {
$participant->veg = $baseline->veg;
$changed = true;
}
if (false === $this->isSameService($participant->skiPass, $baseline->skiPass)) { if (false === $this->isSameService($participant->skiPass, $baseline->skiPass)) {
$participant->skiPass = $baseline->skiPass; $participant->skiPass = $baseline->skiPass;
$changed = true; $changed = true;
@@ -109,6 +109,49 @@ class BookingDataProcessorTest extends TestCase
$this->assertEquals('1', $service['@zuordnung']); $this->assertEquals('1', $service['@zuordnung']);
} }
public function testVegServiceIsIncludedInUpdatePayload(): void
{
$formData = $this->createCompleteFormData();
$vegService = $this->createMockService(194672);
$formData->travel->additionalServices[194672] = $vegService;
$formData->participants[0]->veg = $vegService;
$result = $this->processor->createUpdateRequestPayload($formData);
$this->assertNotEmpty($result['zusatzleistungen']['zusatzleistung']);
$vegPayload = null;
foreach ($result['zusatzleistungen']['zusatzleistung'] as $service) {
if (194672 === $service['@idleistung']) {
$vegPayload = $service;
break;
}
}
$this->assertNotNull($vegPayload);
$this->assertSame(1, $vegPayload['@anzahl']);
$this->assertSame('1', $vegPayload['@zuordnung']);
}
public function testVegSelectionIsRestoredWhenHydratingBookingDto(): void
{
$booking = $this->createMockBooking();
$travel = $this->createMockTravel();
$vegService = $this->createMockService(194672);
$vegService->subType = 'VEG';
$vegService->mapping = [0];
$booking->additionalServices[194672] = $vegService;
$travel->additionalServices[194672] = $vegService;
$dto = $this->processor->createBookingDtoFromBooking($booking, $travel);
$this->assertNotNull($dto->participants[0]->veg);
$this->assertSame(194672, $dto->participants[0]->veg?->id);
}
public function testTransportationServicesProcessing(): void public function testTransportationServicesProcessing(): void
{ {
$formData = $this->createFormDataWithTransportation(); $formData = $this->createFormDataWithTransportation();
@@ -47,17 +47,23 @@ class BookingEditDraftManagerMutabilityTest extends TestCase
public function testDraftSkipsAdditionalServicesWhenImmutable(): void public function testDraftSkipsAdditionalServicesWhenImmutable(): void
{ {
$originalService = $this->createService(10, 'Original'); $originalService = $this->createService(10, 'Original');
$originalVeg = $this->createService(11, 'Original Veg');
$participant = new ParticipantDto(); $participant = new ParticipantDto();
$participant->additionalServices = [$originalService]; $participant->additionalServices = [$originalService];
$participant->courses = []; $participant->courses = [];
$participant->board = []; $participant->board = [];
$participant->veg = $originalVeg;
$participant->rentals = []; $participant->rentals = [];
$participant->skiPass = null; $participant->skiPass = null;
$participant->rentalInsurance = null; $participant->rentalInsurance = null;
$travel = $this->createTravel( $travel = $this->createTravel(
additionalServicesMutable: false, additionalServicesMutable: false,
additionalServices: [10 => $originalService, 99 => $this->createService(99, 'Draft Added')], additionalServices: [
10 => $originalService,
11 => $originalVeg,
99 => $this->createService(99, 'Draft Added'),
],
); );
$dto = $this->createBookingDto($travel, [$participant]); $dto = $this->createBookingDto($travel, [$participant]);
@@ -69,6 +75,7 @@ class BookingEditDraftManagerMutabilityTest extends TestCase
'additionalServices' => [99], 'additionalServices' => [99],
'courses' => [99], 'courses' => [99],
'board' => [99], 'board' => [99],
'veg' => 99,
'rentals' => [99], 'rentals' => [99],
'skiPass' => 99, 'skiPass' => 99,
'rentalInsurance' => 99, 'rentalInsurance' => 99,
@@ -83,6 +90,7 @@ class BookingEditDraftManagerMutabilityTest extends TestCase
$this->assertSame([$originalService], $participant->additionalServices); $this->assertSame([$originalService], $participant->additionalServices);
$this->assertSame([], $participant->courses); $this->assertSame([], $participant->courses);
$this->assertSame([], $participant->board); $this->assertSame([], $participant->board);
$this->assertSame($originalVeg, $participant->veg);
$this->assertSame([], $participant->rentals); $this->assertSame([], $participant->rentals);
$this->assertNull($participant->skiPass); $this->assertNull($participant->skiPass);
$this->assertNull($participant->rentalInsurance); $this->assertNull($participant->rentalInsurance);
@@ -91,16 +99,18 @@ class BookingEditDraftManagerMutabilityTest extends TestCase
public function testDraftAppliesAdditionalServicesWhenMutable(): void public function testDraftAppliesAdditionalServicesWhenMutable(): void
{ {
$originalService = $this->createService(10, 'Original'); $originalService = $this->createService(10, 'Original');
$originalVeg = $this->createService(11, 'Original Veg');
$draftService = $this->createService(99, 'Draft Added'); $draftService = $this->createService(99, 'Draft Added');
$participant = new ParticipantDto(); $participant = new ParticipantDto();
$participant->additionalServices = [$originalService]; $participant->additionalServices = [$originalService];
$participant->courses = []; $participant->courses = [];
$participant->veg = $originalVeg;
$participant->skiPass = null; $participant->skiPass = null;
$travel = $this->createTravel( $travel = $this->createTravel(
additionalServicesMutable: true, additionalServicesMutable: true,
additionalServices: [10 => $originalService, 99 => $draftService], additionalServices: [10 => $originalService, 11 => $originalVeg, 99 => $draftService],
); );
$dto = $this->createBookingDto($travel, [$participant]); $dto = $this->createBookingDto($travel, [$participant]);
@@ -111,6 +121,7 @@ class BookingEditDraftManagerMutabilityTest extends TestCase
'services' => [ 'services' => [
'additionalServices' => [99], 'additionalServices' => [99],
'courses' => [99], 'courses' => [99],
'veg' => 99,
'skiPass' => 99, 'skiPass' => 99,
], ],
], ],
@@ -124,6 +135,7 @@ class BookingEditDraftManagerMutabilityTest extends TestCase
$this->assertSame(99, $participant->additionalServices[0]->id); $this->assertSame(99, $participant->additionalServices[0]->id);
$this->assertCount(1, $participant->courses); $this->assertCount(1, $participant->courses);
$this->assertSame(99, $participant->courses[0]->id); $this->assertSame(99, $participant->courses[0]->id);
$this->assertSame($draftService, $participant->veg);
$this->assertInstanceOf(Service::class, $participant->skiPass); $this->assertInstanceOf(Service::class, $participant->skiPass);
$skiPass = $participant->skiPass; $skiPass = $participant->skiPass;
$this->assertNotNull($skiPass); $this->assertNotNull($skiPass);
@@ -32,6 +32,7 @@ class BookingEditSubmitGuardTest extends TestCase
$workingParticipant = new ParticipantDto(); $workingParticipant = new ParticipantDto();
$workingParticipant->index = 0; $workingParticipant->index = 0;
$workingParticipant->additionalServices = [$this->createService(99)]; $workingParticipant->additionalServices = [$this->createService(99)];
$workingParticipant->veg = $this->createService(88);
$workingParticipant->transportationOutbound = $this->createService(88); $workingParticipant->transportationOutbound = $this->createService(88);
$workingParticipant->pickup = $this->createPickup(77); $workingParticipant->pickup = $this->createPickup(77);
@@ -41,6 +42,7 @@ class BookingEditSubmitGuardTest extends TestCase
$baselineParticipant = new ParticipantDto(); $baselineParticipant = new ParticipantDto();
$baselineParticipant->index = 0; $baselineParticipant->index = 0;
$baselineParticipant->additionalServices = [$this->createService(10)]; $baselineParticipant->additionalServices = [$this->createService(10)];
$baselineParticipant->veg = $this->createService(11);
$baselineParticipant->transportationOutbound = $this->createService(20); $baselineParticipant->transportationOutbound = $this->createService(20);
$baselineParticipant->pickup = $this->createPickup(30); $baselineParticipant->pickup = $this->createPickup(30);
@@ -58,6 +60,7 @@ class BookingEditSubmitGuardTest extends TestCase
$this->assertTrue($changed); $this->assertTrue($changed);
$this->assertSame([10], array_map(static fn (Service $s) => $s->id, $workingParticipant->additionalServices)); $this->assertSame([10], array_map(static fn (Service $s) => $s->id, $workingParticipant->additionalServices));
$this->assertSame(11, $workingParticipant->veg?->id);
$this->assertSame(20, $workingParticipant->transportationOutbound?->id); $this->assertSame(20, $workingParticipant->transportationOutbound?->id);
$this->assertSame(30, $workingParticipant->pickup?->id); $this->assertSame(30, $workingParticipant->pickup?->id);
} }