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
@@ -10,10 +10,13 @@ use App\Entity\Groups\Accommodation;
|
||||
use App\Entity\Groups\AccommodationBooking;
|
||||
use App\Entity\Groups\AccommodationPrice;
|
||||
use App\Enum\Groups\AccommodationBookingOrigin;
|
||||
use App\Enum\Groups\AccommodationBookingPeriodPosition;
|
||||
use App\Enum\Groups\AccommodationBookingStatus;
|
||||
use App\Enum\Groups\AdditionalServiceType;
|
||||
use App\Exception\ImplausibleBookingPriceException;
|
||||
use App\Form\Model\AccommodationBookingDto;
|
||||
use App\Form\Model\AccommodationBookingPeriodDto;
|
||||
use App\Form\Model\AccommodationBookingPeriodLineDto;
|
||||
use App\Model\AccommodationBookingQueryParams;
|
||||
use App\Repository\Groups\AccommodationPriceRepository;
|
||||
use App\Repository\Groups\AccommodationRepository;
|
||||
@@ -951,7 +954,86 @@ class AccommodationBookingServiceTest extends TestCase
|
||||
self::assertSame($breakdown, $booking->getPriceBreakdown(), 'the derived keys must not be persisted');
|
||||
self::assertSame(10895, $booking->getTotalPrice());
|
||||
self::assertSame('CHF', $booking->getPricingCurrency());
|
||||
self::assertSame(1, $booking->getPricingVersion());
|
||||
self::assertSame(2, $booking->getPricingVersion());
|
||||
}
|
||||
|
||||
public function testSplittingOffAPeriodRepricesAndWritesTheBooking(): void
|
||||
{
|
||||
$booking = $this->periodBooking();
|
||||
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
$entityManager->expects(self::once())->method('flush');
|
||||
$breakdownCalculator = $this->createMock(AccommodationBookingBreakdownCalculator::class);
|
||||
$breakdownCalculator->expects(self::once())->method('computeCurrent')->with($booking)->willReturn(null);
|
||||
|
||||
$service = $this->createServiceWithAccommodation(entityManager: $entityManager, breakdownCalculator: $breakdownCalculator);
|
||||
$violations = $service->splitOffPeriod(
|
||||
$booking,
|
||||
AccommodationBookingPeriodPosition::Leading,
|
||||
new AccommodationBookingPeriodDto(1, [3 => new AccommodationBookingPeriodLineDto('Übernachtung', 30000)], 'Vorausteam'),
|
||||
);
|
||||
|
||||
self::assertCount(0, $violations);
|
||||
self::assertSame('Vorausteam', $booking->getLeadingPeriod()?->getLabel());
|
||||
self::assertSame([['label' => 'Übernachtung', 'amount' => 30000]], $booking->getLeadingPeriod()?->getLines());
|
||||
self::assertSame(6, $booking->getMainNights());
|
||||
}
|
||||
|
||||
public function testASplitThatLeavesTheGroupNoNightIsNeitherPricedNorWritten(): void
|
||||
{
|
||||
$booking = $this->periodBooking();
|
||||
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
$entityManager->expects(self::never())->method('flush');
|
||||
$breakdownCalculator = $this->createMock(AccommodationBookingBreakdownCalculator::class);
|
||||
$breakdownCalculator->expects(self::never())->method('computeCurrent');
|
||||
|
||||
$service = $this->createServiceWithAccommodation(entityManager: $entityManager, breakdownCalculator: $breakdownCalculator);
|
||||
$violations = $service->splitOffPeriod($booking, AccommodationBookingPeriodPosition::Trailing, new AccommodationBookingPeriodDto(7));
|
||||
|
||||
self::assertCount(1, $violations);
|
||||
}
|
||||
|
||||
public function testUpdatingAPeriodChangesItsLengthAndLines(): void
|
||||
{
|
||||
$booking = $this->periodBooking();
|
||||
$period = $booking->splitOffPeriod(AccommodationBookingPeriodPosition::Trailing, 1);
|
||||
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
$entityManager->expects(self::once())->method('flush');
|
||||
|
||||
$service = $this->createServiceWithAccommodation(entityManager: $entityManager);
|
||||
$violations = $service->updatePeriod($booking, $period, new AccommodationBookingPeriodDto(2, [new AccommodationBookingPeriodLineDto('Abbau', 5000)]));
|
||||
|
||||
self::assertCount(0, $violations);
|
||||
self::assertSame(2, $period->getNights());
|
||||
self::assertSame([['label' => 'Abbau', 'amount' => 5000]], $period->getLines());
|
||||
self::assertSame(5, $booking->getMainNights());
|
||||
}
|
||||
|
||||
public function testRemovingAPeriodGivesItsNightsBackToTheGroup(): void
|
||||
{
|
||||
$booking = $this->periodBooking();
|
||||
$period = $booking->splitOffPeriod(AccommodationBookingPeriodPosition::Leading, 2);
|
||||
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
$entityManager->expects(self::once())->method('flush');
|
||||
|
||||
$service = $this->createServiceWithAccommodation(entityManager: $entityManager);
|
||||
$violations = $service->removePeriod($booking, $period);
|
||||
|
||||
self::assertCount(0, $violations);
|
||||
self::assertTrue($booking->getPeriods()->isEmpty());
|
||||
self::assertSame(7, $booking->getMainNights());
|
||||
}
|
||||
|
||||
private function periodBooking(): AccommodationBooking
|
||||
{
|
||||
return (new AccommodationBooking())
|
||||
->setAccommodation((new Accommodation())->setCalendarCode('HOTEL'))
|
||||
->setDateFrom(new \DateTimeImmutable('2026-07-01'))
|
||||
->setDateTo(new \DateTimeImmutable('2026-07-08'))
|
||||
->setPaxCount(20);
|
||||
}
|
||||
|
||||
public function testChangeAccommodationSwapsTheHouseAndDropsTheBookedServices(): void
|
||||
|
||||
Reference in new issue
Block a user