319 lines
10 KiB
PHP
319 lines
10 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\BusProNet\Model;
|
|
|
|
use App\BusProNet\Constants;
|
|
|
|
/**
|
|
* Represents a booking with participants, services, and pricing information.
|
|
*
|
|
* This class handles complete booking data including participant information,
|
|
* selected services, transportation details, accommodation, and pricing calculations.
|
|
* It provides methods to retrieve participant-specific data and calculate costs.
|
|
*/
|
|
class Booking
|
|
{
|
|
public ?int $id = null;
|
|
public ?int $agencyId = null;
|
|
public ?int $bookingNumber = null;
|
|
public ?string $status = null;
|
|
public ?PersonalData $applicant = null;
|
|
public ?int $participantCount = null;
|
|
public ?float $price = null;
|
|
public ?\DateTimeImmutable $bookingDate = null;
|
|
public ?string $travelName = null;
|
|
public ?int $dateId = null;
|
|
public ?string $travelCode = null;
|
|
public ?\DateTimeImmutable $travelDate = null;
|
|
public ?Travel $travelData = null;
|
|
public ?int $hotelId = null;
|
|
public ?string $hotelName = null;
|
|
public bool $hasDocuments = false;
|
|
public ?float $payment = null;
|
|
public ?string $paymentId = null;
|
|
public ?string $paymentType = null;
|
|
public ?string $paymentLabel = null;
|
|
public ?BankAccount $bankAccount = null;
|
|
public array $participantsStatus = [];
|
|
public array $participants = [];
|
|
public array $transportationServices = [];
|
|
public array $additionalServices = [];
|
|
public array $rooms = [];
|
|
public array $pickupsOutbound = [];
|
|
public array $pickupsInbound = [];
|
|
public array $surcharges = [];
|
|
public array $insurances = [];
|
|
public ?int $invoiceNumber = null;
|
|
public ?float $totalPrice = null;
|
|
public ?string $travelInfoUrl = null;
|
|
|
|
/**
|
|
* Calculates the remaining balance for the booking.
|
|
*
|
|
* Returns the difference between the total price and any payments made.
|
|
* If no payment has been made, returns the full price.
|
|
*
|
|
* @return float The remaining balance amount
|
|
*/
|
|
public function getBalance(): float
|
|
{
|
|
if (null === $this->payment) {
|
|
return $this->price;
|
|
}
|
|
|
|
return $this->price - $this->payment;
|
|
}
|
|
|
|
/**
|
|
* Retrieves additional services filtered by group.
|
|
*
|
|
* Filters the additional services array based on the provided group(s).
|
|
* Supports both single group strings and arrays of groups.
|
|
*
|
|
* @param mixed $group The service group(s) to filter by
|
|
*
|
|
* @return array<Service> The filtered services array
|
|
*/
|
|
public function getAdditionalServicesByGroup(mixed $group): array
|
|
{
|
|
$group = (array) $group;
|
|
|
|
return array_filter($this->additionalServices, function (Service $service) use ($group) {
|
|
return in_array($service->subType, $group);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Retrieves additional services for a specific participant by group.
|
|
*
|
|
* Filters additional services by group and participant index mapping.
|
|
* Returns services that are assigned to the specified participant.
|
|
*
|
|
* @param int $participantIndex The participant index to filter by
|
|
* @param mixed $group The service group(s) to filter by
|
|
*
|
|
* @return array<Service> The filtered services for the participant
|
|
*/
|
|
public function getAdditionalServicesForParticipantByGroup(int $participantIndex, mixed $group): array
|
|
{
|
|
$selectedServices = $this->getAdditionalServicesByGroup($group);
|
|
|
|
return array_filter($selectedServices, function (Service $service) use ($participantIndex) {
|
|
return in_array($participantIndex, $service->mapping);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Retrieves transportation service for a specific participant and direction.
|
|
*
|
|
* Finds the transportation service that matches the participant index
|
|
* and travel direction (e.g., 'H' for outbound, 'R' for inbound).
|
|
*
|
|
* @param int $participantIndex The participant index to search for
|
|
* @param string $direction The travel direction ('H' or 'R')
|
|
*
|
|
* @return Service|null The matching transportation service or null if not found
|
|
*/
|
|
public function getTransportationServiceForParticipantAndDirection(
|
|
int $participantIndex,
|
|
string $direction,
|
|
): ?Service {
|
|
foreach ($this->transportationServices as $service) {
|
|
if ($service->direction !== $direction) {
|
|
continue;
|
|
}
|
|
if (in_array($participantIndex, $service->mapping)) {
|
|
return $service;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Retrieves pickup service for a specific participant.
|
|
*
|
|
* Finds the pickup service assigned to the specified participant
|
|
* from the outbound pickup services.
|
|
*
|
|
* @param int $participantIndex The participant index to search for
|
|
*
|
|
* @return Pickup|null The matching pickup service or null if not found
|
|
*/
|
|
public function getPickupForParticipant(int $participantIndex): ?Pickup
|
|
{
|
|
foreach ($this->pickupsOutbound as $pickup) {
|
|
if (in_array($participantIndex, $pickup->mapping)) {
|
|
return $pickup;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Gets the insurance assigned to a specific participant.
|
|
*
|
|
* @param int $participantIndex The participant index (0-based)
|
|
*
|
|
* @return Insurance|null The assigned insurance or null if none assigned
|
|
*/
|
|
public function getInsuranceForParticipant(int $participantIndex): ?Insurance
|
|
{
|
|
foreach ($this->insurances as $insurance) {
|
|
if (in_array($participantIndex, $insurance->mapping ?? [], true)) {
|
|
return $insurance;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Retrieves ski pass for a specific participant.
|
|
*
|
|
* Since each participant can only have one ski pass, this method returns
|
|
* the single ski pass assigned to the participant or null if none is assigned.
|
|
*
|
|
* @param int $participantIndex The participant index to search for
|
|
*
|
|
* @return Service|null The participant's ski pass or null if not found
|
|
*/
|
|
public function getSkiPassForParticipant(int $participantIndex): ?Service
|
|
{
|
|
$skiPasses = $this->getAdditionalServicesByGroup('SPA');
|
|
|
|
foreach ($skiPasses as $service) {
|
|
if (in_array($participantIndex, $service->mapping)) {
|
|
return $service;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Retrieves rental insurance for a specific participant.
|
|
*/
|
|
public function getRentalInsuranceForParticipant(int $participantIndex): ?Service
|
|
{
|
|
$rentalInsurances = $this->getAdditionalServicesByGroup(Constants::TOKEN_RENTAL_INSURANCE);
|
|
|
|
foreach ($rentalInsurances as $service) {
|
|
if (in_array($participantIndex, $service->mapping)) {
|
|
return $service;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Retrieves room assignment for a specific participant.
|
|
*
|
|
* Finds the room assigned to the specified participant
|
|
* based on the room mapping configuration.
|
|
*
|
|
* @param int $participantIndex The participant index to search for
|
|
*
|
|
* @return Room|null The matching room or null if not found
|
|
*/
|
|
public function getRoomForParticipant(int $participantIndex): ?Room
|
|
{
|
|
foreach ($this->rooms as $room) {
|
|
if (in_array($participantIndex, $room->mapping)) {
|
|
return $room;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Calculates the total price for a specific participant.
|
|
*
|
|
* Sums up all services, surcharges, and room costs assigned to the participant.
|
|
* Includes mandatory services that apply to all participants.
|
|
*
|
|
* @param int $participantIndex The participant index to calculate for
|
|
*
|
|
* @return float The total price for the participant
|
|
*/
|
|
public function getPriceForParticipant(int $participantIndex): float
|
|
{
|
|
$price = 0.0;
|
|
|
|
// Sum up all services
|
|
foreach ([...$this->transportationServices, ...$this->additionalServices] as $service) {
|
|
if ((in_array($participantIndex, $service->mapping) || true === $service->mandatory)
|
|
&& isset($service->individualPrice[$participantIndex])) {
|
|
$price += $service->individualPrice[$participantIndex] ?? 0;
|
|
}
|
|
}
|
|
|
|
// Sum up all surcharges
|
|
foreach ($this->surcharges as $surcharge) {
|
|
if (in_array($participantIndex, $surcharge->mapping)
|
|
&& isset($surcharge->individualPrice[$participantIndex])) {
|
|
$price += $surcharge->individualPrice[$participantIndex] ?? 0;
|
|
}
|
|
}
|
|
|
|
$room = $this->getRoomForParticipant($participantIndex);
|
|
if (null !== $room && isset($room->individualPrice[$participantIndex])) {
|
|
$price += $room->individualPrice[$participantIndex] ?? 0;
|
|
}
|
|
|
|
return $price;
|
|
}
|
|
|
|
/**
|
|
* Retrieves surcharges for a specific participant.
|
|
*
|
|
* Filters surcharges based on participant index mapping.
|
|
*
|
|
* @param int $participantIndex The participant index to filter by
|
|
*
|
|
* @return array<Surcharge> The surcharges assigned to the participant
|
|
*/
|
|
public function getSurchargesForParticipant(int $participantIndex): array
|
|
{
|
|
return array_filter($this->surcharges, function (Surcharge $surcharge) use ($participantIndex) {
|
|
return in_array($participantIndex, $surcharge->mapping);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Calculates the total price for all participants.
|
|
*
|
|
* Sums up the individual prices for all participants in the booking.
|
|
*
|
|
* @return float The calculated total price for all participants
|
|
*/
|
|
public function getCalculatedTotalPrice(): float
|
|
{
|
|
$totalPrice = 0.0;
|
|
|
|
foreach ($this->participants as $index => $participant) {
|
|
$totalPrice += $this->getPriceForParticipant($index);
|
|
}
|
|
|
|
return $totalPrice;
|
|
}
|
|
|
|
/**
|
|
* Determines if the booking is editable.
|
|
*
|
|
* A booking is editable if the travel date is in the future and
|
|
* the status is not cancelled ('S') or unknown ('U').
|
|
*
|
|
* @return bool True if the booking can be edited, false otherwise
|
|
*/
|
|
public function isEditable(): bool
|
|
{
|
|
return $this->travelDate > new \DateTimeImmutable() && false === in_array($this->status, ['S', 'U']);
|
|
}
|
|
}
|