From b4db0cb8f219556cab1adf04326b0c26c9143388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Fri, 18 Jul 2025 15:59:45 +0200 Subject: [PATCH] wip: booking process, refactor participant room assignment logic --- src/Form/BookingCreateStep2Type.php | 101 +++++++++--------- .../DataAdapters/ParticipantDataAdapter.php | 34 ++++++ 2 files changed, 83 insertions(+), 52 deletions(-) create mode 100644 src/Form/DataAdapters/ParticipantDataAdapter.php diff --git a/src/Form/BookingCreateStep2Type.php b/src/Form/BookingCreateStep2Type.php index dd14fdf..0e5baed 100644 --- a/src/Form/BookingCreateStep2Type.php +++ b/src/Form/BookingCreateStep2Type.php @@ -2,6 +2,7 @@ namespace App\Form; +use App\Form\DataAdapters\ParticipantDataAdapter; use App\Form\Model\BookingCreateDto; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; @@ -29,49 +30,9 @@ class BookingCreateStep2Type extends AbstractType return; } - // Count participants assigned to each room - $roomOccupancy = []; - foreach ($bookingCreateDto->participants as $participant) { - if (null !== $participant->assignedRoomId) { - $roomOccupancy[$participant->assignedRoomId] = ($roomOccupancy[$participant->assignedRoomId] ?? 0) + 1; - } - } - - // Generate per-participant room choices - $roomChoices = []; - foreach ($bookingCreateDto->participants as $index => $participant) { - $participantRoomChoices = []; - - foreach ($bookingCreateDto->getSelectedRooms() as $roomSelection) { - $currentOccupancy = $roomOccupancy[$roomSelection->roomId] ?? 0; - - // If this participant is already assigned to this room, exclude them from occupancy count - $adjustedOccupancy = $currentOccupancy; - if ($participant->assignedRoomId === $roomSelection->roomId) { - --$adjustedOccupancy; - } - - $remainingCapacity = $roomSelection->minPax - $adjustedOccupancy; - - // Include room if it has capacity OR if it's the participant's current assignment - if ($remainingCapacity > 0 || $participant->assignedRoomId === $roomSelection->roomId) { - $participantRoomChoices[$roomSelection->roomLabel] = $roomSelection->roomId; - } - } - - $roomChoices[$index] = $participantRoomChoices; - } - - // Create a custom form type that handles per-participant room choices - $form->add('participants', CollectionType::class, [ - 'entry_type' => BookingCreateParticipantType::class, - 'allow_add' => false, - 'allow_delete' => false, - 'by_reference' => false, - 'entry_options' => [ - 'room_choices' => $roomChoices, - ], - ]); + $adapter = new ParticipantDataAdapter($bookingCreateDto->participants); + $roomChoices = $this->generateRoomChoices($adapter, $bookingCreateDto->getSelectedRooms()); + $this->addParticipantsField($form, $roomChoices); } public function onPreSubmit(FormEvent $event): void @@ -81,20 +42,46 @@ class BookingCreateStep2Type extends AbstractType /** @var BookingCreateDto $bookingCreateDto */ $bookingCreateDto = $form->getData(); + $adapter = new ParticipantDataAdapter($data['participants']); + $roomChoices = $this->generateRoomChoices($adapter, $bookingCreateDto->getSelectedRooms()); + $form->remove('participants'); + $this->addParticipantsField($form, $roomChoices); + } + + /** + * Calculates room occupancy based on participant assignments. + * + * @return array + */ + private function calculateRoomOccupancy(ParticipantDataAdapter $adapter): array + { $roomOccupancy = []; - foreach ($data['participants'] as $participant) { - if (null !== $participant['assignedRoomId']) { - $assignedRoomId = (int) $participant['assignedRoomId']; + + foreach ($adapter->getParticipants() as $participant) { + $assignedRoomId = $adapter->getAssignedRoomId($participant); + if (null !== $assignedRoomId) { $roomOccupancy[$assignedRoomId] = ($roomOccupancy[$assignedRoomId] ?? 0) + 1; } } - $roomChoices = []; - foreach ($data['participants'] as $index => $participant) { - $participantRoomChoices = []; - $assignedRoomId = (int) $participant['assignedRoomId']; + return $roomOccupancy; + } - foreach ($bookingCreateDto->getSelectedRooms() as $roomSelection) { + /** + * Generates room choices for each participant based on availability and current assignments. + * + * @return array> + */ + private function generateRoomChoices(ParticipantDataAdapter $adapter, array $selectedRooms): array + { + $roomOccupancy = $this->calculateRoomOccupancy($adapter); + $roomChoices = []; + + foreach ($adapter->getParticipants() as $index => $participant) { + $participantRoomChoices = []; + $assignedRoomId = $adapter->getAssignedRoomId($participant); + + foreach ($selectedRooms as $roomSelection) { $currentOccupancy = $roomOccupancy[$roomSelection->roomId] ?? 0; // If this participant is already assigned to this room, exclude them from occupancy count @@ -113,7 +100,17 @@ class BookingCreateStep2Type extends AbstractType $roomChoices[$index] = $participantRoomChoices; } - $form->remove('participants'); + + return $roomChoices; + } + + /** + * Adds the participants collection field to the form with the given room choices. + * + * @param array> $roomChoices + */ + private function addParticipantsField(FormInterface $form, array $roomChoices): void + { $form->add('participants', CollectionType::class, [ 'entry_type' => BookingCreateParticipantType::class, 'allow_add' => false, diff --git a/src/Form/DataAdapters/ParticipantDataAdapter.php b/src/Form/DataAdapters/ParticipantDataAdapter.php new file mode 100644 index 0000000..b88af11 --- /dev/null +++ b/src/Form/DataAdapters/ParticipantDataAdapter.php @@ -0,0 +1,34 @@ +participants = $participants; + } + + public function getParticipants(): array + { + return $this->participants; + } + + public function getAssignedRoomId(mixed $participant): ?int + { + if (is_array($participant)) { + $assignedRoomId = $participant['assignedRoomId'] ?? null; + return null !== $assignedRoomId ? (int) $assignedRoomId : null; + } + + return $participant->assignedRoomId; + } +}