fix: pass BusPro room assignments through on edit

This commit is contained in:
fromme committed 2026-11-09 18:00:47 +01:00
1 parent 897a1ac7f9
commit d50995a21c
7 files changed
+163 -45

No files matched your search

@@ -342,6 +342,66 @@ class BookingDataProcessorTest extends TestCase
$this->assertEquals('07.01.2024', $room['@abreise']);
}
public function testUpdatePayloadSendsBookedRoomsUnchanged(): void
{
$formData = $this->createFormDataWithBookedRooms();
$result = $this->processor->createUpdateRequestPayload($formData);
$this->assertSame(
[95 => ['1', '1,2,3,4'], 3 => ['3', '5,6,7,8,9,10']],
$this->roomsInPayload($result)
);
}
public function testUpdatePayloadDropsCanceledParticipantsFromRooms(): void
{
$formData = $this->createFormDataWithBookedRooms();
$formData->participants[5]->status = 'S';
$formData->booking->participantsStatus[5] = 'S';
$result = $this->processor->createUpdateRequestPayload($formData);
$this->assertSame(
[95 => ['1', '1,2,3,4'], 3 => ['3', '5,7,8,9,10']],
$this->roomsInPayload($result)
);
}
public function testUpdatePayloadKeepsRoomChangesMadeInBusProDuringTheEdit(): void
{
$formData = $this->createFormDataWithBookedRooms();
// The office moved participant 4 into the doubles after the edit session was loaded
$formData->booking->rooms[95]->mapping = [0, 1, 2];
$formData->booking->rooms[3]->totalCount = 4;
$formData->booking->rooms[3]->mapping = [3, 4, 5, 6, 7, 8, 9];
$result = $this->processor->createUpdateRequestPayload($formData);
$this->assertSame(
[95 => ['1', '1,2,3'], 3 => ['4', '4,5,6,7,8,9,10']],
$this->roomsInPayload($result)
);
}
public function testUpdatePayloadKeepsARoomTypeAddedInBusProDuringTheEdit(): void
{
$formData = $this->createFormDataWithBookedRooms();
// The office moved participants 1 and 2 out of the 4-bed room into a new double
$formData->booking->rooms[95]->mapping = [2, 3];
$formData->booking->rooms[95]->totalCount = 1;
$formData->booking->rooms[7] = $this->createBookedRoom(7, 'DZ', 1, [0, 1]);
$result = $this->processor->createUpdateRequestPayload($formData);
$this->assertSame(
[95 => ['1', '3,4'], 3 => ['3', '5,6,7,8,9,10'], 7 => ['1', '1,2']],
$this->roomsInPayload($result)
);
}
public function testCommunicationObjectCreation(): void
{
$formData = $this->createFormDataWithoutExistingCommunication();
@@ -526,6 +586,60 @@ class BookingDataProcessorTest extends TestCase
return $formData;
}
/**
* Ten participants as BusPro reports them: four in one 4-bed room, six in three doubles.
*/
private function createFormDataWithBookedRooms(): BookingDto
{
$bookingDto = new BookingDto($this->createMockTravel(), 1);
$bookingDto->booking = $this->createMockBooking();
$bookingDto->booking->participants = [];
$bookingDto->booking->participantsStatus = [];
$bookingDto->participants = [];
for ($index = 0; $index < 10; ++$index) {
$bookingDto->booking->participants[$index] = $this->createMockPersonalData("Participant{$index}");
$bookingDto->booking->participantsStatus[$index] = 'F';
$bookingDto->participants[$index] = $this->createMockParticipantDto($index, 'F');
$bookingDto->participants[$index]->assignedRoomId = $index < 4 ? 95 : 3;
}
$bookingDto->booking->rooms = [
95 => $this->createBookedRoom(95, '4er', 1, [0, 1, 2, 3]),
3 => $this->createBookedRoom(3, 'DZ', 3, [4, 5, 6, 7, 8, 9]),
];
return $bookingDto;
}
/** @param list<int> $mapping */
private function createBookedRoom(int $id, string $category, int $totalCount, array $mapping): Room
{
$room = new Room();
$room->id = $id;
$room->category = $category;
$room->boardId = 2;
$room->totalCount = $totalCount;
$room->mapping = $mapping;
return $room;
}
/**
* @param array<string, mixed> $payload
*
* @return array<int, array{string, string}> Room id => [anzahl, zuordnung]
*/
private function roomsInPayload(array $payload): array
{
$rooms = [];
foreach ($payload['ferienzielunterbringungen']['ferienzielunterbringung'] as $room) {
$rooms[$room['@idzimmer']] = [(string) $room['@anzahl'], $room['@zuordnung']];
}
return $rooms;
}
private function createFormDataWithoutExistingCommunication(): BookingDto
{
$formData = $this->createCompleteFormData();
@@ -33,7 +33,12 @@ class ParticipantAssignedRoomFieldHandlerTest extends TestCase
public function testShouldProcessReturnsTrueWhenFieldPresent(): void
{
$this->assertTrue($this->handler->shouldProcess(['assignedRoomId' => '1'], BookingDto::MODE_CREATE, 0));
$this->assertTrue($this->handler->shouldProcess(['assignedRoomId' => ''], BookingDto::MODE_EDIT, 5));
$this->assertTrue($this->handler->shouldProcess(['assignedRoomId' => ''], BookingDto::MODE_CREATE, 5));
}
public function testShouldProcessReturnsFalseInEditMode(): void
{
$this->assertFalse($this->handler->shouldProcess(['assignedRoomId' => '1'], BookingDto::MODE_EDIT, 0));
}
public function testShouldProcessReturnsFalseWhenFieldNotPresent(): void
@@ -13,13 +13,12 @@ use App\Service\ServiceAvailabilityCalculator;
use PHPUnit\Framework\TestCase;
/**
* Tests that draft restoration never unassigns a room.
* Tests that draft restoration never changes a room assignment.
*
* Edit mode renders the room as static text and never submits assignedRoomId, so a null in
* the draft payload is always an artefact of a snapshot taken before BusPro reported the
* assignment - typically for seats added to a group booking shortly before the draft was
* saved. Replaying such a null would strip the room from the UI and from the outbound
* zuordnung, so the room id uses the same merge strategy as single-select services.
* Edit mode renders the room as static text and never submits assignedRoomId, so the draft
* only holds what BusPro reported when it was saved: a null for seats added to a group booking
* shortly before, or a room the office has since reassigned. The room always comes from the
* booking as loaded; only the free-text remarks are restored.
*/
class BookingEditDraftMergerRoomAssignmentTest extends TestCase
{
@@ -43,7 +42,7 @@ class BookingEditDraftMergerRoomAssignmentTest extends TestCase
$this->assertSame(74, $participant->assignedRoomId);
}
public function testDraftAppliesRoomThatResolvesAgainstTravel(): void
public function testDraftDoesNotMoveParticipantToAnotherRoom(): void
{
$participant = new ParticipantDto();
$participant->mutable = true;
@@ -56,7 +55,7 @@ class BookingEditDraftMergerRoomAssignmentTest extends TestCase
$this->apply($travel, $participant, ['assignedRoomId' => 75]);
$this->assertSame(75, $participant->assignedRoomId);
$this->assertSame(74, $participant->assignedRoomId);
}
public function testDraftSkipsRoomThatIsUnknownToTravel(): void