feat: correct calculation and display of individual pricing
This commit is contained in:
@@ -8,6 +8,7 @@ use App\Controller\Traits\HtmxControllerTrait;
|
||||
use App\Form\BookingCreateStep2Type;
|
||||
use App\Form\Model\BookingCreateDto;
|
||||
use App\Form\Model\ParticipantDto;
|
||||
use App\Service\BookingPriceCalculatorService;
|
||||
use App\Service\BookingService;
|
||||
use App\Service\TravelDataService;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@@ -29,6 +30,7 @@ class CreateStep2Controller extends AbstractController
|
||||
|
||||
public function __construct(
|
||||
private readonly BookingService $bookingService,
|
||||
private readonly BookingPriceCalculatorService $priceCalculator,
|
||||
private readonly TravelDataService $travelDataService,
|
||||
) {
|
||||
}
|
||||
@@ -80,12 +82,14 @@ class CreateStep2Controller extends AbstractController
|
||||
$roomAssignmentCounts = $this->bookingService->getRoomAssignmentCounts($bookingCreateDto);
|
||||
$availableRooms = $bookingCreateDto->travel->getAvailableRooms();
|
||||
$groupedSelectedRooms = $this->bookingService->groupRoomSelectionsByType($bookingCreateDto->getSelectedRooms(), $availableRooms);
|
||||
$participantPrices = $this->priceCalculator->calculateAllParticipantIndividualPrices($bookingCreateDto);
|
||||
|
||||
return $this->render('booking/create_step_2.html.twig', [
|
||||
'bookingCreateDto' => $bookingCreateDto,
|
||||
'participantsCount' => $participantsCount,
|
||||
'pricingData' => $summary['pricing'],
|
||||
'assignmentCounts' => $roomAssignmentCounts,
|
||||
'participantPrices' => $participantPrices,
|
||||
'form' => $form->createView(),
|
||||
'groupedSelectedRooms' => $groupedSelectedRooms,
|
||||
]);
|
||||
@@ -132,6 +136,7 @@ class CreateStep2Controller extends AbstractController
|
||||
$roomAssignmentCounts = $this->bookingService->getRoomAssignmentCounts($bookingCreateDto);
|
||||
$availableRooms = $bookingCreateDto->travel->getAvailableRooms();
|
||||
$groupedSelectedRooms = $this->bookingService->groupRoomSelectionsByType($bookingCreateDto->getSelectedRooms(), $availableRooms);
|
||||
$participantPrices = $this->priceCalculator->calculateAllParticipantIndividualPrices($bookingCreateDto);
|
||||
|
||||
// The DTO is now updated with the latest selection and submitted data has been cleaned.
|
||||
// We can now render the blocks with the fresh data.
|
||||
@@ -144,6 +149,7 @@ class CreateStep2Controller extends AbstractController
|
||||
'participantsCount' => $participantsCount,
|
||||
'pricingData' => $summary['pricing'],
|
||||
'assignmentCounts' => $roomAssignmentCounts,
|
||||
'participantPrices' => $participantPrices,
|
||||
'groupedSelectedRooms' => $groupedSelectedRooms,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -66,12 +66,17 @@ class BookingPriceCalculatorService
|
||||
continue;
|
||||
}
|
||||
|
||||
$totalPrice = $roomSelection->quantity * $room->price;
|
||||
// Calculate participant count for this room selection
|
||||
$participantCount = $room->minPax * $roomSelection->quantity;
|
||||
|
||||
// Each participant pays the full room price
|
||||
$totalPrice = $participantCount * $room->price;
|
||||
|
||||
$roomPricing[] = [
|
||||
'roomId' => $room->id,
|
||||
'label' => $room->label,
|
||||
'quantity' => $roomSelection->quantity,
|
||||
'participantCount' => $participantCount,
|
||||
'unitPrice' => $room->price,
|
||||
'totalPrice' => $totalPrice,
|
||||
];
|
||||
@@ -171,6 +176,68 @@ class BookingPriceCalculatorService
|
||||
return '€'.$this->formatPrice($price);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total price for an individual participant.
|
||||
*
|
||||
* This method calculates the complete price breakdown for a single participant,
|
||||
* including their room allocation (full room price) and all selected services.
|
||||
*
|
||||
* @param BookingDtoInterface $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
|
||||
*/
|
||||
public function calculateIndividualParticipantPrice(BookingDtoInterface $bookingDto, int $participantIndex): float
|
||||
{
|
||||
if (false === $bookingDto instanceof BookingCreateDto) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
$participant = $bookingDto->getParticipant($participantIndex);
|
||||
if (null === $participant) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
$totalPrice = 0.0;
|
||||
|
||||
// Add room price if participant is assigned to a room
|
||||
if (null !== $participant->assignedRoomId) {
|
||||
$room = $this->getRoomById($bookingDto, $participant->assignedRoomId);
|
||||
if (null !== $room && null !== $room->price) {
|
||||
// Each participant pays the full room price
|
||||
$totalPrice += $room->price;
|
||||
}
|
||||
}
|
||||
|
||||
// Add service prices for this participant
|
||||
$totalPrice += $this->calculateParticipantServiceTotal($participant);
|
||||
|
||||
return $totalPrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates individual prices for all participants in a booking.
|
||||
*
|
||||
* @param BookingDtoInterface $bookingDto The booking data containing all participants
|
||||
*
|
||||
* @return array Array indexed by participant index containing individual prices
|
||||
*/
|
||||
public function calculateAllParticipantIndividualPrices(BookingDtoInterface $bookingDto): array
|
||||
{
|
||||
if (false === $bookingDto instanceof BookingCreateDto) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$participantPrices = [];
|
||||
$participants = $bookingDto->getParticipants();
|
||||
|
||||
foreach ($participants as $index => $participant) {
|
||||
$participantPrices[$index] = $this->calculateIndividualParticipantPrice($bookingDto, $index);
|
||||
}
|
||||
|
||||
return $participantPrices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregates all transportation-related services and pricing into separate line items.
|
||||
*
|
||||
@@ -405,6 +472,68 @@ class BookingPriceCalculatorService
|
||||
$serviceAggregation[$serviceKey]['totalPrice'] += $service->price * $quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total service cost for a single participant.
|
||||
*
|
||||
* @param ParticipantDto $participant The participant to calculate services for
|
||||
*
|
||||
* @return float The total service cost for this participant
|
||||
*/
|
||||
private function calculateParticipantServiceTotal(ParticipantDto $participant): float
|
||||
{
|
||||
$serviceTotal = 0.0;
|
||||
|
||||
// Single service selections
|
||||
if (null !== $participant->skiPass && null !== $participant->skiPass->price) {
|
||||
$serviceTotal += $participant->skiPass->price;
|
||||
}
|
||||
|
||||
if (null !== $participant->rentalInsurance && null !== $participant->rentalInsurance->price) {
|
||||
$serviceTotal += $participant->rentalInsurance->price;
|
||||
}
|
||||
|
||||
// Transportation services
|
||||
if (null !== $participant->transportationOutbound && null !== $participant->transportationOutbound->price) {
|
||||
$serviceTotal += $participant->transportationOutbound->price;
|
||||
}
|
||||
|
||||
if (null !== $participant->transportationInbound && null !== $participant->transportationInbound->price) {
|
||||
$serviceTotal += $participant->transportationInbound->price;
|
||||
}
|
||||
|
||||
if (null !== $participant->pickupOutbound && null !== $participant->pickupOutbound->price) {
|
||||
$serviceTotal += $participant->pickupOutbound->price;
|
||||
}
|
||||
|
||||
if (null !== $participant->pickupInbound && null !== $participant->pickupInbound->price) {
|
||||
$serviceTotal += $participant->pickupInbound->price;
|
||||
}
|
||||
|
||||
if (null !== $participant->parkingService && null !== $participant->parkingService->price) {
|
||||
$serviceTotal += $participant->parkingService->price;
|
||||
}
|
||||
|
||||
// Multiple service selections
|
||||
$multipleServiceArrays = [
|
||||
'courses' => $participant->courses,
|
||||
'additionalServices' => $participant->additionalServices,
|
||||
'board' => $participant->board,
|
||||
'rentals' => $participant->rentals,
|
||||
];
|
||||
|
||||
foreach ($multipleServiceArrays as $serviceArray) {
|
||||
if (true === is_array($serviceArray)) {
|
||||
foreach ($serviceArray as $service) {
|
||||
if ($service instanceof Service && null !== $service->price) {
|
||||
$serviceTotal += $service->price;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $serviceTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a room by ID from the booking's travel data.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user