fix: reset room assignments after updated selection if required
This commit is contained in:
@@ -74,6 +74,9 @@ class Step2Controller extends AbstractController
|
|||||||
fn ($user, $participant) => $this->prepopulationService->prepopulateApplicantFromUser($user, $participant)
|
fn ($user, $participant) => $this->prepopulationService->prepopulateApplicantFromUser($user, $participant)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Validate room assignments against current selection (handles back-navigation from step 2 to step 1)
|
||||||
|
$this->roomAssignmentService->validateAndResetInvalidAssignments($bookingCreateDto);
|
||||||
|
|
||||||
// Auto-assign rooms if needed
|
// Auto-assign rooms if needed
|
||||||
$this->roomAssignmentService->assignRoomsIfNeeded($bookingCreateDto);
|
$this->roomAssignmentService->assignRoomsIfNeeded($bookingCreateDto);
|
||||||
|
|
||||||
|
|||||||
@@ -110,4 +110,48 @@ class RoomAssignmentService
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates and resets room assignments that reference rooms no longer selected.
|
||||||
|
*
|
||||||
|
* This method ensures room assignments remain valid after room selection changes in Step 1.
|
||||||
|
* When a user goes back to Step 1 and changes room selections, existing assignments may
|
||||||
|
* reference room IDs that are no longer in the selected rooms list. This method detects
|
||||||
|
* such invalid assignments and resets them to null.
|
||||||
|
*
|
||||||
|
* @param BookingDto $dto The booking DTO to validate
|
||||||
|
*
|
||||||
|
* @return bool True if any assignments were reset, false if all were valid
|
||||||
|
*/
|
||||||
|
public function validateAndResetInvalidAssignments(BookingDto $dto): bool
|
||||||
|
{
|
||||||
|
$selectedRoomIds = $this->getSelectedRoomIds($dto);
|
||||||
|
$resetOccurred = false;
|
||||||
|
|
||||||
|
foreach ($dto->participants as $participant) {
|
||||||
|
if (null !== $participant->assignedRoomId && false === in_array($participant->assignedRoomId, $selectedRoomIds, true)) {
|
||||||
|
$participant->assignedRoomId = null;
|
||||||
|
$resetOccurred = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resetOccurred;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of room IDs from currently selected rooms.
|
||||||
|
*
|
||||||
|
* @param BookingDto $dto The booking DTO containing room selections
|
||||||
|
*
|
||||||
|
* @return array<int> Array of selected room IDs
|
||||||
|
*/
|
||||||
|
private function getSelectedRoomIds(BookingDto $dto): array
|
||||||
|
{
|
||||||
|
$ids = [];
|
||||||
|
foreach ($dto->getSelectedRooms() as $roomSelection) {
|
||||||
|
$ids[] = $roomSelection->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,6 +190,109 @@ class RoomAssignmentServiceTest extends TestCase
|
|||||||
self::assertSame(100, $bookingDto->participants[1]->assignedRoomId);
|
self::assertSame(100, $bookingDto->participants[1]->assignedRoomId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function validateAndResetInvalidAssignmentsResetsOrphanedAssignments(): void
|
||||||
|
{
|
||||||
|
// Create DTO with only room 100 selected
|
||||||
|
$bookingDto = $this->createBookingDtoWithRoomSelections([
|
||||||
|
['roomId' => 100, 'quantity' => 2, 'capacity' => 2],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create participants with assignments to room 100 and room 200 (no longer selected)
|
||||||
|
$bookingDto->participants = [
|
||||||
|
new ParticipantDto(),
|
||||||
|
new ParticipantDto(),
|
||||||
|
new ParticipantDto(),
|
||||||
|
new ParticipantDto(),
|
||||||
|
];
|
||||||
|
$bookingDto->participants[0]->assignedRoomId = 100;
|
||||||
|
$bookingDto->participants[1]->assignedRoomId = 100;
|
||||||
|
$bookingDto->participants[2]->assignedRoomId = 200; // Invalid - room not selected
|
||||||
|
$bookingDto->participants[3]->assignedRoomId = 200; // Invalid - room not selected
|
||||||
|
|
||||||
|
$result = $this->service->validateAndResetInvalidAssignments($bookingDto);
|
||||||
|
|
||||||
|
self::assertTrue($result, 'Should return true when assignments were reset');
|
||||||
|
self::assertSame(100, $bookingDto->participants[0]->assignedRoomId);
|
||||||
|
self::assertSame(100, $bookingDto->participants[1]->assignedRoomId);
|
||||||
|
self::assertNull($bookingDto->participants[2]->assignedRoomId, 'Invalid assignment should be reset to null');
|
||||||
|
self::assertNull($bookingDto->participants[3]->assignedRoomId, 'Invalid assignment should be reset to null');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function validateAndResetInvalidAssignmentsReturnsFalseWhenAllValid(): void
|
||||||
|
{
|
||||||
|
$bookingDto = $this->createBookingDtoWithRoomSelections([
|
||||||
|
['roomId' => 100, 'quantity' => 2, 'capacity' => 2],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// All participants assigned to the valid room
|
||||||
|
$bookingDto->participants = [
|
||||||
|
new ParticipantDto(),
|
||||||
|
new ParticipantDto(),
|
||||||
|
];
|
||||||
|
$bookingDto->participants[0]->assignedRoomId = 100;
|
||||||
|
$bookingDto->participants[1]->assignedRoomId = 100;
|
||||||
|
|
||||||
|
$result = $this->service->validateAndResetInvalidAssignments($bookingDto);
|
||||||
|
|
||||||
|
self::assertFalse($result, 'Should return false when no assignments needed reset');
|
||||||
|
self::assertSame(100, $bookingDto->participants[0]->assignedRoomId);
|
||||||
|
self::assertSame(100, $bookingDto->participants[1]->assignedRoomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function validateAndResetInvalidAssignmentsHandlesNullAssignments(): void
|
||||||
|
{
|
||||||
|
$bookingDto = $this->createBookingDtoWithRoomSelections([
|
||||||
|
['roomId' => 100, 'quantity' => 1, 'capacity' => 2],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Participants with null assignments should not trigger a reset
|
||||||
|
$bookingDto->participants = [
|
||||||
|
new ParticipantDto(),
|
||||||
|
new ParticipantDto(),
|
||||||
|
];
|
||||||
|
$bookingDto->participants[0]->assignedRoomId = null;
|
||||||
|
$bookingDto->participants[1]->assignedRoomId = null;
|
||||||
|
|
||||||
|
$result = $this->service->validateAndResetInvalidAssignments($bookingDto);
|
||||||
|
|
||||||
|
self::assertFalse($result, 'Should return false when only null assignments exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function validateAndResetInvalidAssignmentsHandlesEmptySelectedRooms(): void
|
||||||
|
{
|
||||||
|
// All rooms have quantity 0 (none selected)
|
||||||
|
$bookingDto = $this->createBookingDtoWithRoomSelections([
|
||||||
|
['roomId' => 100, 'quantity' => 0, 'capacity' => 2],
|
||||||
|
['roomId' => 200, 'quantity' => 0, 'capacity' => 2],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Participants still have old assignments
|
||||||
|
$bookingDto->participants = [
|
||||||
|
new ParticipantDto(),
|
||||||
|
new ParticipantDto(),
|
||||||
|
];
|
||||||
|
$bookingDto->participants[0]->assignedRoomId = 100;
|
||||||
|
$bookingDto->participants[1]->assignedRoomId = 200;
|
||||||
|
|
||||||
|
$result = $this->service->validateAndResetInvalidAssignments($bookingDto);
|
||||||
|
|
||||||
|
self::assertTrue($result, 'Should return true when all assignments become invalid');
|
||||||
|
self::assertNull($bookingDto->participants[0]->assignedRoomId);
|
||||||
|
self::assertNull($bookingDto->participants[1]->assignedRoomId);
|
||||||
|
}
|
||||||
|
|
||||||
private function createBookingDtoWithRoomSelections(array $selections): BookingDto
|
private function createBookingDtoWithRoomSelections(array $selections): BookingDto
|
||||||
{
|
{
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
|
|||||||
Reference in New Issue
Block a user