fix: refuse implausible accommodation booking prices
This commit is contained in:
1 parent
773cd4f847
commit
56adf72d12
16 files changed
+628
-15
No files matched your search
@@ -12,6 +12,7 @@ use App\Entity\Groups\AccommodationPrice;
|
||||
use App\Enum\Groups\AccommodationBookingOrigin;
|
||||
use App\Enum\Groups\AccommodationBookingStatus;
|
||||
use App\Enum\Groups\AdditionalServiceType;
|
||||
use App\Exception\ImplausibleBookingPriceException;
|
||||
use App\Form\Model\AccommodationBookingDto;
|
||||
use App\Model\AccommodationBookingQueryParams;
|
||||
use App\Repository\Groups\AccommodationPriceRepository;
|
||||
@@ -65,6 +66,18 @@ class AccommodationBookingServiceTest extends TestCase
|
||||
$service->initFromParams(new AccommodationBookingQueryParams('HOTEL', '2026-02-31', '2026-03-05'));
|
||||
}
|
||||
|
||||
public function testApplyDatesRejectsAnImplausiblyLongStay(): void
|
||||
{
|
||||
// The customer picks from a calendar, so this is a hand-built URL rather than a typo —
|
||||
// the cap is the same one the backoffice form enforces on the entity.
|
||||
$service = $this->createServiceWithAccommodation();
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage(sprintf('Der Aufenthalt darf höchstens %d Nächte umfassen.', AccommodationBooking::MAX_NIGHTS));
|
||||
|
||||
$service->applyDates(new AccommodationBookingDto(), '2026-02-28', '2226-03-01');
|
||||
}
|
||||
|
||||
public function testIssueAccessLinkForDirectBookingSetsTimestampForDirectBooking(): void
|
||||
{
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
@@ -962,6 +975,33 @@ class AccommodationBookingServiceTest extends TestCase
|
||||
self::assertNull($booking->getTotalPrice(), 'the frozen price belonged to the old house');
|
||||
}
|
||||
|
||||
public function testChangeAccommodationLeavesNothingHalfAppliedWhenTheNewHousePricesImplausibly(): void
|
||||
{
|
||||
// The swap and the dropped services are already on the managed entity by the time the
|
||||
// price is computed, so a refusal has to put the row back rather than leave a booking
|
||||
// sitting at a new house with no price.
|
||||
$breakdown = ['total' => AccommodationBooking::MAX_TOTAL_PRICE + 1, 'currency' => 'EUR'];
|
||||
$breakdownCalculator = $this->createStub(AccommodationBookingBreakdownCalculator::class);
|
||||
$breakdownCalculator->method('computeCurrent')->willReturn($breakdown);
|
||||
$breakdownCalculator->method('withDiscounts')
|
||||
->willReturn($breakdown + ['discounts' => [], 'discountedTotal' => AccommodationBooking::MAX_TOTAL_PRICE + 1]);
|
||||
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
$entityManager->expects(self::once())->method('refresh');
|
||||
$entityManager->expects(self::never())->method('flush');
|
||||
|
||||
$service = $this->createServiceWithAccommodation(
|
||||
entityManager: $entityManager,
|
||||
breakdownCalculator: $breakdownCalculator,
|
||||
);
|
||||
|
||||
$booking = $this->draftWithServices();
|
||||
|
||||
$this->expectException(ImplausibleBookingPriceException::class);
|
||||
|
||||
$service->changeAccommodation($booking, (new Accommodation())->setName('Berghaus')->setCalendarCode('BERG'));
|
||||
}
|
||||
|
||||
public function testChangeAccommodationNoOpsForANonDraft(): void
|
||||
{
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
|
||||
Reference in new issue
Block a user