feat: split nights off an accommodation booking as separate periods
addresses #869f6z36v
This commit is contained in:
1 parent
972839286c
commit
7001bc0cf2
35 files changed
+2221
-25
No files matched your search
@@ -86,6 +86,8 @@ class GroupsPriceCalculator
|
||||
$nights,
|
||||
$dateFrom,
|
||||
$dateTo,
|
||||
$dateFrom,
|
||||
$nights,
|
||||
$prices,
|
||||
$boardService?->getPrice(),
|
||||
array_map(
|
||||
@@ -104,7 +106,12 @@ class GroupsPriceCalculator
|
||||
* Same calculation but using frozen snapshot data from an AccommodationBooking entity
|
||||
* instead of live catalog entities.
|
||||
*
|
||||
* @param AccommodationPrice[] $prices all prices overlapping the booking window
|
||||
* $dateFrom/$dateTo/$nights are the nights being priced, which is the main period of a booking
|
||||
* with split-off periods. $stayDateFrom and $stayNights describe the whole stay, which the
|
||||
* includedPax floor and the short-term surcharge are judged on, so that splitting nights off
|
||||
* never changes either.
|
||||
*
|
||||
* @param AccommodationPrice[] $prices all prices overlapping the whole stay
|
||||
* @param list<array{label: string, price: int, type: string, originalServiceId: int|null}> $additionalServiceSnapshots
|
||||
*
|
||||
* @return array{
|
||||
@@ -131,6 +138,8 @@ class GroupsPriceCalculator
|
||||
int $nights,
|
||||
\DateTimeImmutable $dateFrom,
|
||||
\DateTimeImmutable $dateTo,
|
||||
\DateTimeImmutable $stayDateFrom,
|
||||
int $stayNights,
|
||||
array $prices,
|
||||
?int $boardServicePricePerPersonNight,
|
||||
array $additionalServiceSnapshots,
|
||||
@@ -151,6 +160,8 @@ class GroupsPriceCalculator
|
||||
$nights,
|
||||
$dateFrom,
|
||||
$dateTo,
|
||||
$stayDateFrom,
|
||||
$stayNights,
|
||||
$prices,
|
||||
$boardServicePricePerPersonNight,
|
||||
$items,
|
||||
@@ -186,15 +197,19 @@ class GroupsPriceCalculator
|
||||
int $nights,
|
||||
\DateTimeImmutable $dateFrom,
|
||||
\DateTimeImmutable $dateTo,
|
||||
\DateTimeImmutable $stayDateFrom,
|
||||
int $stayNights,
|
||||
array $prices,
|
||||
?int $boardServicePricePerPersonNight,
|
||||
array $additionalItems,
|
||||
string $currency,
|
||||
): array {
|
||||
// Derive effectivePax: children 0–3 don't count, but never drop below includedPax
|
||||
// Derive effectivePax: children 0–3 don't count, but never drop below includedPax.
|
||||
// The floor comes from the stay's first night, not the priced range's, so that splitting
|
||||
// nights off the start cannot swap in another price row's floor.
|
||||
$firstCandidates = array_values(array_filter(
|
||||
$prices,
|
||||
fn (AccommodationPrice $p) => $p->getDateFrom() <= $dateFrom && $p->getDateTo() >= $dateFrom,
|
||||
fn (AccommodationPrice $p) => $p->getDateFrom() <= $stayDateFrom && $p->getDateTo() >= $stayDateFrom,
|
||||
));
|
||||
$firstWinner = $this->priceTimelineBuilder->resolveWinner($firstCandidates);
|
||||
$includedPaxFloor = $firstWinner?->getIncludedPax() ?? 1;
|
||||
@@ -239,10 +254,10 @@ class GroupsPriceCalculator
|
||||
}
|
||||
}
|
||||
|
||||
// Rule 3: short-term surcharge
|
||||
// Rule 3: short-term surcharge, judged on the whole stay but charged on the priced nights
|
||||
$shortTermSurcharge = 0;
|
||||
if (isset(self::SHORT_TERM_FACTORS[$nights])) {
|
||||
$shortTermSurcharge = (int) round(($basePrice + $additionalPersonsPrice) * self::SHORT_TERM_FACTORS[$nights] / 100);
|
||||
if (isset(self::SHORT_TERM_FACTORS[$stayNights])) {
|
||||
$shortTermSurcharge = (int) round(($basePrice + $additionalPersonsPrice) * self::SHORT_TERM_FACTORS[$stayNights] / 100);
|
||||
}
|
||||
|
||||
// Board is only billable — and only triggers the catering surcharge — when it costs
|
||||
|
||||
Reference in new issue
Block a user