wip: group inquiries and booking
This commit is contained in:
1 parent
18a890e50e
commit
e7bfb19ac9
71 files changed
+2731
-512
No files matched your search
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Service;
|
||||
|
||||
use App\Entity\Groups\AccommodationBooking;
|
||||
use App\Repository\Groups\AccommodationPriceRepository;
|
||||
use App\Service\AccommodationBookingBreakdownCalculator;
|
||||
use App\Service\GroupsPriceCalculator;
|
||||
use App\Service\PriceTimelineBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AccommodationBookingBreakdownCalculatorTest extends TestCase
|
||||
{
|
||||
public function testComputeReturnsStoredSnapshotWithoutLoadingCurrentPrices(): void
|
||||
{
|
||||
$snapshot = ['total' => 12345, 'currency' => 'EUR'];
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setPriceSnapshot($snapshot, 12345, 'EUR', 1);
|
||||
|
||||
$priceRepository = $this->createMock(AccommodationPriceRepository::class);
|
||||
$priceRepository->expects(self::never())->method('findByHotelCodeAndDateRange');
|
||||
|
||||
$calculator = new AccommodationBookingBreakdownCalculator(
|
||||
new GroupsPriceCalculator(new PriceTimelineBuilder(), [
|
||||
'runningCostsEur' => 0,
|
||||
'runningCostsChf' => 0,
|
||||
'undersubscription30Eur' => 0,
|
||||
'undersubscription30Chf' => 0,
|
||||
'undersubscription40Eur' => 0,
|
||||
'undersubscription40Chf' => 0,
|
||||
]),
|
||||
$priceRepository,
|
||||
);
|
||||
|
||||
self::assertSame($snapshot, $calculator->compute($booking));
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ use App\Entity\Groups\AccommodationBooking;
|
||||
use App\Service\AccommodationBookingLinkSigner;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
class AccommodationBookingLinkSignerTest extends TestCase
|
||||
@@ -94,6 +96,77 @@ class AccommodationBookingLinkSignerTest extends TestCase
|
||||
self::assertSame('2026-04-01T00:00:00+00:00', $signer->expiresAt($booking)?->format(\DATE_ATOM));
|
||||
}
|
||||
|
||||
public function testSessionIsAuthorizedAfterAuthorizeSession(): void
|
||||
{
|
||||
$booking = $this->bookingWithAccessLink();
|
||||
$signer = $this->createSigner();
|
||||
$request = $this->requestWithSession();
|
||||
|
||||
self::assertFalse($signer->isSessionAuthorized($request, $booking));
|
||||
|
||||
$signer->authorizeSession($request, $booking);
|
||||
|
||||
self::assertTrue($signer->isSessionAuthorized($request, $booking));
|
||||
}
|
||||
|
||||
public function testSessionAuthorizationIsPerBooking(): void
|
||||
{
|
||||
$booking = $this->bookingWithAccessLink();
|
||||
$otherBooking = $this->bookingWithAccessLink();
|
||||
$signer = $this->createSigner();
|
||||
$request = $this->requestWithSession();
|
||||
|
||||
$signer->authorizeSession($request, $booking);
|
||||
|
||||
self::assertTrue($signer->isSessionAuthorized($request, $booking));
|
||||
self::assertFalse($signer->isSessionAuthorized($request, $otherBooking));
|
||||
}
|
||||
|
||||
public function testSessionAuthorizationIsRevokedWhenLinkIsRegenerated(): void
|
||||
{
|
||||
$booking = $this->bookingWithAccessLink();
|
||||
$signer = $this->createSigner();
|
||||
$request = $this->requestWithSession();
|
||||
|
||||
$signer->authorizeSession($request, $booking);
|
||||
self::assertTrue($signer->isSessionAuthorized($request, $booking));
|
||||
|
||||
// Regenerating the access link overwrites accessLinkIssuedAt — the
|
||||
// previously-authorized session no longer matches.
|
||||
$booking->setAccessLinkIssuedAt(new \DateTimeImmutable('+1 minute'));
|
||||
|
||||
self::assertFalse($signer->isSessionAuthorized($request, $booking));
|
||||
}
|
||||
|
||||
public function testSessionAuthorizationFailsPastTtlEvenIfSessionMatches(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setAccessLinkIssuedAt(new \DateTimeImmutable('-91 days'));
|
||||
$signer = $this->createSigner();
|
||||
$request = $this->requestWithSession();
|
||||
|
||||
$signer->authorizeSession($request, $booking);
|
||||
|
||||
self::assertFalse($signer->isSessionAuthorized($request, $booking));
|
||||
}
|
||||
|
||||
public function testSessionAuthorizationFailsWithoutAccessLinkIssuedAt(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$signer = $this->createSigner();
|
||||
$request = $this->requestWithSession();
|
||||
|
||||
self::assertFalse($signer->isSessionAuthorized($request, $booking));
|
||||
}
|
||||
|
||||
private function requestWithSession(): Request
|
||||
{
|
||||
$request = Request::create('https://example.com/');
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
private function bookingWithAccessLink(): AccommodationBooking
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
|
||||
@@ -175,7 +175,7 @@ class AccommodationBookingServiceTest extends TestCase
|
||||
$service->sendCustomerConfirmationEmail($booking);
|
||||
}
|
||||
|
||||
public function testRegenerateAccessLinkAndNotifyCustomerAlwaysOverwritesAndSends(): void
|
||||
public function testRegenerateAccessLinkOverwritesAccessLinkIssuedAt(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setEmail('[email protected]');
|
||||
@@ -190,7 +190,7 @@ class AccommodationBookingServiceTest extends TestCase
|
||||
$breakdownCalculator->method('compute')->willReturn(null);
|
||||
|
||||
$mailer = $this->createMock(Mailer::class);
|
||||
$mailer->expects(self::once())->method('createAndSendEmail');
|
||||
$mailer->expects(self::never())->method('createAndSendEmail');
|
||||
|
||||
$service = $this->createServiceWithAccommodation(
|
||||
entityManager: $entityManager,
|
||||
@@ -198,7 +198,7 @@ class AccommodationBookingServiceTest extends TestCase
|
||||
breakdownCalculator: $breakdownCalculator,
|
||||
);
|
||||
|
||||
$service->regenerateAccessLinkAndNotifyCustomer($booking);
|
||||
$service->regenerateAccessLink($booking);
|
||||
|
||||
self::assertNotSame($previousIssuedAt, $booking->getAccessLinkIssuedAt());
|
||||
}
|
||||
@@ -234,6 +234,39 @@ class AccommodationBookingServiceTest extends TestCase
|
||||
self::assertNull($booking->getAcceptedAt());
|
||||
}
|
||||
|
||||
public function testRefreshPriceSnapshotStoresDiscountedFinalTotal(): void
|
||||
{
|
||||
$booking = new AccommodationBooking();
|
||||
$booking->setAccommodationDiscount(10);
|
||||
$booking->setBoardServiceDiscount(20);
|
||||
$booking->setAdditionalServicesDiscount(50);
|
||||
|
||||
$breakdown = [
|
||||
'total' => 12345,
|
||||
'currency' => 'CHF',
|
||||
'basePrice' => 8000,
|
||||
'additionalPersonsPrice' => 2000,
|
||||
'boardPrice' => 1000,
|
||||
'servicesPrice' => 500,
|
||||
];
|
||||
|
||||
$breakdownCalculator = $this->createMock(AccommodationBookingBreakdownCalculator::class);
|
||||
$breakdownCalculator
|
||||
->expects(self::once())
|
||||
->method('computeCurrent')
|
||||
->with($booking)
|
||||
->willReturn($breakdown);
|
||||
|
||||
$service = $this->createServiceWithAccommodation(breakdownCalculator: $breakdownCalculator);
|
||||
$service->refreshPriceSnapshot($booking);
|
||||
|
||||
// accommodation: (8000+2000)*10% = 1000, board: 1000*20% = 200, services: 500*50% = 250
|
||||
self::assertSame($breakdown, $booking->getPriceBreakdown());
|
||||
self::assertSame(12345 - 1000 - 200 - 250, $booking->getTotalPrice());
|
||||
self::assertSame('CHF', $booking->getPricingCurrency());
|
||||
self::assertSame(1, $booking->getPricingVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccommodationPrice[] $prices
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user