wip: modernized edit flow, fix insurance tier calculation
This commit is contained in:
@@ -15,9 +15,7 @@ use App\BusProNet\Model\PersonalData;
|
|||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\BusProNet\Traits\ApiClientTrait;
|
use App\BusProNet\Traits\ApiClientTrait;
|
||||||
use App\BusProNet\XmlParser\ApiResponseParser;
|
use App\BusProNet\XmlParser\ApiResponseParser;
|
||||||
use App\Form\Model\BookingCreateDto;
|
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\BookingEditDto;
|
|
||||||
use App\Form\Model\RegistrationDto;
|
use App\Form\Model\RegistrationDto;
|
||||||
use League\Flysystem\FilesystemException;
|
use League\Flysystem\FilesystemException;
|
||||||
use League\Flysystem\FilesystemOperator;
|
use League\Flysystem\FilesystemOperator;
|
||||||
@@ -215,14 +213,14 @@ class ApiClient
|
|||||||
* First phase of the two-phase booking process. Validates all booking data
|
* First phase of the two-phase booking process. Validates all booking data
|
||||||
* and returns pricing information without creating an actual booking.
|
* and returns pricing information without creating an actual booking.
|
||||||
*
|
*
|
||||||
* @param BookingCreateDto $bookingDto The booking creation form data
|
* @param BookingDto $bookingDto The booking creation form data
|
||||||
* @param bool $debug Enable debug mode (XML dumps)
|
* @param bool $debug Enable debug mode (XML dumps)
|
||||||
*
|
*
|
||||||
* @return Notification|BookingResponse Notification on error, BookingResponse on success
|
* @return Notification|BookingResponse Notification on error, BookingResponse on success
|
||||||
*
|
*
|
||||||
* @throws ApiClientException If the API request fails
|
* @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');
|
$payload = $this->bookingDataProcessor->createBookingRequestPayload($bookingDto, 'Anfrage');
|
||||||
|
|
||||||
@@ -242,14 +240,14 @@ class ApiClient
|
|||||||
* Second phase of the two-phase booking process. Creates the actual booking
|
* Second phase of the two-phase booking process. Creates the actual booking
|
||||||
* after successful inquiry validation.
|
* after successful inquiry validation.
|
||||||
*
|
*
|
||||||
* @param BookingCreateDto $bookingDto The booking creation form data
|
* @param BookingDto $bookingDto The booking creation form data
|
||||||
* @param bool $debug Enable debug mode (XML dumps)
|
* @param bool $debug Enable debug mode (XML dumps)
|
||||||
*
|
*
|
||||||
* @return Notification|BookingResponse Notification on error, BookingResponse with booking number on success
|
* @return Notification|BookingResponse Notification on error, BookingResponse with booking number on success
|
||||||
*
|
*
|
||||||
* @throws ApiClientException If the API request fails
|
* @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');
|
$payload = $this->bookingDataProcessor->createBookingRequestPayload($bookingDto, 'Buchung');
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ use App\BusProNet\Model\PersonalData;
|
|||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\BusProNet\Utility\DirectionMapper;
|
use App\BusProNet\Utility\DirectionMapper;
|
||||||
use App\Form\Model\BankAccountDto;
|
use App\Form\Model\BankAccountDto;
|
||||||
use App\Form\Model\BookingCreateDto;
|
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\BookingEditDto;
|
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use App\Service\InsuranceMatchingService;
|
use App\Service\InsuranceMatchingService;
|
||||||
|
|
||||||
@@ -39,6 +37,12 @@ class BookingDataProcessor
|
|||||||
*
|
*
|
||||||
* Extracts all service selections from the booking entity and assigns them
|
* Extracts all service selections from the booking entity and assigns them
|
||||||
* to participant DTOs, creating a unified data structure identical to create mode.
|
* 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
|
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.
|
* Insurance can be either individual or package-based, with automatic price-tier adjustment.
|
||||||
*
|
*
|
||||||
* @param ParticipantDto $participant The participant data from the form
|
* @param ParticipantDto $participant The participant data from the form
|
||||||
* @param Booking $bookingData The booking data object to update
|
* @param Booking $bookingData The booking data object to update
|
||||||
* @param Travel $travelData The travel data containing available insurances
|
* @param Travel $travelData The travel data containing available insurances
|
||||||
*/
|
*/
|
||||||
private function processInsurance(ParticipantDto $participant, Booking $bookingData, Travel $travelData): void
|
private function processInsurance(ParticipantDto $participant, Booking $bookingData, Travel $travelData): void
|
||||||
{
|
{
|
||||||
@@ -654,7 +658,7 @@ class BookingDataProcessor
|
|||||||
* ('Anfrage') or a final booking commit ('Buchung').
|
* ('Anfrage') or a final booking commit ('Buchung').
|
||||||
*
|
*
|
||||||
* @param BookingDto $bookingDto The booking creation form data
|
* @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
|
* @return array The structured payload array for BusProNet API submission
|
||||||
*/
|
*/
|
||||||
@@ -822,11 +826,11 @@ class BookingDataProcessor
|
|||||||
* - abreise (departure date)
|
* - abreise (departure date)
|
||||||
* - anzahl (number of rooms of this type booked)
|
* - anzahl (number of rooms of this type booked)
|
||||||
*
|
*
|
||||||
* @param array $payload The payload array to modify
|
* @param array $payload The payload array to modify
|
||||||
* @param array $roomMap Map of room ID to participant IDs
|
* @param array $roomMap Map of room ID to participant IDs
|
||||||
* @param BookingCreateDto $bookingDto The booking data for accessing room details and quantities
|
* @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)) {
|
if (empty($roomMap)) {
|
||||||
return;
|
return;
|
||||||
@@ -870,7 +874,7 @@ class BookingDataProcessor
|
|||||||
*
|
*
|
||||||
* @return array<string, array<int>> Map of room ID to participant IDs
|
* @return array<string, array<int>> Map of room ID to participant IDs
|
||||||
*/
|
*/
|
||||||
private function collectRoomMappings(BookingCreateDto $bookingDto): array
|
private function collectRoomMappings(BookingDto $bookingDto): array
|
||||||
{
|
{
|
||||||
$roomMap = [];
|
$roomMap = [];
|
||||||
|
|
||||||
@@ -893,7 +897,7 @@ class BookingDataProcessor
|
|||||||
*
|
*
|
||||||
* @return array<string, array<int>> Map of service ID to participant IDs
|
* @return array<string, array<int>> Map of service ID to participant IDs
|
||||||
*/
|
*/
|
||||||
private function collectServiceMappings(BookingCreateDto $bookingDto): array
|
private function collectServiceMappings(BookingDto $bookingDto): array
|
||||||
{
|
{
|
||||||
$serviceMap = [];
|
$serviceMap = [];
|
||||||
|
|
||||||
@@ -944,7 +948,7 @@ class BookingDataProcessor
|
|||||||
*
|
*
|
||||||
* @return array<string, array<int>> Map of transportation service ID to participant IDs
|
* @return array<string, array<int>> Map of transportation service ID to participant IDs
|
||||||
*/
|
*/
|
||||||
private function collectTransportationMappings(BookingCreateDto $bookingDto): array
|
private function collectTransportationMappings(BookingDto $bookingDto): array
|
||||||
{
|
{
|
||||||
$transportationMap = [];
|
$transportationMap = [];
|
||||||
|
|
||||||
@@ -971,7 +975,7 @@ class BookingDataProcessor
|
|||||||
*
|
*
|
||||||
* @return array<string, array<int>> Map of pickup ID to participant IDs
|
* @return array<string, array<int>> Map of pickup ID to participant IDs
|
||||||
*/
|
*/
|
||||||
private function collectPickupMappings(BookingCreateDto $bookingDto): array
|
private function collectPickupMappings(BookingDto $bookingDto): array
|
||||||
{
|
{
|
||||||
$pickupMap = [];
|
$pickupMap = [];
|
||||||
|
|
||||||
@@ -993,7 +997,7 @@ class BookingDataProcessor
|
|||||||
*
|
*
|
||||||
* @return array<string, array<int>> Map of insurance ID to participant IDs
|
* @return array<string, array<int>> Map of insurance ID to participant IDs
|
||||||
*/
|
*/
|
||||||
private function collectInsuranceMappings(BookingCreateDto $bookingDto): array
|
private function collectInsuranceMappings(BookingDto $bookingDto): array
|
||||||
{
|
{
|
||||||
$insuranceMap = [];
|
$insuranceMap = [];
|
||||||
|
|
||||||
@@ -1033,7 +1037,12 @@ class BookingDataProcessor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all available insurances from travel data
|
// 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
|
// Use InsuranceMatchingService for proper type-based assignment with price tier matching
|
||||||
$assignments = $this->insuranceMatchingService->batchAssignInsuranceToParticipants(
|
$assignments = $this->insuranceMatchingService->batchAssignInsuranceToParticipants(
|
||||||
@@ -1055,7 +1064,7 @@ class BookingDataProcessor
|
|||||||
|
|
||||||
// In edit mode: only apply bulk insurance if participant has no insurance
|
// In edit mode: only apply bulk insurance if participant has no insurance
|
||||||
// This respects the rule that once assigned, insurance cannot be changed
|
// 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
|
continue; // Skip participants with existing insurance assignment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,4 +96,14 @@ class Service
|
|||||||
|
|
||||||
#[Groups(['api:single', 'api:list'])]
|
#[Groups(['api:single', 'api:list'])]
|
||||||
public ?string $description = null;
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ class TravelParser extends AbstractParser
|
|||||||
// Parse age constraints
|
// Parse age constraints
|
||||||
$this->parseServiceAgeConstraints($serviceNode, $service);
|
$this->parseServiceAgeConstraints($serviceNode, $service);
|
||||||
|
|
||||||
|
// Parse insurance calculation flag
|
||||||
|
$service->includeInInsuranceCalculation = $this->stringToBool($serviceNode->attr('versicherungsberechnung'));
|
||||||
|
|
||||||
$additionalServices[$serviceId] = $service;
|
$additionalServices[$serviceId] = $service;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -192,6 +195,9 @@ class TravelParser extends AbstractParser
|
|||||||
$service->dayTime = (new DayTimeUtility())->mapTime($timeFrom);
|
$service->dayTime = (new DayTimeUtility())->mapTime($timeFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse insurance calculation flag
|
||||||
|
$service->includeInInsuranceCalculation = $this->stringToBool($serviceNode->attr('versicherungsberechnung'));
|
||||||
|
|
||||||
$transportationServices[$serviceId] = $service;
|
$transportationServices[$serviceId] = $service;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Controller\Booking;
|
namespace App\Controller\Booking;
|
||||||
|
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
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
|
* @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
|
// Allow access to current step or any previous step
|
||||||
if ($expectedStep > $bookingCreateDto->currentStep) {
|
if ($expectedStep > $bookingCreateDto->currentStep) {
|
||||||
@@ -36,7 +36,7 @@ trait BookingCreateTrait
|
|||||||
/**
|
/**
|
||||||
* Redirects to the current step based on the DTO's currentStep.
|
* 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) {
|
$route = match ($bookingCreateDto->currentStep) {
|
||||||
2 => 'app_booking_create_step_2',
|
2 => 'app_booking_create_step_2',
|
||||||
@@ -51,7 +51,7 @@ trait BookingCreateTrait
|
|||||||
/**
|
/**
|
||||||
* Returns the total number of participants based on room selections.
|
* Returns the total number of participants based on room selections.
|
||||||
*/
|
*/
|
||||||
private function getParticipantsCount(BookingCreateDto $bookingCreateDto): int
|
private function getParticipantsCount(BookingDto $bookingCreateDto): int
|
||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
->bookingService
|
->bookingService
|
||||||
@@ -63,7 +63,7 @@ trait BookingCreateTrait
|
|||||||
*
|
*
|
||||||
* @return array<string, mixed> Array containing all variables needed for the summary partial
|
* @return array<string, mixed> 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);
|
$participantsCount = $this->getParticipantsCount($bookingCreateDto);
|
||||||
$summary = $this->bookingService->getRoomSummaryAndParticipantCount($bookingCreateDto);
|
$summary = $this->bookingService->getRoomSummaryAndParticipantCount($bookingCreateDto);
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ use App\Exception\HotelNotFoundException;
|
|||||||
use App\Exception\HotelNotInTravelException;
|
use App\Exception\HotelNotInTravelException;
|
||||||
use App\Exception\NoRoomsAvailableException;
|
use App\Exception\NoRoomsAvailableException;
|
||||||
use App\Exception\TravelNotFoundException;
|
use App\Exception\TravelNotFoundException;
|
||||||
|
use App\Form\Model\BookingDto;
|
||||||
use App\Service\BookingService;
|
use App\Service\BookingService;
|
||||||
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ trait BookingExceptionHandlerTrait
|
|||||||
* Handles all booking-related exceptions and provides appropriate user feedback
|
* Handles all booking-related exceptions and provides appropriate user feedback
|
||||||
* by redirecting to the error page with flash messages.
|
* 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 {
|
try {
|
||||||
return $bookingService->getOrCreateBookingCreateDto($request);
|
return $bookingService->getOrCreateBookingCreateDto($request);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace App\Controller\Booking;
|
|||||||
|
|
||||||
use App\Controller\Traits\HtmxControllerTrait;
|
use App\Controller\Traits\HtmxControllerTrait;
|
||||||
use App\Form\BookingCreateStep2Type;
|
use App\Form\BookingCreateStep2Type;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use App\Service\BookingPriceCalculatorService;
|
use App\Service\BookingPriceCalculatorService;
|
||||||
use App\Service\BookingService;
|
use App\Service\BookingService;
|
||||||
@@ -67,7 +67,7 @@ class CreateStep2Controller extends AbstractController
|
|||||||
// Pre-select mandatory services for participants with birth dates
|
// Pre-select mandatory services for participants with birth dates
|
||||||
$this->bookingService->preselectMandatoryServices($bookingCreateDto);
|
$this->bookingService->preselectMandatoryServices($bookingCreateDto);
|
||||||
|
|
||||||
$this->bookingService->saveBookingCreateDto($request, $bookingCreateDto);
|
$this->bookingService->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE);
|
||||||
|
|
||||||
$form = $this->createForm(BookingCreateStep2Type::class, $bookingCreateDto, [
|
$form = $this->createForm(BookingCreateStep2Type::class, $bookingCreateDto, [
|
||||||
'attr' => ['novalidate' => 'novalidate'],
|
'attr' => ['novalidate' => 'novalidate'],
|
||||||
@@ -78,7 +78,7 @@ class CreateStep2Controller extends AbstractController
|
|||||||
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$bookingCreateDto->currentStep = 3;
|
$bookingCreateDto->currentStep = 3;
|
||||||
$this->bookingService->saveBookingCreateDto($request, $bookingCreateDto);
|
$this->bookingService->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE);
|
||||||
|
|
||||||
return $this->redirectToRoute('app_booking_create_step_3');
|
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
|
// Pre-select mandatory services after form processing but before pricing calculation
|
||||||
$this->bookingService->preselectMandatoryServices($bookingCreateDto);
|
$this->bookingService->preselectMandatoryServices($bookingCreateDto);
|
||||||
|
|
||||||
$this->bookingService->saveBookingCreateDto($request, $bookingCreateDto);
|
$this->bookingService->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE);
|
||||||
|
|
||||||
// Collect notifications from all participants
|
// Collect notifications from all participants
|
||||||
$notifications = $this->collectParticipantNotifications($bookingCreateDto);
|
$notifications = $this->collectParticipantNotifications($bookingCreateDto);
|
||||||
@@ -173,9 +173,9 @@ class CreateStep2Controller extends AbstractController
|
|||||||
* based on room selections. Preserves existing participant data when possible
|
* based on room selections. Preserves existing participant data when possible
|
||||||
* and assigns proper index values.
|
* 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);
|
$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.
|
* 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.
|
* 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;
|
$dateId = $bookingCreateDto->travel->id;
|
||||||
|
|
||||||
$availabilities = $this->travelDataService->getAvailabilityDataCached($dateId);
|
$availabilities = $this->travelDataService->getAvailabilityData($dateId, true);
|
||||||
|
|
||||||
if (null !== $availabilities) {
|
if (null !== $availabilities) {
|
||||||
$this->travelDataService->patchAvailabilities($bookingCreateDto->travel, $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
|
* 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.
|
* 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
|
// Check if any participants need room assignment
|
||||||
$needsAssignment = false;
|
$needsAssignment = false;
|
||||||
@@ -235,11 +235,11 @@ class CreateStep2Controller extends AbstractController
|
|||||||
/**
|
/**
|
||||||
* Collects all notifications from participants and clears them.
|
* 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{type: string, message: string}> Array of notification messages
|
* @return array<array{type: string, message: string}> Array of notification messages
|
||||||
*/
|
*/
|
||||||
private function collectParticipantNotifications(BookingCreateDto $bookingCreateDto): array
|
private function collectParticipantNotifications(BookingDto $bookingCreateDto): array
|
||||||
{
|
{
|
||||||
$notifications = [];
|
$notifications = [];
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Form;
|
namespace App\Form;
|
||||||
|
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
@@ -30,7 +30,7 @@ class BookingCreateStep1Type extends AbstractType
|
|||||||
public function configureOptions(OptionsResolver $resolver): void
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'data_class' => BookingCreateDto::class,
|
'data_class' => BookingDto::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Form;
|
namespace App\Form;
|
||||||
|
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Service\ParticipantFieldHandlerRegistry;
|
use App\Form\Service\ParticipantFieldHandlerRegistry;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||||
@@ -31,7 +31,7 @@ class BookingCreateStep2Type extends AbstractType
|
|||||||
*/
|
*/
|
||||||
public function onPreSetData(FormEvent $event): void
|
public function onPreSetData(FormEvent $event): void
|
||||||
{
|
{
|
||||||
/** @var BookingCreateDto|null $data */
|
/** @var BookingDto|null $data */
|
||||||
$data = $event->getData();
|
$data = $event->getData();
|
||||||
if (null === $data) {
|
if (null === $data) {
|
||||||
return;
|
return;
|
||||||
@@ -43,7 +43,7 @@ class BookingCreateStep2Type extends AbstractType
|
|||||||
/**
|
/**
|
||||||
* Handles dynamic participant form field updates on POST requests (e.g., from HTMX).
|
* 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
|
* the form's children are processed. It then rebuilds the participants
|
||||||
* field to ensure choice loaders are created with the fresh state.
|
* field to ensure choice loaders are created with the fresh state.
|
||||||
*/
|
*/
|
||||||
@@ -52,7 +52,7 @@ class BookingCreateStep2Type extends AbstractType
|
|||||||
$form = $event->getForm();
|
$form = $event->getForm();
|
||||||
$submittedData = $event->getData();
|
$submittedData = $event->getData();
|
||||||
|
|
||||||
/** @var BookingCreateDto $bookingDto */
|
/** @var BookingDto $bookingDto */
|
||||||
$bookingDto = $form->getData();
|
$bookingDto = $form->getData();
|
||||||
|
|
||||||
// Process field handlers and synchronize submitted data with cleaned DTO state
|
// 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
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'data_class' => BookingCreateDto::class,
|
'data_class' => BookingDto::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Form;
|
namespace App\Form;
|
||||||
|
|
||||||
use App\BusProNet\Constants;
|
use App\BusProNet\Constants;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
@@ -69,7 +69,7 @@ class BookingCreateStep3Type extends AbstractType
|
|||||||
public function configureOptions(OptionsResolver $resolver): void
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$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.
|
* 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);
|
$travelStartDate = CarbonImmutable::instance($bookingDto->travel->dateFrom);
|
||||||
$now = CarbonImmutable::now();
|
$now = CarbonImmutable::now();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Form;
|
namespace App\Form;
|
||||||
|
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
@@ -31,7 +31,7 @@ class BookingCreateStep4Type extends AbstractType
|
|||||||
public function configureOptions(OptionsResolver $resolver): void
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'data_class' => BookingCreateDto::class,
|
'data_class' => BookingDto::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Form\Model;
|
|
||||||
|
|
||||||
use App\BusProNet\Constants;
|
|
||||||
use App\BusProNet\Model\Travel;
|
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
|
||||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|
||||||
|
|
||||||
class BookingCreateDto implements BookingDtoInterface
|
|
||||||
{
|
|
||||||
public int $currentStep = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array<int, RoomSelectionDto>
|
|
||||||
*/
|
|
||||||
#[Assert\Valid]
|
|
||||||
public array $roomSelections = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array<int, ParticipantDto>
|
|
||||||
*/
|
|
||||||
#[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<int, RoomSelectionDto>
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Form\Model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for unified access to booking data across create and edit workflows.
|
|
||||||
*
|
|
||||||
* This interface provides a consistent API for accessing common booking data
|
|
||||||
* regardless of whether the data comes from a creation workflow (BookingCreateDto)
|
|
||||||
* or an edit workflow (BookingEditDto). This enables code reuse and simplifies
|
|
||||||
* form field handlers and state management systems.
|
|
||||||
*/
|
|
||||||
interface BookingDtoInterface
|
|
||||||
{
|
|
||||||
public const MODE_CREATE = 'create';
|
|
||||||
public const MODE_EDIT = 'edit';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the booking mode (create or edit).
|
|
||||||
*
|
|
||||||
* @return string One of MODE_CREATE or MODE_EDIT constants
|
|
||||||
*/
|
|
||||||
public function getMode(): string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all participants in the booking.
|
|
||||||
*
|
|
||||||
* @return array<int, ParticipantDto> 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;
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Form\Model;
|
|
||||||
|
|
||||||
use App\BusProNet\Constants;
|
|
||||||
use App\BusProNet\Model\Booking;
|
|
||||||
use App\BusProNet\Model\PersonalData;
|
|
||||||
use App\BusProNet\Model\Travel;
|
|
||||||
use App\BusProNet\Utility\DirectionMapper;
|
|
||||||
use Symfony\Component\Validator\Constraints as Assert;
|
|
||||||
|
|
||||||
class BookingEditDto implements BookingDtoInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var array<int, ParticipantDto>
|
|
||||||
*/
|
|
||||||
#[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<int, RoomSelectionDto>
|
|
||||||
*/
|
|
||||||
public function getSelectedRooms(): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Form;
|
namespace App\Form;
|
||||||
|
|
||||||
use App\BusProNet\Constants;
|
use App\BusProNet\Constants;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
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.
|
* 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);
|
$travelStartDate = CarbonImmutable::instance($bookingDto->travel->dateFrom);
|
||||||
$now = CarbonImmutable::now();
|
$now = CarbonImmutable::now();
|
||||||
|
|||||||
@@ -194,6 +194,16 @@ class CreateFieldStateProvider extends AbstractFieldStateProvider
|
|||||||
'hidden' => FieldValueCondition::equals('parking', false),
|
'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
|
// Example field state conditions would be registered here
|
||||||
// For demonstration purposes, here are some example patterns:
|
// For demonstration purposes, here are some example patterns:
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ use App\BusProNet\Constants;
|
|||||||
use App\BusProNet\Model\Pickup;
|
use App\BusProNet\Model\Pickup;
|
||||||
use App\BusProNet\Model\Service;
|
use App\BusProNet\Model\Service;
|
||||||
use App\BusProNet\Utility\DirectionMapper;
|
use App\BusProNet\Utility\DirectionMapper;
|
||||||
use App\Form\Model\BookingCreateDto;
|
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\BookingEditDto;
|
|
||||||
use App\Form\Service\Abstract\AbstractFieldOptionsProvider;
|
use App\Form\Service\Abstract\AbstractFieldOptionsProvider;
|
||||||
use App\Form\Service\Factory\ParticipantRoomChoiceLoaderFactory;
|
use App\Form\Service\Factory\ParticipantRoomChoiceLoaderFactory;
|
||||||
use App\Service\InsuranceMatchingService;
|
use App\Service\InsuranceMatchingService;
|
||||||
@@ -462,9 +460,9 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
|||||||
* as the participant's selected skipass. This ensures rental equipment
|
* as the participant's selected skipass. This ensures rental equipment
|
||||||
* is only available for the exact duration of the skipass.
|
* 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 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
|
* @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.
|
* 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 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
|
* @return bool True if the service should be read-only due to unavailability
|
||||||
*/
|
*/
|
||||||
private function isServiceUnavailableForParticipant(Service $service, BookingDto $bookingDto, int $participantIndex): bool
|
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
|
// For non-create workflows, don't apply availability restrictions
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -610,9 +608,9 @@ class ParticipantFieldOptionsProvider extends AbstractFieldOptionsProvider
|
|||||||
* If no age evaluator is configured or participant has no birth date,
|
* If no age evaluator is configured or participant has no birth date,
|
||||||
* returns empty array to be handled by field visibility conditions.
|
* 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 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
|
* @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.
|
* Gets eligible insurances for a participant based on eligibility criteria.
|
||||||
*
|
*
|
||||||
* @param BookingDto $bookingDto The booking DTO containing travel and participant data
|
* @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
|
* @return array Array of eligible insurance objects filtered by age, family status, and other constraints
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -125,6 +125,10 @@ class ParticipantInsuranceFieldHandler extends AbstractParticipantFieldHandler
|
|||||||
$currentInsurance = $participant->insurance;
|
$currentInsurance = $participant->insurance;
|
||||||
$availableInsurances = $bookingDto->travel->insurances ?? [];
|
$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
|
// Determine if this is a new user selection or just form resubmission
|
||||||
$isNewSelection = null !== $selectedInsuranceId
|
$isNewSelection = null !== $selectedInsuranceId
|
||||||
&& (null === $currentInsurance || !$this->isSameInsurance($selectedInsuranceId, $currentInsurance));
|
&& (null === $currentInsurance || !$this->isSameInsurance($selectedInsuranceId, $currentInsurance));
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use App\BusProNet\Constants;
|
|||||||
use App\BusProNet\Model\Insurance;
|
use App\BusProNet\Model\Insurance;
|
||||||
use App\BusProNet\Model\Room;
|
use App\BusProNet\Model\Room;
|
||||||
use App\BusProNet\Model\Service;
|
use App\BusProNet\Model\Service;
|
||||||
use App\Form\Model\BookingCreateDto;
|
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
|
|
||||||
@@ -57,10 +56,6 @@ class BookingPriceCalculatorService
|
|||||||
{
|
{
|
||||||
$roomPricing = [];
|
$roomPricing = [];
|
||||||
|
|
||||||
if (false === $bookingDto instanceof BookingCreateDto) {
|
|
||||||
return $roomPricing;
|
|
||||||
}
|
|
||||||
|
|
||||||
$selectedRooms = $bookingDto->getSelectedRooms();
|
$selectedRooms = $bookingDto->getSelectedRooms();
|
||||||
if (true === empty($selectedRooms)) {
|
if (true === empty($selectedRooms)) {
|
||||||
return $roomPricing;
|
return $roomPricing;
|
||||||
@@ -196,16 +191,12 @@ class BookingPriceCalculatorService
|
|||||||
* including their room allocation (full room price) and all selected services.
|
* including their room allocation (full room price) and all selected services.
|
||||||
*
|
*
|
||||||
* @param BookingDto $bookingDto The booking data containing all participants
|
* @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
|
* @return float The total price for the specified participant
|
||||||
*/
|
*/
|
||||||
public function calculateIndividualParticipantPrice(BookingDto $bookingDto, int $participantIndex): float
|
public function calculateIndividualParticipantPrice(BookingDto $bookingDto, int $participantIndex): float
|
||||||
{
|
{
|
||||||
if (false === $bookingDto instanceof BookingCreateDto) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$participant = $bookingDto->getParticipant($participantIndex);
|
$participant = $bookingDto->getParticipant($participantIndex);
|
||||||
if (null === $participant) {
|
if (null === $participant) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
@@ -237,10 +228,6 @@ class BookingPriceCalculatorService
|
|||||||
*/
|
*/
|
||||||
public function calculateAllParticipantIndividualPrices(BookingDto $bookingDto): array
|
public function calculateAllParticipantIndividualPrices(BookingDto $bookingDto): array
|
||||||
{
|
{
|
||||||
if (false === $bookingDto instanceof BookingCreateDto) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$participantPrices = [];
|
$participantPrices = [];
|
||||||
$participants = $bookingDto->getParticipants();
|
$participants = $bookingDto->getParticipants();
|
||||||
|
|
||||||
@@ -257,17 +244,17 @@ class BookingPriceCalculatorService
|
|||||||
* This method is used for insurance eligibility filtering to avoid circular dependency
|
* This method is used for insurance eligibility filtering to avoid circular dependency
|
||||||
* where insurance selection affects travel price which affects insurance eligibility.
|
* where insurance selection affects travel price which affects insurance eligibility.
|
||||||
*
|
*
|
||||||
* @param BookingDto $bookingDto The booking data containing all participants
|
* Only includes services where versicherungsberechnung='J' in the XML. Services with
|
||||||
* @param int $participantIndex The index of the participant to calculate for
|
* 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
|
public function calculateIndividualParticipantPriceExcludingInsurance(BookingDto $bookingDto, int $participantIndex): float
|
||||||
{
|
{
|
||||||
if (false === $bookingDto instanceof BookingCreateDto) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$participant = $bookingDto->getParticipant($participantIndex);
|
$participant = $bookingDto->getParticipant($participantIndex);
|
||||||
if (null === $participant) {
|
if (null === $participant) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
@@ -285,7 +272,8 @@ class BookingPriceCalculatorService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add service prices for this participant (excluding insurance)
|
// 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;
|
return $totalPrice;
|
||||||
}
|
}
|
||||||
@@ -528,23 +516,28 @@ class BookingPriceCalculatorService
|
|||||||
/**
|
/**
|
||||||
* Calculates the total service cost for a single participant.
|
* Calculates the total service cost for a single participant.
|
||||||
*
|
*
|
||||||
* @param ParticipantDto $participant The participant to calculate services for
|
* @param ParticipantDto $participant The participant to calculate services for
|
||||||
* @param bool $includeInsurance Whether to include insurance pricing (default: true)
|
* @param bool $includeInsurance Whether to include insurance pricing (default: true)
|
||||||
* @param BookingDto|null $bookingDto Optional booking DTO for bulk insurance resolution
|
* @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
|
* @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;
|
$serviceTotal = 0.0;
|
||||||
|
|
||||||
// Single service selections
|
// Single service selections
|
||||||
if (null !== $participant->skiPass && null !== $participant->skiPass->price) {
|
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) {
|
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)
|
// Get effective insurance (considering bulk insurance for dependent participants)
|
||||||
@@ -555,11 +548,15 @@ class BookingPriceCalculatorService
|
|||||||
|
|
||||||
// Transportation services
|
// Transportation services
|
||||||
if (null !== $participant->transportationOutbound && null !== $participant->transportationOutbound->price) {
|
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) {
|
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) {
|
if (null !== $participant->pickup && null !== $participant->pickup->price) {
|
||||||
@@ -567,7 +564,9 @@ class BookingPriceCalculatorService
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $participant->parkingService && null !== $participant->parkingService->price) {
|
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
|
// Multiple service selections
|
||||||
@@ -582,7 +581,9 @@ class BookingPriceCalculatorService
|
|||||||
if (true === is_array($serviceArray)) {
|
if (true === is_array($serviceArray)) {
|
||||||
foreach ($serviceArray as $service) {
|
foreach ($serviceArray as $service) {
|
||||||
if ($service instanceof Service && null !== $service->price) {
|
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.
|
* 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) {
|
if (null === $roomId) {
|
||||||
return null;
|
return null;
|
||||||
@@ -644,7 +645,7 @@ class BookingPriceCalculatorService
|
|||||||
* This method is used for pricing calculations to show correct prices when bulk
|
* 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.
|
* 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
|
* @param BookingDto|null $bookingDto Optional booking DTO for bulk insurance check
|
||||||
*
|
*
|
||||||
* @return Insurance|null The effective insurance for pricing purposes
|
* @return Insurance|null The effective insurance for pricing purposes
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use App\BusProNet\Model\Room;
|
|||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Exception\BookingSessionNotFoundException;
|
use App\Exception\BookingSessionNotFoundException;
|
||||||
use App\Exception\NoRoomsAvailableException;
|
use App\Exception\NoRoomsAvailableException;
|
||||||
use App\Form\Model\BookingCreateDto;
|
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\RoomSelectionDto;
|
use App\Form\Model\RoomSelectionDto;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@@ -32,7 +31,7 @@ class BookingService
|
|||||||
* is first loaded, before any HTMX modifications. This ensures accurate change
|
* is first loaded, before any HTMX modifications. This ensures accurate change
|
||||||
* detection for room assignment resets.
|
* 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;
|
$baselineKey = self::BOOKING_CREATE_BASELINE_KEY;
|
||||||
|
|
||||||
@@ -66,11 +65,11 @@ class BookingService
|
|||||||
*
|
*
|
||||||
* @param Request $request The HTTP request containing session data
|
* @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
|
* @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);
|
$bookingCreateDto = $request->getSession()->get(self::BOOKING_CREATE_KEY);
|
||||||
|
|
||||||
@@ -130,9 +129,9 @@ class BookingService
|
|||||||
* across multiple HTTP requests during the booking flow.
|
* across multiple HTTP requests during the booking flow.
|
||||||
*
|
*
|
||||||
* @param Request $request The HTTP request with session
|
* @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);
|
$this->saveBookingDto($request, $bookingCreateDto, BookingDto::MODE_CREATE);
|
||||||
}
|
}
|
||||||
@@ -164,11 +163,11 @@ class BookingService
|
|||||||
/**
|
/**
|
||||||
* Creates a fresh booking session with the provided travel parameters.
|
* 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
|
* and saves it to the session. It's designed to be called from the clean
|
||||||
* booking entry point without requiring UID parameters.
|
* 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);
|
$travelData = $this->travelDataService->getTravelData($dateId, $hotelId);
|
||||||
if (null === $travelData) {
|
if (null === $travelData) {
|
||||||
@@ -188,7 +187,7 @@ class BookingService
|
|||||||
$availableRooms
|
$availableRooms
|
||||||
);
|
);
|
||||||
|
|
||||||
$bookingCreateDto = new BookingCreateDto($travelData, $hotelId);
|
$bookingCreateDto = new BookingDto($travelData, $hotelId);
|
||||||
$bookingCreateDto->roomSelections = $roomSelections;
|
$bookingCreateDto->roomSelections = $roomSelections;
|
||||||
$bookingCreateDto->currentStep = 1;
|
$bookingCreateDto->currentStep = 1;
|
||||||
$bookingCreateDto->agencyId = $agencyId;
|
$bookingCreateDto->agencyId = $agencyId;
|
||||||
@@ -344,9 +343,9 @@ class BookingService
|
|||||||
* invalid assignments. Called when users modify their room selections
|
* invalid assignments. Called when users modify their room selections
|
||||||
* in step 1 to ensure participants are reassigned appropriately.
|
* 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) {
|
foreach ($dto->participants as $participant) {
|
||||||
$participant->assignedRoomId = null;
|
$participant->assignedRoomId = null;
|
||||||
@@ -358,7 +357,7 @@ class BookingService
|
|||||||
*
|
*
|
||||||
* @return array<int, array{int, int}> Array of [roomId, quantity] pairs
|
* @return array<int, array{int, int}> Array of [roomId, quantity] pairs
|
||||||
*/
|
*/
|
||||||
public function createRoomSelectionSnapshot(BookingCreateDto $dto): array
|
public function createRoomSelectionSnapshot(BookingDto $dto): array
|
||||||
{
|
{
|
||||||
return array_map(
|
return array_map(
|
||||||
fn ($roomSelection) => [(int) $roomSelection->roomId, (int) $roomSelection->quantity],
|
fn ($roomSelection) => [(int) $roomSelection->roomId, (int) $roomSelection->quantity],
|
||||||
@@ -373,11 +372,11 @@ class BookingService
|
|||||||
* to detect changes that would require participant reassignment.
|
* to detect changes that would require participant reassignment.
|
||||||
*
|
*
|
||||||
* @param array $oldSnapshot The baseline room selection snapshot
|
* @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
|
* @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);
|
$newSnapshot = $this->createRoomSelectionSnapshot($newDto);
|
||||||
|
|
||||||
@@ -395,9 +394,9 @@ class BookingService
|
|||||||
* have at least one skipass available for their age. Ineligible participants are
|
* have at least one skipass available for their age. Ineligible participants are
|
||||||
* skipped to prevent their mandatory services from being included in pricing.
|
* 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);
|
$additionalServices = $bookingDto->travel->getAdditionalServicesBySubTypes(\App\BusProNet\Constants::TOKEN_ADDITIONAL);
|
||||||
$mandatoryServices = array_filter($additionalServices, fn ($service) => true === $service->mandatory);
|
$mandatoryServices = array_filter($additionalServices, fn ($service) => true === $service->mandatory);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ namespace App\Service;
|
|||||||
|
|
||||||
use App\BusProNet\Model\Insurance;
|
use App\BusProNet\Model\Insurance;
|
||||||
use App\BusProNet\Traits\SortByPriceTrait;
|
use App\BusProNet\Traits\SortByPriceTrait;
|
||||||
use App\Form\Model\BookingCreateDto;
|
|
||||||
use App\Form\Model\BookingDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use App\Model\InsuranceEligibilityCriteria;
|
use App\Model\InsuranceEligibilityCriteria;
|
||||||
@@ -31,9 +30,9 @@ class InsuranceMatchingService
|
|||||||
/**
|
/**
|
||||||
* Filters insurances based on participant and booking criteria.
|
* Filters insurances based on participant and booking criteria.
|
||||||
*
|
*
|
||||||
* @param array<Insurance> $insurances Available insurances to filter
|
* @param array<Insurance> $insurances Available insurances to filter
|
||||||
* @param ParticipantDto $participant The participant to match insurances for
|
* @param ParticipantDto $participant The participant to match insurances for
|
||||||
* @param BookingDto $booking The booking context for additional criteria
|
* @param BookingDto $booking The booking context for additional criteria
|
||||||
*
|
*
|
||||||
* @return array<Insurance> Filtered array of eligible insurances
|
* @return array<Insurance> Filtered array of eligible insurances
|
||||||
*/
|
*/
|
||||||
@@ -60,10 +59,10 @@ class InsuranceMatchingService
|
|||||||
* current insurance is no longer eligible. It finds the same insurance type
|
* current insurance is no longer eligible. It finds the same insurance type
|
||||||
* (subType + familyInsurance) with the correct price tier.
|
* (subType + familyInsurance) with the correct price tier.
|
||||||
*
|
*
|
||||||
* @param array<Insurance> $availableInsurances All available insurances
|
* @param array<Insurance> $availableInsurances All available insurances
|
||||||
* @param Insurance $currentInsurance The currently selected insurance
|
* @param Insurance $currentInsurance The currently selected insurance
|
||||||
* @param ParticipantDto $participant The participant to reassign for
|
* @param ParticipantDto $participant The participant to reassign for
|
||||||
* @param BookingDto $booking The booking context
|
* @param BookingDto $booking The booking context
|
||||||
*
|
*
|
||||||
* @return Insurance|null The reassigned insurance or null if no suitable match found
|
* @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
|
* (subType + familyInsurance) to all participants, but selects the appropriate price tier
|
||||||
* based on each participant's individual travel price.
|
* based on each participant's individual travel price.
|
||||||
*
|
*
|
||||||
* @param array<Insurance> $availableInsurances All available insurances
|
* @param array<Insurance> $availableInsurances All available insurances
|
||||||
* @param Insurance $selectedInsurance The insurance selected by the applicant
|
* @param Insurance $selectedInsurance The insurance selected by the applicant
|
||||||
* @param BookingDto $booking The booking with all participants
|
* @param BookingDto $booking The booking with all participants
|
||||||
*
|
*
|
||||||
* @return array<int, Insurance|null> Array indexed by participant index with assigned insurances
|
* @return array<int, Insurance|null> Array indexed by participant index with assigned insurances
|
||||||
*
|
*
|
||||||
@@ -187,8 +186,8 @@ class InsuranceMatchingService
|
|||||||
*/
|
*/
|
||||||
private function checkFamilyInsuranceConstraints(Insurance $insurance, BookingDto $booking): bool
|
private function checkFamilyInsuranceConstraints(Insurance $insurance, BookingDto $booking): bool
|
||||||
{
|
{
|
||||||
// Family booking detection only available in BookingCreateDto
|
// Family booking detection only available in create mode
|
||||||
if (!$booking instanceof BookingCreateDto) {
|
if (BookingDto::MODE_EDIT === $booking->getMode()) {
|
||||||
return true; // Skip family constraints for edit mode
|
return true; // Skip family constraints for edit mode
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,14 +315,34 @@ class InsuranceMatchingService
|
|||||||
* affects travel price which then affects insurance eligibility.
|
* affects travel price which then affects insurance eligibility.
|
||||||
*
|
*
|
||||||
* @param BookingDto $booking The booking to calculate price for
|
* @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
|
* @return float The total travel price for the participant excluding insurance
|
||||||
*/
|
*/
|
||||||
private function calculateTravelPrice(BookingDto $booking, int $participantIndex): float
|
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
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles automatic room assignment for booking participants.
|
* 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
|
* - 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
|
* - 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;
|
$participantIndex = 0;
|
||||||
$selectedRooms = $dto->getSelectedRooms();
|
$selectedRooms = $dto->getSelectedRooms();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace App\Service;
|
|||||||
use App\BusProNet\Constants;
|
use App\BusProNet\Constants;
|
||||||
use App\BusProNet\Model\Service;
|
use App\BusProNet\Model\Service;
|
||||||
use App\BusProNet\Utility\DirectionMapper;
|
use App\BusProNet\Utility\DirectionMapper;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates dynamic service availability based on current booking selections.
|
* 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.
|
* Calculate remaining availability for all services based on current participant selections.
|
||||||
*
|
*
|
||||||
* @param BookingCreateDto $bookingDto The booking data with participant selections
|
* @param BookingDto $bookingDto The booking data with participant selections
|
||||||
* @param int $currentParticipantIndex The index of the participant currently filling the form
|
* @param int $currentParticipantIndex The index of the participant currently filling the form
|
||||||
*
|
*
|
||||||
* @return array<int, int> Array mapping service IDs to remaining availability counts
|
* @return array<int, int> 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);
|
$serviceUsage = $this->calculateServiceUsage($bookingDto, $currentParticipantIndex);
|
||||||
$remainingAvailability = [];
|
$remainingAvailability = [];
|
||||||
@@ -52,13 +52,13 @@ class ServiceAvailabilityCalculator
|
|||||||
/**
|
/**
|
||||||
* Filter services array to only include those with remaining availability.
|
* Filter services array to only include those with remaining availability.
|
||||||
*
|
*
|
||||||
* @param array $services Array of Service objects to filter
|
* @param array $services Array of Service objects to filter
|
||||||
* @param BookingCreateDto $bookingDto The booking data with participant selections
|
* @param BookingDto $bookingDto The booking data with participant selections
|
||||||
* @param int $participantIndex The index of the participant currently filling the form
|
* @param int $participantIndex The index of the participant currently filling the form
|
||||||
*
|
*
|
||||||
* @return array Filtered array containing only available services
|
* @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);
|
$remainingAvailability = $this->calculateRemainingAvailability($bookingDto, $participantIndex);
|
||||||
|
|
||||||
@@ -76,13 +76,13 @@ class ServiceAvailabilityCalculator
|
|||||||
/**
|
/**
|
||||||
* Check if a specific service is unavailable (sold out) for the current participant.
|
* Check if a specific service is unavailable (sold out) for the current participant.
|
||||||
*
|
*
|
||||||
* @param int $serviceId The ID of the service to check
|
* @param int $serviceId The ID of the service to check
|
||||||
* @param BookingCreateDto $bookingDto The booking data with participant selections
|
* @param BookingDto $bookingDto The booking data with participant selections
|
||||||
* @param int $participantIndex The index of the participant currently filling the form
|
* @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)
|
* @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);
|
$allServices = $this->getAllServicesFromTravel($bookingDto);
|
||||||
$service = null;
|
$service = null;
|
||||||
@@ -107,12 +107,12 @@ class ServiceAvailabilityCalculator
|
|||||||
/**
|
/**
|
||||||
* Calculate how many times each service has been selected by other participants.
|
* Calculate how many times each service has been selected by other participants.
|
||||||
*
|
*
|
||||||
* @param BookingCreateDto $bookingDto The booking data with participant selections
|
* @param BookingDto $bookingDto The booking data with participant selections
|
||||||
* @param int $currentParticipantIndex The index of the participant currently filling the form
|
* @param int $currentParticipantIndex The index of the participant currently filling the form
|
||||||
*
|
*
|
||||||
* @return array<int, int> Array mapping service IDs to usage counts
|
* @return array<int, int> Array mapping service IDs to usage counts
|
||||||
*/
|
*/
|
||||||
private function calculateServiceUsage(BookingCreateDto $bookingDto, int $currentParticipantIndex): array
|
private function calculateServiceUsage(BookingDto $bookingDto, int $currentParticipantIndex): array
|
||||||
{
|
{
|
||||||
$serviceUsage = [];
|
$serviceUsage = [];
|
||||||
|
|
||||||
@@ -187,11 +187,11 @@ class ServiceAvailabilityCalculator
|
|||||||
/**
|
/**
|
||||||
* Get all services from the travel data for availability calculation.
|
* 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<Service> Array of all available services
|
* @return array<Service> Array of all available services
|
||||||
*/
|
*/
|
||||||
private function getAllServicesFromTravel(BookingCreateDto $bookingDto): array
|
private function getAllServicesFromTravel(BookingDto $bookingDto): array
|
||||||
{
|
{
|
||||||
$allServices = [];
|
$allServices = [];
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace App\Validator\Constraints;
|
|||||||
use App\BusProNet\ApiClient;
|
use App\BusProNet\ApiClient;
|
||||||
use App\BusProNet\Model\BookingUpdate;
|
use App\BusProNet\Model\BookingUpdate;
|
||||||
use App\BusProNet\Model\Notification;
|
use App\BusProNet\Model\Notification;
|
||||||
use App\Form\Model\BookingEditDto;
|
use App\Form\Model\BookingDto;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintValidator;
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ class BookingValidator extends ConstraintValidator
|
|||||||
|
|
||||||
public function validate(mixed $value, Constraint $constraint): void
|
public function validate(mixed $value, Constraint $constraint): void
|
||||||
{
|
{
|
||||||
/** @var BookingEditDto $booking */
|
/** @var BookingDto $booking */
|
||||||
$bookingData = $value;
|
$bookingData = $value;
|
||||||
|
|
||||||
$result = $this->apiClient->updateBooking($bookingData);
|
$result = $this->apiClient->updateBooking($bookingData);
|
||||||
|
|||||||
@@ -216,9 +216,8 @@
|
|||||||
{% set applicantInsurance = form.vars.data.participants[0].insurance %}
|
{% set applicantInsurance = form.vars.data.participants[0].insurance %}
|
||||||
{% if applicantInsurance %}
|
{% if applicantInsurance %}
|
||||||
{{ applicantInsurance.label }}
|
{{ applicantInsurance.label }}
|
||||||
{% set participantPrice = participantPrices[loop.index0] %}
|
{% if applicantInsurance.price and applicantInsurance.price > 0 %}
|
||||||
{% if participantPrice.insurance and participantPrice.insurance > 0 %}
|
<span class="text-gray-500">(€{{ applicantInsurance.price|number_format(2, ',', '.') }})</span>
|
||||||
<span class="text-gray-500">(€{{ participantPrice.insurance|number_format(2, ',', '.') }})</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="italic text-gray-500 ml-2">– wie Anmelder</span>
|
<span class="italic text-gray-500 ml-2">– wie Anmelder</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use App\BusProNet\Model\Pickup;
|
|||||||
use App\BusProNet\Model\Room;
|
use App\BusProNet\Model\Room;
|
||||||
use App\BusProNet\Model\Service;
|
use App\BusProNet\Model\Service;
|
||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Form\Model\BookingEditDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
@@ -210,29 +210,31 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
$this->assertArrayNotHasKey('zustiege', $result);
|
$this->assertArrayNotHasKey('zustiege', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createCompleteFormData(): BookingEditDto
|
private function createCompleteFormData(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = new BookingEditDto($this->createMockBooking(), $this->createMockTravel());
|
$bookingDto = new BookingDto($this->createMockTravel(), 1);
|
||||||
$formData->participants = [
|
$bookingDto->booking = $this->createMockBooking();
|
||||||
|
$bookingDto->participants = [
|
||||||
$this->createMockParticipantDto(0, 'F'),
|
$this->createMockParticipantDto(0, 'F'),
|
||||||
$this->createMockParticipantDto(1, 'F'),
|
$this->createMockParticipantDto(1, 'F'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $formData;
|
return $bookingDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithCanceledParticipant(): BookingEditDto
|
private function createFormDataWithCanceledParticipant(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = new BookingEditDto($this->createMockBooking(), $this->createMockTravel());
|
$bookingDto = new BookingDto($this->createMockTravel(), 1);
|
||||||
$formData->participants = [
|
$bookingDto->booking = $this->createMockBooking();
|
||||||
|
$bookingDto->participants = [
|
||||||
$this->createMockParticipantDto(0, 'F'),
|
$this->createMockParticipantDto(0, 'F'),
|
||||||
$this->createMockParticipantDto(1, 'S'), // Canceled
|
$this->createMockParticipantDto(1, 'S'), // Canceled
|
||||||
];
|
];
|
||||||
|
|
||||||
return $formData;
|
return $bookingDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithAdditionalServices(): BookingEditDto
|
private function createFormDataWithAdditionalServices(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -243,7 +245,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithTransportation(): BookingEditDto
|
private function createFormDataWithTransportation(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -254,7 +256,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithBusPickup(): BookingEditDto
|
private function createFormDataWithBusPickup(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -267,7 +269,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithNonBusTransportation(): BookingEditDto
|
private function createFormDataWithNonBusTransportation(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -279,7 +281,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithUnusedServices(): BookingEditDto
|
private function createFormDataWithUnusedServices(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -289,7 +291,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithUpdatedPersonalData(): BookingEditDto
|
private function createFormDataWithUpdatedPersonalData(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -302,7 +304,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithInactiveParticipant(): BookingEditDto
|
private function createFormDataWithInactiveParticipant(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -318,7 +320,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataForApplicantSync(): BookingEditDto
|
private function createFormDataForApplicantSync(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -330,7 +332,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithBankAccount(): BookingEditDto
|
private function createFormDataWithBankAccount(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -345,7 +347,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithoutBankAccount(): BookingEditDto
|
private function createFormDataWithoutBankAccount(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
$formData->booking->bankAccount = null;
|
$formData->booking->bankAccount = null;
|
||||||
@@ -353,7 +355,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithRooms(): BookingEditDto
|
private function createFormDataWithRooms(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -371,7 +373,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithoutExistingCommunication(): BookingEditDto
|
private function createFormDataWithoutExistingCommunication(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
|
|
||||||
@@ -384,7 +386,7 @@ class BookingDataProcessorTest extends TestCase
|
|||||||
return $formData;
|
return $formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createFormDataWithoutPickups(): BookingEditDto
|
private function createFormDataWithoutPickups(): BookingDto
|
||||||
{
|
{
|
||||||
$formData = $this->createCompleteFormData();
|
$formData = $this->createCompleteFormData();
|
||||||
$formData->booking->pickupsOutbound = [];
|
$formData->booking->pickupsOutbound = [];
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ namespace App\Tests\Form\Service\Condition;
|
|||||||
|
|
||||||
use App\BusProNet\Model\Booking;
|
use App\BusProNet\Model\Booking;
|
||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\BookingEditDto;
|
|
||||||
use App\Form\Service\Condition\InsuranceMutabilityCondition;
|
use App\Form\Service\Condition\InsuranceMutabilityCondition;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
@@ -35,7 +34,7 @@ class InsuranceMutabilityConditionTest extends TestCase
|
|||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$travel->dateFrom = new \DateTimeImmutable('+10 days');
|
$travel->dateFrom = new \DateTimeImmutable('+10 days');
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 123);
|
$bookingDto = new BookingDto($travel, 123);
|
||||||
|
|
||||||
$result = $this->condition->evaluate($bookingDto, 0, []);
|
$result = $this->condition->evaluate($bookingDto, 0, []);
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ class InsuranceMutabilityConditionTest extends TestCase
|
|||||||
$this->assertStringContainsString('3', $result);
|
$this->assertStringContainsString('3', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createEditDto(\DateTimeImmutable $travelDate, \DateTimeImmutable $bookingDate): BookingEditDto
|
private function createEditDto(\DateTimeImmutable $travelDate, \DateTimeImmutable $bookingDate): BookingDto
|
||||||
{
|
{
|
||||||
$booking = new Booking();
|
$booking = new Booking();
|
||||||
$booking->bookingDate = $bookingDate;
|
$booking->bookingDate = $bookingDate;
|
||||||
@@ -162,6 +161,9 @@ class InsuranceMutabilityConditionTest extends TestCase
|
|||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$travel->dateFrom = $travelDate;
|
$travel->dateFrom = $travelDate;
|
||||||
|
|
||||||
return new BookingEditDto($booking, $travel);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
|
$bookingDto->booking = $booking;
|
||||||
|
|
||||||
|
return $bookingDto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace App\Tests\Form\Service;
|
|||||||
|
|
||||||
use App\BusProNet\Model\Insurance;
|
use App\BusProNet\Model\Insurance;
|
||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use App\Form\Service\ParticipantInsuranceFieldHandler;
|
use App\Form\Service\ParticipantInsuranceFieldHandler;
|
||||||
use App\Service\InsuranceMatchingService;
|
use App\Service\InsuranceMatchingService;
|
||||||
@@ -229,8 +229,8 @@ class ParticipantInsuranceFieldHandlerTest extends TestCase
|
|||||||
return $insurance;
|
return $insurance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createMockBookingDto(): BookingCreateDto
|
private function createMockBookingDto(): BookingDto
|
||||||
{
|
{
|
||||||
return $this->createMock(BookingCreateDto::class);
|
return $this->createMock(BookingDto::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Tests\Form\Service;
|
namespace App\Tests\Form\Service;
|
||||||
|
|
||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use App\Form\Service\ParticipantLicensePlateFieldHandler;
|
use App\Form\Service\ParticipantLicensePlateFieldHandler;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
@@ -38,7 +38,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
public function testProcessFieldWithoutParticipant(): void
|
public function testProcessFieldWithoutParticipant(): void
|
||||||
{
|
{
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$submittedData = ['licensePlate' => 'AB-CD 123'];
|
$submittedData = ['licensePlate' => 'AB-CD 123'];
|
||||||
|
|
||||||
$this->handler->processField($submittedData, $bookingDto, 0);
|
$this->handler->processField($submittedData, $bookingDto, 0);
|
||||||
@@ -54,7 +54,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->licensePlate = 'AB-CD 123'; // Should be cleared
|
$participant->licensePlate = 'AB-CD 123'; // Should be cleared
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$submittedData = ['licensePlate' => 'XY-ZZ 999'];
|
$submittedData = ['licensePlate' => 'XY-ZZ 999'];
|
||||||
@@ -70,7 +70,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->parking = true; // Parking selected
|
$participant->parking = true; // Parking selected
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$submittedData = ['licensePlate' => 'AB-CD 123'];
|
$submittedData = ['licensePlate' => 'AB-CD 123'];
|
||||||
@@ -86,7 +86,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->parking = true; // Parking selected
|
$participant->parking = true; // Parking selected
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$submittedData = ['licensePlate' => ''];
|
$submittedData = ['licensePlate' => ''];
|
||||||
@@ -102,7 +102,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->parking = true; // Parking selected
|
$participant->parking = true; // Parking selected
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$submittedData = ['licensePlate' => null];
|
$submittedData = ['licensePlate' => null];
|
||||||
@@ -118,7 +118,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->parking = true; // Parking selected
|
$participant->parking = true; // Parking selected
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$submittedData = ['licensePlate' => ' AB-CD 123 '];
|
$submittedData = ['licensePlate' => ' AB-CD 123 '];
|
||||||
@@ -134,7 +134,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->parking = true; // Parking selected
|
$participant->parking = true; // Parking selected
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$submittedData = ['licensePlate' => ' '];
|
$submittedData = ['licensePlate' => ' '];
|
||||||
@@ -150,7 +150,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->parking = true; // Parking selected
|
$participant->parking = true; // Parking selected
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
// Test with integer value
|
// Test with integer value
|
||||||
@@ -170,7 +170,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant->parking = true; // Parking selected
|
$participant->parking = true; // Parking selected
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$submittedData = []; // No licensePlate field
|
$submittedData = []; // No licensePlate field
|
||||||
@@ -189,7 +189,7 @@ class ParticipantLicensePlateFieldHandlerTest extends TestCase
|
|||||||
$participant2->parking = true;
|
$participant2->parking = true;
|
||||||
|
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant1, $participant2];
|
$bookingDto->participants = [$participant1, $participant2];
|
||||||
|
|
||||||
$submittedData = ['licensePlate' => 'AB-CD 123'];
|
$submittedData = ['licensePlate' => 'AB-CD 123'];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace App\Tests\Service;
|
|||||||
use App\BusProNet\Model\Room;
|
use App\BusProNet\Model\Room;
|
||||||
use App\BusProNet\Model\Service;
|
use App\BusProNet\Model\Service;
|
||||||
use App\BusProNet\Model\Travel;
|
use App\BusProNet\Model\Travel;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use App\Form\Model\RoomSelectionDto;
|
use App\Form\Model\RoomSelectionDto;
|
||||||
use App\Service\BookingPriceCalculatorService;
|
use App\Service\BookingPriceCalculatorService;
|
||||||
@@ -38,7 +38,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$roomSelection->roomId = 1;
|
$roomSelection->roomId = 1;
|
||||||
$roomSelection->quantity = 2; // 2 rooms selected
|
$roomSelection->quantity = 2; // 2 rooms selected
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->roomSelections = [$roomSelection];
|
$bookingDto->roomSelections = [$roomSelection];
|
||||||
|
|
||||||
// Test the calculation
|
// Test the calculation
|
||||||
@@ -70,7 +70,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$roomSelection->roomId = 2;
|
$roomSelection->roomId = 2;
|
||||||
$roomSelection->quantity = 1; // 1 room selected
|
$roomSelection->quantity = 1; // 1 room selected
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->roomSelections = [$roomSelection];
|
$bookingDto->roomSelections = [$roomSelection];
|
||||||
|
|
||||||
// Test the calculation
|
// Test the calculation
|
||||||
@@ -112,7 +112,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$doubleRoomSelection->roomId = 2;
|
$doubleRoomSelection->roomId = 2;
|
||||||
$doubleRoomSelection->quantity = 2; // 2 double rooms
|
$doubleRoomSelection->quantity = 2; // 2 double rooms
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->roomSelections = [$singleRoomSelection, $doubleRoomSelection];
|
$bookingDto->roomSelections = [$singleRoomSelection, $doubleRoomSelection];
|
||||||
|
|
||||||
// Test the calculation
|
// Test the calculation
|
||||||
@@ -155,7 +155,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$roomSelection->roomId = 1;
|
$roomSelection->roomId = 1;
|
||||||
$roomSelection->quantity = 1;
|
$roomSelection->quantity = 1;
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->roomSelections = [$roomSelection];
|
$bookingDto->roomSelections = [$roomSelection];
|
||||||
|
|
||||||
$result = $this->service->calculateRoomPricing($bookingDto);
|
$result = $this->service->calculateRoomPricing($bookingDto);
|
||||||
@@ -179,7 +179,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$roomSelection->roomId = 1;
|
$roomSelection->roomId = 1;
|
||||||
$roomSelection->quantity = 0; // Zero quantity - not selected
|
$roomSelection->quantity = 0; // Zero quantity - not selected
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->roomSelections = [$roomSelection];
|
$bookingDto->roomSelections = [$roomSelection];
|
||||||
|
|
||||||
$result = $this->service->calculateRoomPricing($bookingDto);
|
$result = $this->service->calculateRoomPricing($bookingDto);
|
||||||
@@ -212,7 +212,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$participant->skiPass = $skiPass;
|
$participant->skiPass = $skiPass;
|
||||||
$participant->courses = [$course];
|
$participant->courses = [$course];
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
||||||
@@ -234,7 +234,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$participant->assignedRoomId = null; // No room assigned
|
$participant->assignedRoomId = null; // No room assigned
|
||||||
$participant->skiPass = $skiPass;
|
$participant->skiPass = $skiPass;
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant];
|
$bookingDto->participants = [$participant];
|
||||||
|
|
||||||
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
||||||
@@ -246,7 +246,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
public function testCalculateIndividualParticipantPriceForNonExistentParticipant(): void
|
public function testCalculateIndividualParticipantPriceForNonExistentParticipant(): void
|
||||||
{
|
{
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [];
|
$bookingDto->participants = [];
|
||||||
|
|
||||||
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
$result = $this->service->calculateIndividualParticipantPrice($bookingDto, 0);
|
||||||
@@ -290,7 +290,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
$participant3 = new ParticipantDto();
|
$participant3 = new ParticipantDto();
|
||||||
$participant3->assignedRoomId = null; // No room assigned
|
$participant3->assignedRoomId = null; // No room assigned
|
||||||
|
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [$participant1, $participant2, $participant3];
|
$bookingDto->participants = [$participant1, $participant2, $participant3];
|
||||||
|
|
||||||
$result = $this->service->calculateAllParticipantIndividualPrices($bookingDto);
|
$result = $this->service->calculateAllParticipantIndividualPrices($bookingDto);
|
||||||
@@ -308,7 +308,7 @@ class BookingPriceCalculatorServiceTest extends TestCase
|
|||||||
public function testCalculateAllParticipantIndividualPricesWithEmptyBooking(): void
|
public function testCalculateAllParticipantIndividualPricesWithEmptyBooking(): void
|
||||||
{
|
{
|
||||||
$travel = new Travel();
|
$travel = new Travel();
|
||||||
$bookingDto = new BookingCreateDto($travel, 1);
|
$bookingDto = new BookingDto($travel, 1);
|
||||||
$bookingDto->participants = [];
|
$bookingDto->participants = [];
|
||||||
|
|
||||||
$result = $this->service->calculateAllParticipantIndividualPrices($bookingDto);
|
$result = $this->service->calculateAllParticipantIndividualPrices($bookingDto);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace App\Tests\Service;
|
namespace App\Tests\Service;
|
||||||
|
|
||||||
use App\BusProNet\Model\Insurance;
|
use App\BusProNet\Model\Insurance;
|
||||||
use App\Form\Model\BookingCreateDto;
|
use App\Form\Model\BookingDto;
|
||||||
use App\Form\Model\ParticipantDto;
|
use App\Form\Model\ParticipantDto;
|
||||||
use App\Service\BookingPriceCalculatorService;
|
use App\Service\BookingPriceCalculatorService;
|
||||||
use App\Service\InsuranceMatchingService;
|
use App\Service\InsuranceMatchingService;
|
||||||
@@ -254,10 +254,10 @@ class InsuranceMatchingServiceTest extends TestCase
|
|||||||
return $participant;
|
return $participant;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createBooking(string $travelDateFrom, string $travelDateTo): BookingCreateDto
|
private function createBooking(string $travelDateFrom, string $travelDateTo): BookingDto
|
||||||
{
|
{
|
||||||
$travel = $this->createTravel($travelDateFrom, $travelDateTo);
|
$travel = $this->createTravel($travelDateFrom, $travelDateTo);
|
||||||
$booking = new BookingCreateDto($travel, 1);
|
$booking = new BookingDto($travel, 1);
|
||||||
|
|
||||||
return $booking;
|
return $booking;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user