diff --git a/src/BusProNet/ApiClient.php b/src/BusProNet/ApiClient.php index 3938d20..0ba3f43 100644 --- a/src/BusProNet/ApiClient.php +++ b/src/BusProNet/ApiClient.php @@ -15,9 +15,7 @@ use App\BusProNet\Model\PersonalData; use App\BusProNet\Model\Travel; use App\BusProNet\Traits\ApiClientTrait; use App\BusProNet\XmlParser\ApiResponseParser; -use App\Form\Model\BookingCreateDto; use App\Form\Model\BookingDto; -use App\Form\Model\BookingEditDto; use App\Form\Model\RegistrationDto; use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemOperator; @@ -215,14 +213,14 @@ class ApiClient * First phase of the two-phase booking process. Validates all booking data * and returns pricing information without creating an actual booking. * - * @param BookingCreateDto $bookingDto The booking creation form data - * @param bool $debug Enable debug mode (XML dumps) + * @param BookingDto $bookingDto The booking creation form data + * @param bool $debug Enable debug mode (XML dumps) * * @return Notification|BookingResponse Notification on error, BookingResponse on success * * @throws ApiClientException If the API request fails */ - public function createBookingInquiry(BookingCreateDto $bookingDto, bool $debug = false): Notification|BookingResponse + public function createBookingInquiry(BookingDto $bookingDto, bool $debug = false): Notification|BookingResponse { $payload = $this->bookingDataProcessor->createBookingRequestPayload($bookingDto, 'Anfrage'); @@ -242,14 +240,14 @@ class ApiClient * Second phase of the two-phase booking process. Creates the actual booking * after successful inquiry validation. * - * @param BookingCreateDto $bookingDto The booking creation form data - * @param bool $debug Enable debug mode (XML dumps) + * @param BookingDto $bookingDto The booking creation form data + * @param bool $debug Enable debug mode (XML dumps) * * @return Notification|BookingResponse Notification on error, BookingResponse with booking number on success * * @throws ApiClientException If the API request fails */ - public function createBooking(BookingCreateDto $bookingDto, bool $debug = false): Notification|BookingResponse + public function createBooking(BookingDto $bookingDto, bool $debug = false): Notification|BookingResponse { $payload = $this->bookingDataProcessor->createBookingRequestPayload($bookingDto, 'Buchung'); diff --git a/src/BusProNet/DataProcessor/BookingDataProcessor.php b/src/BusProNet/DataProcessor/BookingDataProcessor.php index a879d74..3b2200f 100644 --- a/src/BusProNet/DataProcessor/BookingDataProcessor.php +++ b/src/BusProNet/DataProcessor/BookingDataProcessor.php @@ -12,9 +12,7 @@ use App\BusProNet\Model\PersonalData; use App\BusProNet\Model\Travel; use App\BusProNet\Utility\DirectionMapper; use App\Form\Model\BankAccountDto; -use App\Form\Model\BookingCreateDto; use App\Form\Model\BookingDto; -use App\Form\Model\BookingEditDto; use App\Form\Model\ParticipantDto; use App\Service\InsuranceMatchingService; @@ -39,6 +37,12 @@ class BookingDataProcessor * * Extracts all service selections from the booking entity and assigns them * to participant DTOs, creating a unified data structure identical to create mode. + * + * IMPORTANT: Address handling for edit mode + * - ParticipantDto::fromPersonalData() clones address objects to prevent shared references + * - First participant's address is NOT auto-populated from applicant + * - Template uses placeholders to show applicant's address as hints + * - This prevents address data from being inadvertently modified during form binding */ public function createBookingDtoFromBooking(Booking $booking, Travel $travel): BookingDto { @@ -351,8 +355,8 @@ class BookingDataProcessor * Insurance can be either individual or package-based, with automatic price-tier adjustment. * * @param ParticipantDto $participant The participant data from the form - * @param Booking $bookingData The booking data object to update - * @param Travel $travelData The travel data containing available insurances + * @param Booking $bookingData The booking data object to update + * @param Travel $travelData The travel data containing available insurances */ private function processInsurance(ParticipantDto $participant, Booking $bookingData, Travel $travelData): void { @@ -654,7 +658,7 @@ class BookingDataProcessor * ('Anfrage') or a final booking commit ('Buchung'). * * @param BookingDto $bookingDto The booking creation form data - * @param string $bookingType Either 'Anfrage' (inquiry) or 'Buchung' (final booking) + * @param string $bookingType Either 'Anfrage' (inquiry) or 'Buchung' (final booking) * * @return array The structured payload array for BusProNet API submission */ @@ -822,11 +826,11 @@ class BookingDataProcessor * - abreise (departure date) * - anzahl (number of rooms of this type booked) * - * @param array $payload The payload array to modify - * @param array $roomMap Map of room ID to participant IDs - * @param BookingCreateDto $bookingDto The booking data for accessing room details and quantities + * @param array $payload The payload array to modify + * @param array $roomMap Map of room ID to participant IDs + * @param BookingDto $bookingDto The booking data for accessing room details and quantities */ - private function addRoomMappingsToPayload(array &$payload, array $roomMap, BookingCreateDto $bookingDto): void + private function addRoomMappingsToPayload(array &$payload, array $roomMap, BookingDto $bookingDto): void { if (empty($roomMap)) { return; @@ -870,7 +874,7 @@ class BookingDataProcessor * * @return array> Map of room ID to participant IDs */ - private function collectRoomMappings(BookingCreateDto $bookingDto): array + private function collectRoomMappings(BookingDto $bookingDto): array { $roomMap = []; @@ -893,7 +897,7 @@ class BookingDataProcessor * * @return array> Map of service ID to participant IDs */ - private function collectServiceMappings(BookingCreateDto $bookingDto): array + private function collectServiceMappings(BookingDto $bookingDto): array { $serviceMap = []; @@ -944,7 +948,7 @@ class BookingDataProcessor * * @return array> Map of transportation service ID to participant IDs */ - private function collectTransportationMappings(BookingCreateDto $bookingDto): array + private function collectTransportationMappings(BookingDto $bookingDto): array { $transportationMap = []; @@ -971,7 +975,7 @@ class BookingDataProcessor * * @return array> Map of pickup ID to participant IDs */ - private function collectPickupMappings(BookingCreateDto $bookingDto): array + private function collectPickupMappings(BookingDto $bookingDto): array { $pickupMap = []; @@ -993,7 +997,7 @@ class BookingDataProcessor * * @return array> Map of insurance ID to participant IDs */ - private function collectInsuranceMappings(BookingCreateDto $bookingDto): array + private function collectInsuranceMappings(BookingDto $bookingDto): array { $insuranceMap = []; @@ -1033,7 +1037,12 @@ class BookingDataProcessor } // Get all available insurances from travel data - $availableInsurances = array_values($bookingDto->travel->insurances); + $availableInsurances = $bookingDto->travel->insurances; + + // Exclude complementary insurances from bulk assignment logic + // They are only available as part of packages and cannot be directly selected + $availableInsurances = array_filter($availableInsurances, fn ($insurance) => !$insurance->complementary); + $availableInsurances = array_values($availableInsurances); // Use InsuranceMatchingService for proper type-based assignment with price tier matching $assignments = $this->insuranceMatchingService->batchAssignInsuranceToParticipants( @@ -1055,7 +1064,7 @@ class BookingDataProcessor // In edit mode: only apply bulk insurance if participant has no insurance // This respects the rule that once assigned, insurance cannot be changed - if ($bookingDto instanceof BookingEditDto && null !== $participant->insurance) { + if (BookingDto::MODE_EDIT === $bookingDto->getMode() && null !== $participant->insurance) { continue; // Skip participants with existing insurance assignment } diff --git a/src/BusProNet/Model/Service.php b/src/BusProNet/Model/Service.php index ea6c30d..49b47a3 100644 --- a/src/BusProNet/Model/Service.php +++ b/src/BusProNet/Model/Service.php @@ -96,4 +96,14 @@ class Service #[Groups(['api:single', 'api:list'])] public ?string $description = null; + + /** + * Indicates whether this service should be included in insurance eligibility price calculation. + * + * Maps to XML attribute 'versicherungsberechnung' (J=true, N=false). + * When false, this service's price is excluded when determining which insurance + * tier is appropriate for a participant. + */ + #[Groups(['api:single', 'api:list'])] + public bool $includeInInsuranceCalculation = true; } diff --git a/src/BusProNet/XmlParser/TravelParser.php b/src/BusProNet/XmlParser/TravelParser.php index cdeb1d9..4191f29 100644 --- a/src/BusProNet/XmlParser/TravelParser.php +++ b/src/BusProNet/XmlParser/TravelParser.php @@ -145,6 +145,9 @@ class TravelParser extends AbstractParser // Parse age constraints $this->parseServiceAgeConstraints($serviceNode, $service); + // Parse insurance calculation flag + $service->includeInInsuranceCalculation = $this->stringToBool($serviceNode->attr('versicherungsberechnung')); + $additionalServices[$serviceId] = $service; }); @@ -192,6 +195,9 @@ class TravelParser extends AbstractParser $service->dayTime = (new DayTimeUtility())->mapTime($timeFrom); } + // Parse insurance calculation flag + $service->includeInInsuranceCalculation = $this->stringToBool($serviceNode->attr('versicherungsberechnung')); + $transportationServices[$serviceId] = $service; }); diff --git a/src/Controller/Booking/BookingCreateTrait.php b/src/Controller/Booking/BookingCreateTrait.php index 705a8c6..ab42604 100644 --- a/src/Controller/Booking/BookingCreateTrait.php +++ b/src/Controller/Booking/BookingCreateTrait.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Controller\Booking; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use Symfony\Component\HttpFoundation\RedirectResponse; /** @@ -21,7 +21,7 @@ trait BookingCreateTrait * * @return RedirectResponse|null Returns redirect response if validation fails, null if access is allowed */ - private function validateStepAccess(BookingCreateDto $bookingCreateDto, int $expectedStep): ?RedirectResponse + private function validateStepAccess(BookingDto $bookingCreateDto, int $expectedStep): ?RedirectResponse { // Allow access to current step or any previous step if ($expectedStep > $bookingCreateDto->currentStep) { @@ -36,7 +36,7 @@ trait BookingCreateTrait /** * Redirects to the current step based on the DTO's currentStep. */ - private function redirectToCurrentStep(BookingCreateDto $bookingCreateDto): RedirectResponse + private function redirectToCurrentStep(BookingDto $bookingCreateDto): RedirectResponse { $route = match ($bookingCreateDto->currentStep) { 2 => 'app_booking_create_step_2', @@ -51,7 +51,7 @@ trait BookingCreateTrait /** * Returns the total number of participants based on room selections. */ - private function getParticipantsCount(BookingCreateDto $bookingCreateDto): int + private function getParticipantsCount(BookingDto $bookingCreateDto): int { return $this ->bookingService @@ -63,7 +63,7 @@ trait BookingCreateTrait * * @return array Array containing all variables needed for the summary partial */ - private function getSummaryVariables(BookingCreateDto $bookingCreateDto): array + private function getSummaryVariables(BookingDto $bookingCreateDto): array { $participantsCount = $this->getParticipantsCount($bookingCreateDto); $summary = $this->bookingService->getRoomSummaryAndParticipantCount($bookingCreateDto); diff --git a/src/Controller/Booking/BookingExceptionHandlerTrait.php b/src/Controller/Booking/BookingExceptionHandlerTrait.php index ab64705..963c980 100644 --- a/src/Controller/Booking/BookingExceptionHandlerTrait.php +++ b/src/Controller/Booking/BookingExceptionHandlerTrait.php @@ -9,7 +9,9 @@ use App\Exception\HotelNotFoundException; use App\Exception\HotelNotInTravelException; use App\Exception\NoRoomsAvailableException; use App\Exception\TravelNotFoundException; +use App\Form\Model\BookingDto; use App\Service\BookingService; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -27,7 +29,7 @@ trait BookingExceptionHandlerTrait * Handles all booking-related exceptions and provides appropriate user feedback * by redirecting to the error page with flash messages. */ - protected function getOrCreateBookingCreateDto(BookingService $bookingService, Request $request): mixed + protected function getOrCreateBookingCreateDto(BookingService $bookingService, Request $request): BookingDto|RedirectResponse { try { return $bookingService->getOrCreateBookingCreateDto($request); diff --git a/src/Controller/Booking/CreateStep2Controller.php b/src/Controller/Booking/CreateStep2Controller.php index 2f194b8..3dd27c4 100644 --- a/src/Controller/Booking/CreateStep2Controller.php +++ b/src/Controller/Booking/CreateStep2Controller.php @@ -6,7 +6,7 @@ namespace App\Controller\Booking; use App\Controller\Traits\HtmxControllerTrait; use App\Form\BookingCreateStep2Type; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; use App\Service\BookingPriceCalculatorService; use App\Service\BookingService; @@ -67,7 +67,7 @@ class CreateStep2Controller extends AbstractController // Pre-select mandatory services for participants with birth dates $this->bookingService->preselectMandatoryServices($bookingCreateDto); - $this->bookingService->saveBookingCreateDto($request, $bookingCreateDto); + $this->bookingService->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE); $form = $this->createForm(BookingCreateStep2Type::class, $bookingCreateDto, [ 'attr' => ['novalidate' => 'novalidate'], @@ -78,7 +78,7 @@ class CreateStep2Controller extends AbstractController if ($form->isSubmitted() && $form->isValid()) { $bookingCreateDto->currentStep = 3; - $this->bookingService->saveBookingCreateDto($request, $bookingCreateDto); + $this->bookingService->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE); return $this->redirectToRoute('app_booking_create_step_3'); } @@ -129,7 +129,7 @@ class CreateStep2Controller extends AbstractController // Pre-select mandatory services after form processing but before pricing calculation $this->bookingService->preselectMandatoryServices($bookingCreateDto); - $this->bookingService->saveBookingCreateDto($request, $bookingCreateDto); + $this->bookingService->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE); // Collect notifications from all participants $notifications = $this->collectParticipantNotifications($bookingCreateDto); @@ -173,9 +173,9 @@ class CreateStep2Controller extends AbstractController * based on room selections. Preserves existing participant data when possible * and assigns proper index values. * - * @param BookingCreateDto $bookingCreateDto The booking DTO to update + * @param BookingDto $bookingCreateDto The booking DTO to update */ - private function ensureCorrectNumberOfParticipants(BookingCreateDto $bookingCreateDto): void + private function ensureCorrectNumberOfParticipants(BookingDto $bookingCreateDto): void { $participantsCount = $this->getParticipantsCount($bookingCreateDto); @@ -195,13 +195,13 @@ class CreateStep2Controller extends AbstractController * to ensure service availability is reasonably up-to-date while reducing API calls. * This is essential for accurate pricing and service selection during the booking process. * - * @param BookingCreateDto $bookingCreateDto The booking DTO containing travel data to enrich + * @param BookingDto $bookingCreateDto The booking DTO containing travel data to enrich */ - private function enrichWithFreshAvailabilities(BookingCreateDto $bookingCreateDto): void + private function enrichWithFreshAvailabilities(BookingDto $bookingCreateDto): void { $dateId = $bookingCreateDto->travel->id; - $availabilities = $this->travelDataService->getAvailabilityDataCached($dateId); + $availabilities = $this->travelDataService->getAvailabilityData($dateId, true); if (null !== $availabilities) { $this->travelDataService->patchAvailabilities($bookingCreateDto->travel, $availabilities); @@ -214,9 +214,9 @@ class CreateStep2Controller extends AbstractController * This is called when entering Step 2 to ensure all participants have room assignments * based on the selected rooms from Step 1. Only assigns if participants are unassigned. * - * @param BookingCreateDto $bookingCreateDto The booking DTO with participants and room selections + * @param BookingDto $bookingCreateDto The booking DTO with participants and room selections */ - private function autoAssignRoomsIfNeeded(BookingCreateDto $bookingCreateDto): void + private function autoAssignRoomsIfNeeded(BookingDto $bookingCreateDto): void { // Check if any participants need room assignment $needsAssignment = false; @@ -235,11 +235,11 @@ class CreateStep2Controller extends AbstractController /** * Collects all notifications from participants and clears them. * - * @param BookingCreateDto $bookingCreateDto The booking DTO containing participants + * @param BookingDto $bookingCreateDto The booking DTO containing participants * * @return array Array of notification messages */ - private function collectParticipantNotifications(BookingCreateDto $bookingCreateDto): array + private function collectParticipantNotifications(BookingDto $bookingCreateDto): array { $notifications = []; diff --git a/src/Form/BookingCreateStep1Type.php b/src/Form/BookingCreateStep1Type.php index 32a99dd..11df1fb 100644 --- a/src/Form/BookingCreateStep1Type.php +++ b/src/Form/BookingCreateStep1Type.php @@ -2,7 +2,7 @@ namespace App\Form; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\FormBuilderInterface; @@ -30,7 +30,7 @@ class BookingCreateStep1Type extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => BookingCreateDto::class, + 'data_class' => BookingDto::class, ]); } } diff --git a/src/Form/BookingCreateStep2Type.php b/src/Form/BookingCreateStep2Type.php index a005214..1b3eadf 100644 --- a/src/Form/BookingCreateStep2Type.php +++ b/src/Form/BookingCreateStep2Type.php @@ -2,7 +2,7 @@ namespace App\Form; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use App\Form\Service\ParticipantFieldHandlerRegistry; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; @@ -31,7 +31,7 @@ class BookingCreateStep2Type extends AbstractType */ public function onPreSetData(FormEvent $event): void { - /** @var BookingCreateDto|null $data */ + /** @var BookingDto|null $data */ $data = $event->getData(); if (null === $data) { return; @@ -43,7 +43,7 @@ class BookingCreateStep2Type extends AbstractType /** * Handles dynamic participant form field updates on POST requests (e.g., from HTMX). * - * This listener synchronizes the BookingCreateDto with the submitted participant data *before* + * This listener synchronizes the BookingDto with the submitted participant data *before* * the form's children are processed. It then rebuilds the participants * field to ensure choice loaders are created with the fresh state. */ @@ -52,7 +52,7 @@ class BookingCreateStep2Type extends AbstractType $form = $event->getForm(); $submittedData = $event->getData(); - /** @var BookingCreateDto $bookingDto */ + /** @var BookingDto $bookingDto */ $bookingDto = $form->getData(); // Process field handlers and synchronize submitted data with cleaned DTO state @@ -81,7 +81,7 @@ class BookingCreateStep2Type extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => BookingCreateDto::class, + 'data_class' => BookingDto::class, ]); } } diff --git a/src/Form/BookingCreateStep3Type.php b/src/Form/BookingCreateStep3Type.php index 12a8c92..2d2bedf 100644 --- a/src/Form/BookingCreateStep3Type.php +++ b/src/Form/BookingCreateStep3Type.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace App\Form; use App\BusProNet\Constants; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use Carbon\CarbonImmutable; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -69,7 +69,7 @@ class BookingCreateStep3Type extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => BookingCreateDto::class, + 'data_class' => BookingDto::class, ]); } @@ -88,7 +88,7 @@ class BookingCreateStep3Type extends AbstractType * * Direct debit is only available if the travel starts at least 14 days from now. */ - private function isDebitAvailable(BookingCreateDto $bookingDto): bool + private function isDebitAvailable(BookingDto $bookingDto): bool { $travelStartDate = CarbonImmutable::instance($bookingDto->travel->dateFrom); $now = CarbonImmutable::now(); diff --git a/src/Form/BookingCreateStep4Type.php b/src/Form/BookingCreateStep4Type.php index 1120f4b..dead5d8 100644 --- a/src/Form/BookingCreateStep4Type.php +++ b/src/Form/BookingCreateStep4Type.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Form; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\FormBuilderInterface; @@ -31,7 +31,7 @@ class BookingCreateStep4Type extends AbstractType public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'data_class' => BookingCreateDto::class, + 'data_class' => BookingDto::class, ]); } -} \ No newline at end of file +} diff --git a/src/Form/Model/BookingCreateDto.php b/src/Form/Model/BookingCreateDto.php deleted file mode 100644 index 870ac84..0000000 --- a/src/Form/Model/BookingCreateDto.php +++ /dev/null @@ -1,151 +0,0 @@ - - */ - #[Assert\Valid] - public array $roomSelections = []; - - /** - * @var array - */ - #[Assert\Valid] - public array $participants = []; - - #[Assert\Choice( - choices: [Constants::PAYMENT_METHOD_TRANSFER, Constants::PAYMENT_METHOD_DEBIT], - message: 'Bitte wählen Sie eine gültige Zahlungsart.' - )] - public ?string $paymentMethod = Constants::PAYMENT_METHOD_TRANSFER; - - public ?BankAccountDto $bankAccount = null; - - public ?int $agencyId = null; - - public function __construct(public Travel $travel, public int $hotelId) - { - } - - public function getMode(): string - { - return BookingDtoInterface::MODE_CREATE; - } - - /** - * @return array - */ - public function getSelectedRooms(): array - { - return array_filter($this->roomSelections, function (RoomSelectionDto $roomSelection) { - return 0 < $roomSelection->quantity; - }); - } - - public function getParticipants(): array - { - return $this->participants; - } - - public function hasParticipant(int $index): bool - { - return isset($this->participants[$index]); - } - - public function getParticipant(int $index): ?ParticipantDto - { - return $this->participants[$index] ?? null; - } - - /** - * Determines if this is a family booking based on participant age distribution. - * - * A family booking is defined as: - * - 1 or 2 participants aged 18 or older (adults) - * - At least 1 participant younger than 18 (children) - * - * @return bool True if this qualifies as a family booking - */ - public function isFamilyBooking(): bool - { - $adults = 0; // Count of participants >= 18 years - $children = 0; // Count of participants < 18 years - - // Use travel start date for age calculation - $travelStartDate = $this->travel->dateFrom; - - foreach ($this->participants as $participant) { - $age = $participant->getAge($travelStartDate); - - if (null === $age) { - continue; // Skip participants without birth date - } - - if ($age >= 18) { - ++$adults; - } else { - ++$children; - } - } - - return ($adults >= 1 && $adults <= 2) && ($children >= 1); - } - - #[Assert\Callback(callback: 'validateRoomSelection', groups: ['booking_create_step_1'])] - public function validateRoomSelection(ExecutionContextInterface $context): void - { - $selectedRooms = $this->getSelectedRooms(); - - if (0 === count($selectedRooms)) { - $context->buildViolation('Bitte mindestens ein Zimmer/Bett auswählen') - ->addViolation(); - } - } - - #[Assert\Callback] - public function validateBankAccount(ExecutionContextInterface $context): void - { - if (Constants::PAYMENT_METHOD_DEBIT !== $this->paymentMethod) { - return; - } - - if (null === $this->bankAccount) { - $context->buildViolation('Bitte geben Sie Ihre Bankverbindung an.') - ->atPath('bankAccount') - ->addViolation(); - - return; - } - - // Validate IBAN - if (null === $this->bankAccount->iban || '' === trim($this->bankAccount->iban)) { - $context->buildViolation('Bitte geben Sie Ihre IBAN ein.') - ->atPath('bankAccount.iban') - ->addViolation(); - } - - // Validate account holder - if (null === $this->bankAccount->accountHolder || '' === trim($this->bankAccount->accountHolder)) { - $context->buildViolation('Bitte geben Sie den Kontoinhaber ein.') - ->atPath('bankAccount.accountHolder') - ->addViolation(); - } - - // Validate SEPA mandate - if (false === $this->bankAccount->sepaMandateAccepted) { - $context->buildViolation('Bitte akzeptieren Sie das SEPA-Mandat.') - ->atPath('bankAccount.sepaMandateAccepted') - ->addViolation(); - } - } -} diff --git a/src/Form/Model/BookingDtoInterface.php b/src/Form/Model/BookingDtoInterface.php deleted file mode 100644 index 27bd9a1..0000000 --- a/src/Form/Model/BookingDtoInterface.php +++ /dev/null @@ -1,51 +0,0 @@ - Array of participant DTOs indexed by participant index - */ - public function getParticipants(): array; - - /** - * Checks if a participant exists at the given index. - * - * @param int $index The participant index to check - * - * @return bool True if a participant exists at the given index - */ - public function hasParticipant(int $index): bool; - - /** - * Gets a participant by index. - * - * @param int $index The participant index - * - * @return ParticipantDto|null The participant DTO or null if not found - */ - public function getParticipant(int $index): ?ParticipantDto; -} diff --git a/src/Form/Model/BookingEditDto.php b/src/Form/Model/BookingEditDto.php deleted file mode 100644 index 4d18554..0000000 --- a/src/Form/Model/BookingEditDto.php +++ /dev/null @@ -1,121 +0,0 @@ - - */ - #[Assert\Valid] - public array $participants = []; - - public function __construct(public Booking $booking, public Travel $travel) - { - } - - public function getMode(): string - { - return BookingDtoInterface::MODE_EDIT; - } - - public static function fromBooking(Booking $booking, Travel $travel): static - { - $instance = new static($booking, $travel); - - $instance->booking = $booking; - $instance->travel = $travel; - - foreach ($booking->participants as $index => $participant) { - /** @var PersonalData $participant */ - // For the first participant (applicant), use applicant data instead of participant data - $personalData = 0 === $index && null !== $booking->applicant ? $booking->applicant : $participant; - $participantData = ParticipantDto::fromPersonalData($personalData); - $participantData->index = $index; - - $participantData->courses = $booking - ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_COURSES); - - // Skipass is single selection - use dedicated method - $participantData->skiPass = $booking->getSkiPassForParticipant($index); - - $participantData->additionalServices = $booking - ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_ADDITIONAL); - $participantData->board = $booking - ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_BOARD); - $participantData->rentals = $booking - ->getAdditionalServicesForParticipantByGroup($index, Constants::TOKEN_RENTALS); - // Transportation services using improved direction mapping - // Direction mapping handles BusProNet's inconsistent codes (H <=> HIN, R <=> RUECK) - $outboundTransportation = $booking - ->getTransportationServiceForParticipantAndDirection($index, DirectionMapper::OUTBOUND_BOOKING); - $inboundTransportation = $booking - ->getTransportationServiceForParticipantAndDirection($index, DirectionMapper::INBOUND_BOOKING); - - // Set new improved property names - $participantData->transportationOutbound = $outboundTransportation; - $participantData->transportationInbound = $inboundTransportation; - - // Pickup handling (currently only supports outbound pickup) - $pickup = $booking->getPickupForParticipant($index); - $participantData->pickup = $pickup; - - // Insurance - get insurance for participant - $insurance = $booking->getInsuranceForParticipant($index); - $participantData->insurance = $insurance; - - // Room assignment - extract from booking room mappings - $room = $booking->getRoomForParticipant($index); - $participantData->assignedRoomId = $room?->id; - - $instance->participants[$index] = $participantData; - } - - return $instance; - } - - public function isCanceled(): bool - { - return 'S' === $this->booking->status; - } - - public function isOption(): bool - { - return 'O' === $this->booking->status; - } - - public function getParticipants(): array - { - return $this->participants; - } - - public function hasParticipant(int $index): bool - { - return isset($this->participants[$index]); - } - - public function getParticipant(int $index): ?ParticipantDto - { - return $this->participants[$index] ?? null; - } - - /** - * Gets all selected rooms for the booking (edit context). - * - * In edit mode, rooms are fixed and not selectable - returns empty array. - * Participant count should be derived from actual participants, not room selections. - * - * @return array - */ - public function getSelectedRooms(): array - { - return []; - } -} diff --git a/src/Form/PaymentType.php b/src/Form/PaymentType.php index 4f1e6af..f0f2f24 100644 --- a/src/Form/PaymentType.php +++ b/src/Form/PaymentType.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace App\Form; use App\BusProNet\Constants; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use Carbon\CarbonImmutable; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; @@ -95,7 +95,7 @@ class PaymentType extends AbstractType * * Direct debit is only available if the travel starts at least 14 days from now. */ - private function isDebitAvailable(BookingCreateDto $bookingDto): bool + private function isDebitAvailable(BookingDto $bookingDto): bool { $travelStartDate = CarbonImmutable::instance($bookingDto->travel->dateFrom); $now = CarbonImmutable::now(); diff --git a/src/Form/Service/CreateFieldStateProvider.php b/src/Form/Service/CreateFieldStateProvider.php index bfd0563..e697e02 100644 --- a/src/Form/Service/CreateFieldStateProvider.php +++ b/src/Form/Service/CreateFieldStateProvider.php @@ -194,6 +194,16 @@ class CreateFieldStateProvider extends AbstractFieldStateProvider 'hidden' => FieldValueCondition::equals('parking', false), ]; + // Make mobile field required for applicant (participant index 0) + $this->fieldStateConditions['mobile'] = [ + 'required' => new ApplicantCondition(), + ]; + + // Make address field required for applicant (participant index 0) + $this->fieldStateConditions['address'] = [ + 'required' => new ApplicantCondition(), + ]; + // Example field state conditions would be registered here // For demonstration purposes, here are some example patterns: diff --git a/src/Form/Service/ParticipantFieldOptionsProvider.php b/src/Form/Service/ParticipantFieldOptionsProvider.php index 99e1cab..8b6de7b 100644 --- a/src/Form/Service/ParticipantFieldOptionsProvider.php +++ b/src/Form/Service/ParticipantFieldOptionsProvider.php @@ -8,9 +8,7 @@ use App\BusProNet\Constants; use App\BusProNet\Model\Pickup; use App\BusProNet\Model\Service; use App\BusProNet\Utility\DirectionMapper; -use App\Form\Model\BookingCreateDto; use App\Form\Model\BookingDto; -use App\Form\Model\BookingEditDto; use App\Form\Service\Abstract\AbstractFieldOptionsProvider; use App\Form\Service\Factory\ParticipantRoomChoiceLoaderFactory; use App\Service\InsuranceMatchingService; @@ -462,9 +460,9 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider * as the participant's selected skipass. This ensures rental equipment * is only available for the exact duration of the skipass. * - * @param array $rentals Array of rental Service objects to filter + * @param array $rentals Array of rental Service objects to filter * @param BookingDto $bookingDto The booking DTO containing participant data - * @param int $participantIndex Index of the participant to evaluate + * @param int $participantIndex Index of the participant to evaluate * * @return array Filtered array of rentals matching skipass duration */ @@ -587,15 +585,15 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider /** * Checks if a service should be rendered as read-only due to unavailability. * - * @param Service $service The service to check + * @param Service $service The service to check * @param BookingDto $bookingDto The booking DTO containing participant data - * @param int $participantIndex Index of the participant currently selecting services + * @param int $participantIndex Index of the participant currently selecting services * * @return bool True if the service should be read-only due to unavailability */ private function isServiceUnavailableForParticipant(Service $service, BookingDto $bookingDto, int $participantIndex): bool { - if (!$bookingDto instanceof BookingCreateDto) { + if (BookingDto::MODE_EDIT === $bookingDto->getMode()) { // For non-create workflows, don't apply availability restrictions return false; } @@ -610,9 +608,9 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider * If no age evaluator is configured or participant has no birth date, * returns empty array to be handled by field visibility conditions. * - * @param array $services Array of Service objects to filter + * @param array $services Array of Service objects to filter * @param BookingDto $bookingDto The booking DTO containing participant data - * @param int $participantIndex Index of the participant to evaluate + * @param int $participantIndex Index of the participant to evaluate * * @return array Filtered array of available services */ @@ -667,7 +665,7 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider * Gets eligible insurances for a participant based on eligibility criteria. * * @param BookingDto $bookingDto The booking DTO containing travel and participant data - * @param int $participantIndex The index of the participant to get eligible insurances for + * @param int $participantIndex The index of the participant to get eligible insurances for * * @return array Array of eligible insurance objects filtered by age, family status, and other constraints */ diff --git a/src/Form/Service/ParticipantInsuranceFieldHandler.php b/src/Form/Service/ParticipantInsuranceFieldHandler.php index 4c09cc5..85326e7 100644 --- a/src/Form/Service/ParticipantInsuranceFieldHandler.php +++ b/src/Form/Service/ParticipantInsuranceFieldHandler.php @@ -125,6 +125,10 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler $currentInsurance = $participant->insurance; $availableInsurances = $bookingDto->travel->insurances ?? []; + // Exclude complementary insurances from reassignment logic + // They are only available as part of packages and cannot be directly selected + $availableInsurances = array_filter($availableInsurances, fn ($insurance) => !$insurance->complementary); + // Determine if this is a new user selection or just form resubmission $isNewSelection = null !== $selectedInsuranceId && (null === $currentInsurance || !$this->isSameInsurance($selectedInsuranceId, $currentInsurance)); diff --git a/src/Service/BookingPriceCalculatorService.php b/src/Service/BookingPriceCalculatorService.php index bb4a436..6015fa2 100644 --- a/src/Service/BookingPriceCalculatorService.php +++ b/src/Service/BookingPriceCalculatorService.php @@ -8,7 +8,6 @@ use App\BusProNet\Constants; use App\BusProNet\Model\Insurance; use App\BusProNet\Model\Room; use App\BusProNet\Model\Service; -use App\Form\Model\BookingCreateDto; use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; @@ -57,10 +56,6 @@ class BookingPriceCalculatorService { $roomPricing = []; - if (false === $bookingDto instanceof BookingCreateDto) { - return $roomPricing; - } - $selectedRooms = $bookingDto->getSelectedRooms(); if (true === empty($selectedRooms)) { return $roomPricing; @@ -196,16 +191,12 @@ class BookingPriceCalculatorService * including their room allocation (full room price) and all selected services. * * @param BookingDto $bookingDto The booking data containing all participants - * @param int $participantIndex The index of the participant to calculate for + * @param int $participantIndex The index of the participant to calculate for * * @return float The total price for the specified participant */ public function calculateIndividualParticipantPrice(BookingDto $bookingDto, int $participantIndex): float { - if (false === $bookingDto instanceof BookingCreateDto) { - return 0.0; - } - $participant = $bookingDto->getParticipant($participantIndex); if (null === $participant) { return 0.0; @@ -237,10 +228,6 @@ class BookingPriceCalculatorService */ public function calculateAllParticipantIndividualPrices(BookingDto $bookingDto): array { - if (false === $bookingDto instanceof BookingCreateDto) { - return []; - } - $participantPrices = []; $participants = $bookingDto->getParticipants(); @@ -257,17 +244,17 @@ class BookingPriceCalculatorService * This method is used for insurance eligibility filtering to avoid circular dependency * where insurance selection affects travel price which affects insurance eligibility. * - * @param BookingDto $bookingDto The booking data containing all participants - * @param int $participantIndex The index of the participant to calculate for + * Only includes services where versicherungsberechnung='J' in the XML. Services with + * versicherungsberechnung='N' (like CO² compensation) are excluded from the calculation + * as per BPN API requirements for insurance tier determination. * - * @return float The total price for the specified participant excluding insurance + * @param BookingDto $bookingDto The booking data containing all participants + * @param int $participantIndex The index of the participant to calculate for + * + * @return float The total price for the specified participant excluding insurance and non-calculated services */ public function calculateIndividualParticipantPriceExcludingInsurance(BookingDto $bookingDto, int $participantIndex): float { - if (false === $bookingDto instanceof BookingCreateDto) { - return 0.0; - } - $participant = $bookingDto->getParticipant($participantIndex); if (null === $participant) { return 0.0; @@ -285,7 +272,8 @@ class BookingPriceCalculatorService } // Add service prices for this participant (excluding insurance) - $totalPrice += $this->calculateParticipantServiceTotal($participant, false); + // For insurance eligibility calculation, only include services marked with versicherungsberechnung='J' + $totalPrice += $this->calculateParticipantServiceTotal($participant, false, null, true); return $totalPrice; } @@ -528,23 +516,28 @@ class BookingPriceCalculatorService /** * Calculates the total service cost for a single participant. * - * @param ParticipantDto $participant The participant to calculate services for - * @param bool $includeInsurance Whether to include insurance pricing (default: true) - * @param BookingDto|null $bookingDto Optional booking DTO for bulk insurance resolution + * @param ParticipantDto $participant The participant to calculate services for + * @param bool $includeInsurance Whether to include insurance pricing (default: true) + * @param BookingDto|null $bookingDto Optional booking DTO for bulk insurance resolution + * @param bool $onlyInsuranceCalculationServices Only include services with includeInInsuranceCalculation=true (default: false) * * @return float The total service cost for this participant */ - private function calculateParticipantServiceTotal(ParticipantDto $participant, bool $includeInsurance = true, ?BookingDto $bookingDto = null): float + private function calculateParticipantServiceTotal(ParticipantDto $participant, bool $includeInsurance = true, ?BookingDto $bookingDto = null, bool $onlyInsuranceCalculationServices = false): float { $serviceTotal = 0.0; // Single service selections if (null !== $participant->skiPass && null !== $participant->skiPass->price) { - $serviceTotal += $participant->skiPass->price; + if (false === $onlyInsuranceCalculationServices || true === $participant->skiPass->includeInInsuranceCalculation) { + $serviceTotal += $participant->skiPass->price; + } } if (null !== $participant->rentalInsurance && null !== $participant->rentalInsurance->price) { - $serviceTotal += $participant->rentalInsurance->price; + if (false === $onlyInsuranceCalculationServices || true === $participant->rentalInsurance->includeInInsuranceCalculation) { + $serviceTotal += $participant->rentalInsurance->price; + } } // Get effective insurance (considering bulk insurance for dependent participants) @@ -555,11 +548,15 @@ class BookingPriceCalculatorService // Transportation services if (null !== $participant->transportationOutbound && null !== $participant->transportationOutbound->price) { - $serviceTotal += $participant->transportationOutbound->price; + if (false === $onlyInsuranceCalculationServices || true === $participant->transportationOutbound->includeInInsuranceCalculation) { + $serviceTotal += $participant->transportationOutbound->price; + } } if (null !== $participant->transportationInbound && null !== $participant->transportationInbound->price) { - $serviceTotal += $participant->transportationInbound->price; + if (false === $onlyInsuranceCalculationServices || true === $participant->transportationInbound->includeInInsuranceCalculation) { + $serviceTotal += $participant->transportationInbound->price; + } } if (null !== $participant->pickup && null !== $participant->pickup->price) { @@ -567,7 +564,9 @@ class BookingPriceCalculatorService } if (null !== $participant->parkingService && null !== $participant->parkingService->price) { - $serviceTotal += $participant->parkingService->price; + if (false === $onlyInsuranceCalculationServices || true === $participant->parkingService->includeInInsuranceCalculation) { + $serviceTotal += $participant->parkingService->price; + } } // Multiple service selections @@ -582,7 +581,9 @@ class BookingPriceCalculatorService if (true === is_array($serviceArray)) { foreach ($serviceArray as $service) { if ($service instanceof Service && null !== $service->price) { - $serviceTotal += $service->price; + if (false === $onlyInsuranceCalculationServices || true === $service->includeInInsuranceCalculation) { + $serviceTotal += $service->price; + } } } } @@ -594,7 +595,7 @@ class BookingPriceCalculatorService /** * Retrieves a room by ID from the booking's travel data. */ - private function getRoomById(BookingCreateDto $bookingDto, ?int $roomId): ?Room + private function getRoomById(BookingDto $bookingDto, ?int $roomId): ?Room { if (null === $roomId) { return null; @@ -644,7 +645,7 @@ class BookingPriceCalculatorService * This method is used for pricing calculations to show correct prices when bulk * insurance is enabled, even though the actual assignment happens in the processor. * - * @param ParticipantDto $participant The participant to get insurance for + * @param ParticipantDto $participant The participant to get insurance for * @param BookingDto|null $bookingDto Optional booking DTO for bulk insurance check * * @return Insurance|null The effective insurance for pricing purposes diff --git a/src/Service/BookingService.php b/src/Service/BookingService.php index 0f2641f..e530643 100644 --- a/src/Service/BookingService.php +++ b/src/Service/BookingService.php @@ -6,7 +6,6 @@ use App\BusProNet\Model\Room; use App\BusProNet\Model\Travel; use App\Exception\BookingSessionNotFoundException; use App\Exception\NoRoomsAvailableException; -use App\Form\Model\BookingCreateDto; use App\Form\Model\BookingDto; use App\Form\Model\RoomSelectionDto; use Symfony\Component\HttpFoundation\Request; @@ -32,7 +31,7 @@ class BookingService * is first loaded, before any HTMX modifications. This ensures accurate change * detection for room assignment resets. */ - public function getOrCreateBaselineSnapshot(Request $request, BookingCreateDto $bookingCreateDto): array + public function getOrCreateBaselineSnapshot(Request $request, BookingDto $bookingCreateDto): array { $baselineKey = self::BOOKING_CREATE_BASELINE_KEY; @@ -66,11 +65,11 @@ class BookingService * * @param Request $request The HTTP request containing session data * - * @return BookingCreateDto The booking DTO from session + * @return BookingDto The booking DTO from session * * @throws BookingSessionNotFoundException When no valid booking session exists */ - public function getOrCreateBookingCreateDto(Request $request): BookingCreateDto + public function getOrCreateBookingCreateDto(Request $request): BookingDto { $bookingCreateDto = $request->getSession()->get(self::BOOKING_CREATE_KEY); @@ -130,9 +129,9 @@ class BookingService * across multiple HTTP requests during the booking flow. * * @param Request $request The HTTP request with session - * @param BookingCreateDto $bookingCreateDto The booking DTO to persist + * @param BookingDto $bookingCreateDto The booking DTO to persist */ - public function saveBookingCreateDto(Request $request, BookingCreateDto $bookingCreateDto): void + public function saveBookingCreateDto(Request $request, BookingDto $bookingCreateDto): void { $this->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE); } @@ -164,11 +163,11 @@ class BookingService /** * Creates a fresh booking session with the provided travel parameters. * - * This method initializes a new BookingCreateDto with empty room selections + * This method initializes a new BookingDto with empty room selections * and saves it to the session. It's designed to be called from the clean * booking entry point without requiring UID parameters. */ - public function startFreshBooking(Request $request, int $dateId, int $hotelId, ?int $agencyId = null): BookingCreateDto + public function startFreshBooking(Request $request, int $dateId, int $hotelId, ?int $agencyId = null): BookingDto { $travelData = $this->travelDataService->getTravelData($dateId, $hotelId); if (null === $travelData) { @@ -188,7 +187,7 @@ class BookingService $availableRooms ); - $bookingCreateDto = new BookingCreateDto($travelData, $hotelId); + $bookingCreateDto = new BookingDto($travelData, $hotelId); $bookingCreateDto->roomSelections = $roomSelections; $bookingCreateDto->currentStep = 1; $bookingCreateDto->agencyId = $agencyId; @@ -344,9 +343,9 @@ class BookingService * invalid assignments. Called when users modify their room selections * in step 1 to ensure participants are reassigned appropriately. * - * @param BookingCreateDto $dto The booking DTO to reset assignments for + * @param BookingDto $dto The booking DTO to reset assignments for */ - public function resetParticipantAssignments(BookingCreateDto $dto): void + public function resetParticipantAssignments(BookingDto $dto): void { foreach ($dto->participants as $participant) { $participant->assignedRoomId = null; @@ -358,7 +357,7 @@ class BookingService * * @return array Array of [roomId, quantity] pairs */ - public function createRoomSelectionSnapshot(BookingCreateDto $dto): array + public function createRoomSelectionSnapshot(BookingDto $dto): array { return array_map( fn ($roomSelection) => [(int) $roomSelection->roomId, (int) $roomSelection->quantity], @@ -373,11 +372,11 @@ class BookingService * to detect changes that would require participant reassignment. * * @param array $oldSnapshot The baseline room selection snapshot - * @param BookingCreateDto $newDto The current booking DTO + * @param BookingDto $newDto The current booking DTO * * @return bool True if room selections have changed, false otherwise */ - public function hasRoomSelectionChanged(array $oldSnapshot, BookingCreateDto $newDto): bool + public function hasRoomSelectionChanged(array $oldSnapshot, BookingDto $newDto): bool { $newSnapshot = $this->createRoomSelectionSnapshot($newDto); @@ -395,9 +394,9 @@ class BookingService * have at least one skipass available for their age. Ineligible participants are * skipped to prevent their mandatory services from being included in pricing. * - * @param BookingCreateDto $bookingDto The booking DTO to update with mandatory services + * @param BookingDto $bookingDto The booking DTO to update with mandatory services */ - public function preselectMandatoryServices(BookingCreateDto $bookingDto): void + public function preselectMandatoryServices(BookingDto $bookingDto): void { $additionalServices = $bookingDto->travel->getAdditionalServicesBySubTypes(\App\BusProNet\Constants::TOKEN_ADDITIONAL); $mandatoryServices = array_filter($additionalServices, fn ($service) => true === $service->mandatory); diff --git a/src/Service/InsuranceMatchingService.php b/src/Service/InsuranceMatchingService.php index 3b4a2ff..61d904d 100644 --- a/src/Service/InsuranceMatchingService.php +++ b/src/Service/InsuranceMatchingService.php @@ -6,7 +6,6 @@ namespace App\Service; use App\BusProNet\Model\Insurance; use App\BusProNet\Traits\SortByPriceTrait; -use App\Form\Model\BookingCreateDto; use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; use App\Model\InsuranceEligibilityCriteria; @@ -31,9 +30,9 @@ class InsuranceMatchingService /** * Filters insurances based on participant and booking criteria. * - * @param array $insurances Available insurances to filter - * @param ParticipantDto $participant The participant to match insurances for - * @param BookingDto $booking The booking context for additional criteria + * @param array $insurances Available insurances to filter + * @param ParticipantDto $participant The participant to match insurances for + * @param BookingDto $booking The booking context for additional criteria * * @return array Filtered array of eligible insurances */ @@ -60,10 +59,10 @@ class InsuranceMatchingService * current insurance is no longer eligible. It finds the same insurance type * (subType + familyInsurance) with the correct price tier. * - * @param array $availableInsurances All available insurances - * @param Insurance $currentInsurance The currently selected insurance - * @param ParticipantDto $participant The participant to reassign for - * @param BookingDto $booking The booking context + * @param array $availableInsurances All available insurances + * @param Insurance $currentInsurance The currently selected insurance + * @param ParticipantDto $participant The participant to reassign for + * @param BookingDto $booking The booking context * * @return Insurance|null The reassigned insurance or null if no suitable match found */ @@ -90,9 +89,9 @@ class InsuranceMatchingService * (subType + familyInsurance) to all participants, but selects the appropriate price tier * based on each participant's individual travel price. * - * @param array $availableInsurances All available insurances - * @param Insurance $selectedInsurance The insurance selected by the applicant - * @param BookingDto $booking The booking with all participants + * @param array $availableInsurances All available insurances + * @param Insurance $selectedInsurance The insurance selected by the applicant + * @param BookingDto $booking The booking with all participants * * @return array Array indexed by participant index with assigned insurances * @@ -187,8 +186,8 @@ class InsuranceMatchingService */ private function checkFamilyInsuranceConstraints(Insurance $insurance, BookingDto $booking): bool { - // Family booking detection only available in BookingCreateDto - if (!$booking instanceof BookingCreateDto) { + // Family booking detection only available in create mode + if (BookingDto::MODE_EDIT === $booking->getMode()) { return true; // Skip family constraints for edit mode } @@ -316,14 +315,34 @@ class InsuranceMatchingService * affects travel price which then affects insurance eligibility. * * @param BookingDto $booking The booking to calculate price for - * @param int $participantIndex The participant index to calculate for + * @param int $participantIndex The participant index to calculate for * * @return float The total travel price for the participant excluding insurance */ private function calculateTravelPrice(BookingDto $booking, int $participantIndex): float { + $participant = $booking->getParticipant($participantIndex); + + // Debug logging to understand price calculation + if (null !== $participant && null !== $participant->insurance) { + error_log(sprintf( + '[InsuranceMatching] Participant %d: calculating travel price WITH insurance=%d (€%.2f) currently selected', + $participantIndex, + $participant->insurance->id, + $participant->insurance->price ?? 0.0 + )); + } + // Use the price calculator to get the participant's individual price excluding insurance - return $this->priceCalculatorService->calculateIndividualParticipantPriceExcludingInsurance($booking, $participantIndex); + $travelPrice = $this->priceCalculatorService->calculateIndividualParticipantPriceExcludingInsurance($booking, $participantIndex); + + error_log(sprintf( + '[InsuranceMatching] Participant %d: calculated travel price (excluding insurance) = €%.2f', + $participantIndex, + $travelPrice + )); + + return $travelPrice; } /** diff --git a/src/Service/RoomAssignmentService.php b/src/Service/RoomAssignmentService.php index 35021b3..65c78ea 100644 --- a/src/Service/RoomAssignmentService.php +++ b/src/Service/RoomAssignmentService.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace App\Service; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; /** * Handles automatic room assignment for booking participants. @@ -26,9 +26,9 @@ class RoomAssignmentService * - 2x "Doppelzimmer" (capacity 2) = participants 0-1 → room A, participants 2-3 → room A * - 1x "3-Bett-Zimmer" (capacity 3) = participants 4-6 → room B * - * @param BookingCreateDto $dto The booking DTO containing room selections and participants + * @param BookingDto $dto The booking DTO containing room selections and participants */ - public function assignParticipantsToRooms(BookingCreateDto $dto): void + public function assignParticipantsToRooms(BookingDto $dto): void { $participantIndex = 0; $selectedRooms = $dto->getSelectedRooms(); diff --git a/src/Service/ServiceAvailabilityCalculator.php b/src/Service/ServiceAvailabilityCalculator.php index 7b41bc4..9493629 100644 --- a/src/Service/ServiceAvailabilityCalculator.php +++ b/src/Service/ServiceAvailabilityCalculator.php @@ -7,7 +7,7 @@ namespace App\Service; use App\BusProNet\Constants; use App\BusProNet\Model\Service; use App\BusProNet\Utility\DirectionMapper; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; /** * Calculates dynamic service availability based on current booking selections. @@ -22,12 +22,12 @@ class ServiceAvailabilityCalculator /** * Calculate remaining availability for all services based on current participant selections. * - * @param BookingCreateDto $bookingDto The booking data with participant selections - * @param int $currentParticipantIndex The index of the participant currently filling the form + * @param BookingDto $bookingDto The booking data with participant selections + * @param int $currentParticipantIndex The index of the participant currently filling the form * * @return array Array mapping service IDs to remaining availability counts */ - public function calculateRemainingAvailability(BookingCreateDto $bookingDto, int $currentParticipantIndex): array + public function calculateRemainingAvailability(BookingDto $bookingDto, int $currentParticipantIndex): array { $serviceUsage = $this->calculateServiceUsage($bookingDto, $currentParticipantIndex); $remainingAvailability = []; @@ -52,13 +52,13 @@ class ServiceAvailabilityCalculator /** * Filter services array to only include those with remaining availability. * - * @param array $services Array of Service objects to filter - * @param BookingCreateDto $bookingDto The booking data with participant selections - * @param int $participantIndex The index of the participant currently filling the form + * @param array $services Array of Service objects to filter + * @param BookingDto $bookingDto The booking data with participant selections + * @param int $participantIndex The index of the participant currently filling the form * * @return array Filtered array containing only available services */ - public function filterAvailableServices(array $services, BookingCreateDto $bookingDto, int $participantIndex): array + public function filterAvailableServices(array $services, BookingDto $bookingDto, int $participantIndex): array { $remainingAvailability = $this->calculateRemainingAvailability($bookingDto, $participantIndex); @@ -76,13 +76,13 @@ class ServiceAvailabilityCalculator /** * Check if a specific service is unavailable (sold out) for the current participant. * - * @param int $serviceId The ID of the service to check - * @param BookingCreateDto $bookingDto The booking data with participant selections - * @param int $participantIndex The index of the participant currently filling the form + * @param int $serviceId The ID of the service to check + * @param BookingDto $bookingDto The booking data with participant selections + * @param int $participantIndex The index of the participant currently filling the form * * @return bool True if the service is unavailable (has availability limit and remaining is 0) */ - public function isServiceUnavailable(int $serviceId, BookingCreateDto $bookingDto, int $participantIndex): bool + public function isServiceUnavailable(int $serviceId, BookingDto $bookingDto, int $participantIndex): bool { $allServices = $this->getAllServicesFromTravel($bookingDto); $service = null; @@ -107,12 +107,12 @@ class ServiceAvailabilityCalculator /** * Calculate how many times each service has been selected by other participants. * - * @param BookingCreateDto $bookingDto The booking data with participant selections - * @param int $currentParticipantIndex The index of the participant currently filling the form + * @param BookingDto $bookingDto The booking data with participant selections + * @param int $currentParticipantIndex The index of the participant currently filling the form * * @return array Array mapping service IDs to usage counts */ - private function calculateServiceUsage(BookingCreateDto $bookingDto, int $currentParticipantIndex): array + private function calculateServiceUsage(BookingDto $bookingDto, int $currentParticipantIndex): array { $serviceUsage = []; @@ -187,11 +187,11 @@ class ServiceAvailabilityCalculator /** * Get all services from the travel data for availability calculation. * - * @param BookingCreateDto $bookingDto The booking data containing travel information + * @param BookingDto $bookingDto The booking data containing travel information * * @return array Array of all available services */ - private function getAllServicesFromTravel(BookingCreateDto $bookingDto): array + private function getAllServicesFromTravel(BookingDto $bookingDto): array { $allServices = []; diff --git a/src/Validator/Constraints/BookingValidator.php b/src/Validator/Constraints/BookingValidator.php index 725a537..ff40117 100644 --- a/src/Validator/Constraints/BookingValidator.php +++ b/src/Validator/Constraints/BookingValidator.php @@ -5,7 +5,7 @@ namespace App\Validator\Constraints; use App\BusProNet\ApiClient; use App\BusProNet\Model\BookingUpdate; use App\BusProNet\Model\Notification; -use App\Form\Model\BookingEditDto; +use App\Form\Model\BookingDto; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -17,7 +17,7 @@ class BookingValidator extends ConstraintValidator public function validate(mixed $value, Constraint $constraint): void { - /** @var BookingEditDto $booking */ + /** @var BookingDto $booking */ $bookingData = $value; $result = $this->apiClient->updateBooking($bookingData); diff --git a/templates/booking/create_step_2.html.twig b/templates/booking/create_step_2.html.twig index e9a94d9..5ef6eb1 100644 --- a/templates/booking/create_step_2.html.twig +++ b/templates/booking/create_step_2.html.twig @@ -216,9 +216,8 @@ {% set applicantInsurance = form.vars.data.participants[0].insurance %} {% if applicantInsurance %} {{ applicantInsurance.label }} - {% set participantPrice = participantPrices[loop.index0] %} - {% if participantPrice.insurance and participantPrice.insurance > 0 %} - (€{{ participantPrice.insurance|number_format(2, ',', '.') }}) + {% if applicantInsurance.price and applicantInsurance.price > 0 %} + (€{{ applicantInsurance.price|number_format(2, ',', '.') }}) {% endif %} – wie Anmelder {% else %} diff --git a/tests/BusProNet/DataProcessor/BookingDataProcessorTest.php b/tests/BusProNet/DataProcessor/BookingDataProcessorTest.php index 7e78016..a5e0b7a 100644 --- a/tests/BusProNet/DataProcessor/BookingDataProcessorTest.php +++ b/tests/BusProNet/DataProcessor/BookingDataProcessorTest.php @@ -14,7 +14,7 @@ use App\BusProNet\Model\Pickup; use App\BusProNet\Model\Room; use App\BusProNet\Model\Service; use App\BusProNet\Model\Travel; -use App\Form\Model\BookingEditDto; +use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; use PHPUnit\Framework\TestCase; @@ -210,29 +210,31 @@ class BookingDataProcessorTest extends TestCase $this->assertArrayNotHasKey('zustiege', $result); } - private function createCompleteFormData(): BookingEditDto + private function createCompleteFormData(): BookingDto { - $formData = new BookingEditDto($this->createMockBooking(), $this->createMockTravel()); - $formData->participants = [ + $bookingDto = new BookingDto($this->createMockTravel(), 1); + $bookingDto->booking = $this->createMockBooking(); + $bookingDto->participants = [ $this->createMockParticipantDto(0, 'F'), $this->createMockParticipantDto(1, 'F'), ]; - return $formData; + return $bookingDto; } - private function createFormDataWithCanceledParticipant(): BookingEditDto + private function createFormDataWithCanceledParticipant(): BookingDto { - $formData = new BookingEditDto($this->createMockBooking(), $this->createMockTravel()); - $formData->participants = [ + $bookingDto = new BookingDto($this->createMockTravel(), 1); + $bookingDto->booking = $this->createMockBooking(); + $bookingDto->participants = [ $this->createMockParticipantDto(0, 'F'), $this->createMockParticipantDto(1, 'S'), // Canceled ]; - return $formData; + return $bookingDto; } - private function createFormDataWithAdditionalServices(): BookingEditDto + private function createFormDataWithAdditionalServices(): BookingDto { $formData = $this->createCompleteFormData(); @@ -243,7 +245,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithTransportation(): BookingEditDto + private function createFormDataWithTransportation(): BookingDto { $formData = $this->createCompleteFormData(); @@ -254,7 +256,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithBusPickup(): BookingEditDto + private function createFormDataWithBusPickup(): BookingDto { $formData = $this->createCompleteFormData(); @@ -267,7 +269,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithNonBusTransportation(): BookingEditDto + private function createFormDataWithNonBusTransportation(): BookingDto { $formData = $this->createCompleteFormData(); @@ -279,7 +281,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithUnusedServices(): BookingEditDto + private function createFormDataWithUnusedServices(): BookingDto { $formData = $this->createCompleteFormData(); @@ -289,7 +291,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithUpdatedPersonalData(): BookingEditDto + private function createFormDataWithUpdatedPersonalData(): BookingDto { $formData = $this->createCompleteFormData(); @@ -302,7 +304,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithInactiveParticipant(): BookingEditDto + private function createFormDataWithInactiveParticipant(): BookingDto { $formData = $this->createCompleteFormData(); @@ -318,7 +320,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataForApplicantSync(): BookingEditDto + private function createFormDataForApplicantSync(): BookingDto { $formData = $this->createCompleteFormData(); @@ -330,7 +332,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithBankAccount(): BookingEditDto + private function createFormDataWithBankAccount(): BookingDto { $formData = $this->createCompleteFormData(); @@ -345,7 +347,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithoutBankAccount(): BookingEditDto + private function createFormDataWithoutBankAccount(): BookingDto { $formData = $this->createCompleteFormData(); $formData->booking->bankAccount = null; @@ -353,7 +355,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithRooms(): BookingEditDto + private function createFormDataWithRooms(): BookingDto { $formData = $this->createCompleteFormData(); @@ -371,7 +373,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithoutExistingCommunication(): BookingEditDto + private function createFormDataWithoutExistingCommunication(): BookingDto { $formData = $this->createCompleteFormData(); @@ -384,7 +386,7 @@ class BookingDataProcessorTest extends TestCase return $formData; } - private function createFormDataWithoutPickups(): BookingEditDto + private function createFormDataWithoutPickups(): BookingDto { $formData = $this->createCompleteFormData(); $formData->booking->pickupsOutbound = []; diff --git a/tests/Form/Service/Condition/InsuranceMutabilityConditionTest.php b/tests/Form/Service/Condition/InsuranceMutabilityConditionTest.php index 9db25c0..95614a9 100644 --- a/tests/Form/Service/Condition/InsuranceMutabilityConditionTest.php +++ b/tests/Form/Service/Condition/InsuranceMutabilityConditionTest.php @@ -6,8 +6,7 @@ namespace App\Tests\Form\Service\Condition; use App\BusProNet\Model\Booking; use App\BusProNet\Model\Travel; -use App\Form\Model\BookingCreateDto; -use App\Form\Model\BookingEditDto; +use App\Form\Model\BookingDto; use App\Form\Service\Condition\InsuranceMutabilityCondition; use Carbon\Carbon; use PHPUnit\Framework\TestCase; @@ -35,7 +34,7 @@ class InsuranceMutabilityConditionTest extends TestCase $travel = new Travel(); $travel->dateFrom = new \DateTimeImmutable('+10 days'); - $bookingDto = new BookingCreateDto($travel, 123); + $bookingDto = new BookingDto($travel, 123); $result = $this->condition->evaluate($bookingDto, 0, []); @@ -154,7 +153,7 @@ class InsuranceMutabilityConditionTest extends TestCase $this->assertStringContainsString('3', $result); } - private function createEditDto(\DateTimeImmutable $travelDate, \DateTimeImmutable $bookingDate): BookingEditDto + private function createEditDto(\DateTimeImmutable $travelDate, \DateTimeImmutable $bookingDate): BookingDto { $booking = new Booking(); $booking->bookingDate = $bookingDate; @@ -162,6 +161,9 @@ class InsuranceMutabilityConditionTest extends TestCase $travel = new Travel(); $travel->dateFrom = $travelDate; - return new BookingEditDto($booking, $travel); + $bookingDto = new BookingDto($travel, 1); + $bookingDto->booking = $booking; + + return $bookingDto; } } diff --git a/tests/Form/Service/ParticipantInsuranceFieldHandlerTest.php b/tests/Form/Service/ParticipantInsuranceFieldHandlerTest.php index 86e4602..4d952a1 100644 --- a/tests/Form/Service/ParticipantInsuranceFieldHandlerTest.php +++ b/tests/Form/Service/ParticipantInsuranceFieldHandlerTest.php @@ -6,7 +6,7 @@ namespace App\Tests\Form\Service; use App\BusProNet\Model\Insurance; use App\BusProNet\Model\Travel; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; use App\Form\Service\ParticipantInsuranceFieldHandler; use App\Service\InsuranceMatchingService; @@ -229,8 +229,8 @@ class ParticipantInsuranceFieldHandlerTest extends TestCase return $insurance; } - private function createMockBookingDto(): BookingCreateDto + private function createMockBookingDto(): BookingDto { - return $this->createMock(BookingCreateDto::class); + return $this->createMock(BookingDto::class); } } diff --git a/tests/Form/Service/ParticipantLicensePlateFieldHandlerTest.php b/tests/Form/Service/ParticipantLicensePlateFieldHandlerTest.php index a2dfa78..03f1e04 100644 --- a/tests/Form/Service/ParticipantLicensePlateFieldHandlerTest.php +++ b/tests/Form/Service/ParticipantLicensePlateFieldHandlerTest.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace App\Tests\Form\Service; use App\BusProNet\Model\Travel; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; use App\Form\Service\ParticipantLicensePlateFieldHandler; use PHPUnit\Framework\TestCase; @@ -38,7 +38,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase public function testProcessFieldWithoutParticipant(): void { $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $submittedData = ['licensePlate' => 'AB-CD 123']; $this->handler->processField($submittedData, $bookingDto, 0); @@ -54,7 +54,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->licensePlate = 'AB-CD 123'; // Should be cleared $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $submittedData = ['licensePlate' => 'XY-ZZ 999']; @@ -70,7 +70,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->parking = true; // Parking selected $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $submittedData = ['licensePlate' => 'AB-CD 123']; @@ -86,7 +86,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->parking = true; // Parking selected $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $submittedData = ['licensePlate' => '']; @@ -102,7 +102,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->parking = true; // Parking selected $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $submittedData = ['licensePlate' => null]; @@ -118,7 +118,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->parking = true; // Parking selected $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $submittedData = ['licensePlate' => ' AB-CD 123 ']; @@ -134,7 +134,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->parking = true; // Parking selected $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $submittedData = ['licensePlate' => ' ']; @@ -150,7 +150,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->parking = true; // Parking selected $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; // Test with integer value @@ -170,7 +170,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant->parking = true; // Parking selected $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $submittedData = []; // No licensePlate field @@ -189,7 +189,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase $participant2->parking = true; $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant1, $participant2]; $submittedData = ['licensePlate' => 'AB-CD 123']; diff --git a/tests/Service/BookingPriceCalculatorServiceTest.php b/tests/Service/BookingPriceCalculatorServiceTest.php index 92b304a..b36a76b 100644 --- a/tests/Service/BookingPriceCalculatorServiceTest.php +++ b/tests/Service/BookingPriceCalculatorServiceTest.php @@ -7,7 +7,7 @@ namespace App\Tests\Service; use App\BusProNet\Model\Room; use App\BusProNet\Model\Service; use App\BusProNet\Model\Travel; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; use App\Form\Model\RoomSelectionDto; use App\Service\BookingPriceCalculatorService; @@ -38,7 +38,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $roomSelection->roomId = 1; $roomSelection->quantity = 2; // 2 rooms selected - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; // Test the calculation @@ -70,7 +70,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $roomSelection->roomId = 2; $roomSelection->quantity = 1; // 1 room selected - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; // Test the calculation @@ -112,7 +112,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $doubleRoomSelection->roomId = 2; $doubleRoomSelection->quantity = 2; // 2 double rooms - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$singleRoomSelection, $doubleRoomSelection]; // Test the calculation @@ -155,7 +155,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $roomSelection->roomId = 1; $roomSelection->quantity = 1; - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $result = $this->service->calculateRoomPricing($bookingDto); @@ -179,7 +179,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $roomSelection->roomId = 1; $roomSelection->quantity = 0; // Zero quantity - not selected - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->roomSelections = [$roomSelection]; $result = $this->service->calculateRoomPricing($bookingDto); @@ -212,7 +212,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $participant->skiPass = $skiPass; $participant->courses = [$course]; - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0); @@ -234,7 +234,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $participant->assignedRoomId = null; // No room assigned $participant->skiPass = $skiPass; - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant]; $result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0); @@ -246,7 +246,7 @@ class BookingPriceCalculatorServiceTest extends TestCase public function testCalculateIndividualParticipantPriceForNonExistentParticipant(): void { $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = []; $result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0); @@ -290,7 +290,7 @@ class BookingPriceCalculatorServiceTest extends TestCase $participant3 = new ParticipantDto(); $participant3->assignedRoomId = null; // No room assigned - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = [$participant1, $participant2, $participant3]; $result = $this->service->calculateAllParticipantIndividualPrices($bookingDto); @@ -308,7 +308,7 @@ class BookingPriceCalculatorServiceTest extends TestCase public function testCalculateAllParticipantIndividualPricesWithEmptyBooking(): void { $travel = new Travel(); - $bookingDto = new BookingCreateDto($travel, 1); + $bookingDto = new BookingDto($travel, 1); $bookingDto->participants = []; $result = $this->service->calculateAllParticipantIndividualPrices($bookingDto); diff --git a/tests/Service/InsuranceMatchingServiceTest.php b/tests/Service/InsuranceMatchingServiceTest.php index 9b0c747..da2e9ae 100644 --- a/tests/Service/InsuranceMatchingServiceTest.php +++ b/tests/Service/InsuranceMatchingServiceTest.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace App\Tests\Service; use App\BusProNet\Model\Insurance; -use App\Form\Model\BookingCreateDto; +use App\Form\Model\BookingDto; use App\Form\Model\ParticipantDto; use App\Service\BookingPriceCalculatorService; use App\Service\InsuranceMatchingService; @@ -254,10 +254,10 @@ class InsuranceMatchingServiceTest extends TestCase return $participant; } - private function createBooking(string $travelDateFrom, string $travelDateTo): BookingCreateDto + private function createBooking(string $travelDateFrom, string $travelDateTo): BookingDto { $travel = $this->createTravel($travelDateFrom, $travelDateTo); - $booking = new BookingCreateDto($travel, 1); + $booking = new BookingDto($travel, 1); return $booking; }