Files
myep/src/Service/RoomPricingCalculator.php
T

160 lines
5.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Service;
use App\BusProNet\Model\Room;
use App\Form\Model\BookingDto;
/**
* Calculates pricing for room allocations in bookings.
*
* Handles room pricing in both create mode (from room selections) and
* edit mode (from booking entity data with individual participant prices).
*/
class RoomPricingCalculator
{
/**
* Calculates pricing for all selected rooms.
*
* @param BookingDto $bookingDto The booking data containing room selections
*
* @return array Array of room pricing data with labels, quantities, and totals
*/
public function calculateRoomPricing(BookingDto $bookingDto): array
{
// In edit mode, use room data from the booking entity
if (BookingDto::MODE_EDIT === $bookingDto->getMode() && null !== $bookingDto->booking) {
return $this->calculateRoomPricingFromBooking($bookingDto);
}
// In create mode, use room selections from the form
return $this->calculateRoomPricingFromSelections($bookingDto);
}
/**
* Calculates total price for all rooms.
*/
public function calculateRoomTotal(BookingDto $bookingDto): float
{
$roomPricing = $this->calculateRoomPricing($bookingDto);
return array_sum(array_column($roomPricing, 'totalPrice'));
}
/**
* Retrieves a room by ID from the booking's travel data.
*/
public function getRoomById(BookingDto $bookingDto, ?int $roomId): ?Room
{
if (null === $roomId) {
return null;
}
foreach ($bookingDto->travel->rooms as $room) {
if ($room->id === $roomId) {
return $room;
}
}
return null;
}
/**
* Calculates room pricing from form selections (create mode).
*
* @param BookingDto $bookingDto The booking data containing room selections
*
* @return array Array of room pricing data
*/
private function calculateRoomPricingFromSelections(BookingDto $bookingDto): array
{
$roomPricing = [];
$selectedRooms = $bookingDto->getSelectedRooms();
if (true === empty($selectedRooms)) {
return $roomPricing;
}
foreach ($selectedRooms as $roomSelection) {
$room = $this->getRoomById($bookingDto, $roomSelection->id);
if (null === $room || null === $room->price) {
continue;
}
// 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,
];
}
return $roomPricing;
}
/**
* Calculates room pricing from booking entity data (edit mode).
*
* In edit mode, room prices come from the booking entity's individualPrice arrays.
* Each participant has their room price stored in the room's individualPrice array.
*
* @param BookingDto $bookingDto The booking data with booking entity
*
* @return array Array of room pricing data with labels, quantities, and totals
*/
private function calculateRoomPricingFromBooking(BookingDto $bookingDto): array
{
$roomPricing = [];
$roomGroups = [];
// Group participants by room and sum their individual prices
foreach ($bookingDto->booking->rooms as $room) {
if (false === isset($roomGroups[$room->id])) {
$roomGroups[$room->id] = [
'room' => $room,
'participantCount' => 0,
'totalPrice' => 0.0,
];
}
// Sum individual prices for all participants in this room
foreach ($room->mapping as $participantIndex) {
$individualPrice = $room->individualPrice[$participantIndex] ?? 0.0;
$roomGroups[$room->id]['totalPrice'] += $individualPrice;
++$roomGroups[$room->id]['participantCount'];
}
}
// Build pricing array
foreach ($roomGroups as $roomId => $data) {
$room = $data['room'];
$participantCount = $data['participantCount'];
$totalPrice = $data['totalPrice'];
// Calculate average unit price (price per person)
$unitPrice = $participantCount > 0 ? $totalPrice / $participantCount : 0.0;
$roomPricing[] = [
'roomId' => $room->id,
'label' => $room->label,
'quantity' => $room->totalCount,
'participantCount' => $participantCount,
'unitPrice' => $unitPrice,
'totalPrice' => $totalPrice,
];
}
return $roomPricing;
}
}