chore: adopt namespace pattern for accommodation booking controllers

This commit is contained in:
Björn Fromme
2026-08-19 17:07:57 +02:00
parent e105c611be
commit d5f9f4ef10
25 changed files with 137 additions and 138 deletions
@@ -2,15 +2,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Groups; namespace App\Controller\Groups\Booking;
use App\Exception\AccommodationSessionNotFoundException; use App\Exception\AccommodationSessionNotFoundException;
use App\Form\Model\AccommodationBookingDto; use App\Form\Model\AccommodationBookingDto;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController as SymfonyAbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
abstract class AbstractAccommodationController extends AbstractController abstract class AbstractController extends SymfonyAbstractController
{ {
protected function validateStepAccess(AccommodationBookingDto $dto, int $expectedStep): ?RedirectResponse protected function validateStepAccess(AccommodationBookingDto $dto, int $expectedStep): ?RedirectResponse
{ {
@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Groups; namespace App\Controller\Groups\Booking;
use App\Htmx\HxTrait; use App\Htmx\HxTrait;
use App\Model\AccommodationBookingQueryParams; use App\Model\AccommodationBookingQueryParams;
@@ -14,7 +14,7 @@ use Symfony\Component\HttpFoundation\Session\FlashBagAwareSessionInterface;
use Symfony\Component\HttpKernel\Attribute\MapQueryString; use Symfony\Component\HttpKernel\Attribute\MapQueryString;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class IndexController extends AbstractAccommodationController class IndexController extends AbstractController
{ {
use HxTrait; use HxTrait;
@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Groups; namespace App\Controller\Groups\Booking;
use App\BpnConnect\ContingentsClient; use App\BpnConnect\ContingentsClient;
use App\BpnConnect\Exception\BpnConnectException; use App\BpnConnect\Exception\BpnConnectException;
@@ -24,7 +24,7 @@ use Symfony\Component\Routing\Attribute\Route;
use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface; use Symfony\Contracts\Cache\ItemInterface;
class Step1Controller extends AbstractAccommodationController class Step1Controller extends AbstractController
{ {
use HxTrait; use HxTrait;
@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Groups; namespace App\Controller\Groups\Booking;
use App\Entity\Groups\AdditionalService; use App\Entity\Groups\AdditionalService;
use App\Entity\Groups\BoardService; use App\Entity\Groups\BoardService;
@@ -19,7 +19,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class Step2Controller extends AbstractAccommodationController class Step2Controller extends AbstractController
{ {
use HxTrait; use HxTrait;
@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Groups; namespace App\Controller\Groups\Booking;
use App\Entity\Groups\Accommodation; use App\Entity\Groups\Accommodation;
use App\Exception\AccommodationSessionNotFoundException; use App\Exception\AccommodationSessionNotFoundException;
@@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class Step3Controller extends AbstractAccommodationController class Step3Controller extends AbstractController
{ {
public function __construct( public function __construct(
private readonly AccommodationBookingService $bookingService, private readonly AccommodationBookingService $bookingService,
@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Groups; namespace App\Controller\Groups\Booking;
use App\Entity\Groups\Accommodation; use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AdditionalService; use App\Entity\Groups\AdditionalService;
@@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class Step4Controller extends AbstractAccommodationController class Step4Controller extends AbstractController
{ {
use HxTrait; use HxTrait;
@@ -80,7 +80,7 @@ class Step4Controller extends AbstractAccommodationController
$inquiryForm = $this->createForm(AccommodationInquiryConfirmationType::class); $inquiryForm = $this->createForm(AccommodationInquiryConfirmationType::class);
return $this->render('groups/booking/_step4_inquiry_confirmation_modal.html.twig', [ return $this->render('groups/booking/modal_inquiry_confirmation.html.twig', [
'inquiryForm' => $inquiryForm, 'inquiryForm' => $inquiryForm,
]); ]);
} }
@@ -107,7 +107,7 @@ class Step4Controller extends AbstractAccommodationController
return $this->htmxRedirect($request, $this->generateUrl('app_groups_booking_success')); return $this->htmxRedirect($request, $this->generateUrl('app_groups_booking_success'));
} }
return $this->render('groups/booking/_step4_booking_confirmation_modal.html.twig', [ return $this->render('groups/booking/modal_booking_confirmation.html.twig', [
'confirmationForm' => $confirmationForm, 'confirmationForm' => $confirmationForm,
]); ]);
} }
@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Controller\Groups; namespace App\Controller\Groups\Offer;
use App\Entity\Groups\AccommodationBooking; use App\Entity\Groups\AccommodationBooking;
use App\Form\Model\OfferAcceptDto; use App\Form\Model\OfferAcceptDto;
@@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
class OfferController extends AbstractController class IndexController extends AbstractController
{ {
use HxTrait; use HxTrait;
@@ -38,35 +38,35 @@ class OfferController extends AbstractController
* authorizes the session for this booking, and redirects to the plain * authorizes the session for this booking, and redirects to the plain
* (session-gated) offer page nothing downstream needs the signature again. * (session-gated) offer page nothing downstream needs the signature again.
*/ */
#[Route(path: '/groups/booking/offer/{uuid}', name: 'app_groups_booking_offer', methods: ['GET'])] #[Route(path: '/groups/booking/offer/{uuid}', name: 'app_groups_offer', methods: ['GET'])]
public function access(string $uuid, Request $request): Response public function access(string $uuid, Request $request): Response
{ {
$booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]); $booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]);
if (null === $booking || false === $this->linkSigner->isValidLinkRequest($request, $booking)) { if (null === $booking || false === $this->linkSigner->isValidLinkRequest($request, $booking)) {
return $this->render('groups/booking/offer_unavailable.html.twig'); return $this->render('groups/offer/unavailable.html.twig');
} }
if (!$this->isCustomerVisible($booking)) { if (!$this->isCustomerVisible($booking)) {
return $this->render('groups/booking/offer_unavailable.html.twig'); return $this->render('groups/offer/unavailable.html.twig');
} }
$this->linkSigner->authorizeSession($request, $booking); $this->linkSigner->authorizeSession($request, $booking);
return new RedirectResponse($this->generateUrl('app_groups_booking_offer_view', ['uuid' => $uuid])); return new RedirectResponse($this->generateUrl('app_groups_offer_view', ['uuid' => $uuid]));
} }
#[Route(path: '/groups/booking/offer/{uuid}/view', name: 'app_groups_booking_offer_view', methods: ['GET'])] #[Route(path: '/groups/booking/offer/{uuid}/view', name: 'app_groups_offer_view', methods: ['GET'])]
public function view(string $uuid, Request $request): Response public function view(string $uuid, Request $request): Response
{ {
$booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]); $booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]);
if (null === $booking || false === $this->linkSigner->isSessionAuthorized($request, $booking)) { if (null === $booking || false === $this->linkSigner->isSessionAuthorized($request, $booking)) {
return $this->render('groups/booking/offer_unavailable.html.twig'); return $this->render('groups/offer/unavailable.html.twig');
} }
if (!$this->isCustomerVisible($booking)) { if (!$this->isCustomerVisible($booking)) {
return $this->render('groups/booking/offer_unavailable.html.twig'); return $this->render('groups/offer/unavailable.html.twig');
} }
$accommodation = $booking->getAccommodation() ?? throw $this->createNotFoundException('Booking has no accommodation.'); $accommodation = $booking->getAccommodation() ?? throw $this->createNotFoundException('Booking has no accommodation.');
@@ -78,14 +78,14 @@ class OfferController extends AbstractController
priceBreakdown: $priceBreakdown, priceBreakdown: $priceBreakdown,
); );
return $this->render('groups/booking/offer.html.twig', [ return $this->render('groups/offer/view.html.twig', [
'booking' => $booking, 'booking' => $booking,
'priceBreakdown' => $priceBreakdown, 'priceBreakdown' => $priceBreakdown,
'ctx' => $ctx, 'ctx' => $ctx,
]); ]);
} }
#[Route(path: '/groups/booking/offer/{uuid}/confirm', name: 'app_groups_booking_offer_confirm', methods: ['GET', 'POST'])] #[Route(path: '/groups/booking/offer/{uuid}/confirm', name: 'app_groups_offer_confirm', methods: ['GET', 'POST'])]
public function confirm(string $uuid, Request $request): Response public function confirm(string $uuid, Request $request): Response
{ {
$booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]); $booking = $this->bookingRepository->findOneBy(['uuid' => $uuid]);
@@ -115,7 +115,7 @@ class OfferController extends AbstractController
return $this->redirectToOfferPage($request, $uuid); return $this->redirectToOfferPage($request, $uuid);
} }
return $this->render('groups/booking/_offer_accept_confirmation_modal.html.twig', [ return $this->render('groups/offer/modal_accept_confirmation.html.twig', [
'booking' => $booking, 'booking' => $booking,
'confirmationForm' => $confirmationForm, 'confirmationForm' => $confirmationForm,
]); ]);
@@ -138,7 +138,7 @@ class OfferController extends AbstractController
*/ */
private function redirectToOfferPage(Request $request, string $uuid): Response private function redirectToOfferPage(Request $request, string $uuid): Response
{ {
$url = $this->generateUrl('app_groups_booking_offer_view', ['uuid' => $uuid]); $url = $this->generateUrl('app_groups_offer_view', ['uuid' => $uuid]);
return $this->htmxRedirect($request, $url); return $this->htmxRedirect($request, $url);
} }
@@ -34,7 +34,7 @@ class AccommodationBookingLinkSigner
} }
$url = $this->urlGenerator->generate( $url = $this->urlGenerator->generate(
'app_groups_booking_offer', 'app_groups_offer',
['uuid' => $booking->getUuid(), self::TIMESTAMP_PARAM => $issuedAt->getTimestamp()], ['uuid' => $booking->getUuid(), self::TIMESTAMP_PARAM => $issuedAt->getTimestamp()],
UrlGeneratorInterface::ABSOLUTE_URL, UrlGeneratorInterface::ABSOLUTE_URL,
); );
+1 -1
View File
@@ -1,5 +1,5 @@
{#- Prices only — travel dates and group size belong to _stay_details.html.twig and the {#- Prices only — travel dates and group size belong to _stay_details.html.twig and the
PDF's own data block. Mirrors groups/booking/_offer_summary.html.twig, but with inline PDF's own data block. Mirrors groups/offer/_summary.html.twig, but with inline
styles: neither the email layout nor dompdf ships table styling or Tailwind. styles: neither the email layout nor dompdf ships table styling or Tailwind.
Context: booking, priceBreakdown, currency (set in AccommodationBookingService and Context: booking, priceBreakdown, currency (set in AccommodationBookingService and
AccommodationBookingPdfGenerator). -#} AccommodationBookingPdfGenerator). -#}
@@ -1,31 +0,0 @@
<div class="border border-primary-bg mb-4">
<div class="p-2 bg-primary-bg uppercase font-semibold">Persönliche Daten</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-4 gap-y-2 p-2 text-sm">
<div>
<span class="text-gray-600 font-semibold">Gruppenname:</span>
{{ dto.groupName }}
</div>
<div>
<span class="text-gray-600 font-semibold">Name:</span>
{{ dto.salutation }} {{ dto.firstName }} {{ dto.lastName }}
</div>
<div>
<span class="text-gray-600 font-semibold">E-Mail:</span>
{{ dto.email }}
</div>
<div>
<span class="text-gray-600 font-semibold">Telefon:</span>
{{ dto.phone }}
</div>
<div class="md:col-span-2">
<span class="text-gray-600 font-semibold">Adresse:</span>
{{ dto.street }}, {{ dto.zip }} {{ dto.city }}
</div>
{% if dto.remarks %}
<div class="md:col-span-2">
<span class="text-gray-600 font-semibold">Anmerkungen:</span>
{{ dto.remarks }}
</div>
{% endif %}
</div>
</div>
@@ -1,42 +0,0 @@
{% set selectedBoardService = null %}
{% for service in ctx.boardServices %}
{% if service.id == dto.selectedBoardServiceId %}
{% set selectedBoardService = service %}
{% endif %}
{% endfor %}
{% set selectedAdditionalServices = ctx.additionalServices|filter(service => service.id in dto.selectedAdditionalServiceIds) %}
<div class="border border-primary-bg mb-4">
<div class="p-2 bg-primary-bg uppercase font-semibold">Ausgewählte Leistungen</div>
<div class="p-2 text-sm">
<div class="mb-2">
<span class="text-gray-600 font-semibold">Verpflegung:</span>
{% if selectedBoardService %}
{{ selectedBoardService.label }}
{% if selectedBoardService.price > 0 %}
{{ (selectedBoardService.price / 100)|format_currency(ctx.accommodation.currency) }} pro Person und Nacht
{% endif %}
{% if selectedBoardService.description %}
<div class="text-xs text-gray-500">{{ selectedBoardService.description|nl2br }}</div>
{% endif %}
{% else %}
Selbstversorgung
{% endif %}
</div>
{% if selectedAdditionalServices is not empty %}
<div>
<span class="text-gray-600 font-semibold">Zusatzleistungen:</span>
<ul class="list-disc list-inside">
{% for service in selectedAdditionalServices %}
<li>
{{ service.label }}
{{ (service.price / 100)|format_currency(ctx.accommodation.currency) }} {{ service.type.label|trans }}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
+74 -2
View File
@@ -40,8 +40,80 @@
} %} } %}
{% endif %} {% endif %}
{% include 'groups/booking/_step4_services_recap.html.twig' with { 'dto': dto, 'ctx': ctx } %} {% set selectedBoardService = null %}
{% include 'groups/booking/_step4_personal_data_recap.html.twig' with { 'dto': dto } %} {% for service in ctx.boardServices %}
{% if service.id == dto.selectedBoardServiceId %}
{% set selectedBoardService = service %}
{% endif %}
{% endfor %}
{% set selectedAdditionalServices = ctx.additionalServices|filter(service => service.id in dto.selectedAdditionalServiceIds) %}
<div class="border border-primary-bg mb-4">
<div class="p-2 bg-primary-bg uppercase font-semibold">Ausgewählte Leistungen</div>
<div class="p-2 text-sm">
<div class="mb-2">
<span class="text-gray-600 font-semibold">Verpflegung:</span>
{% if selectedBoardService %}
{{ selectedBoardService.label }}
{% if selectedBoardService.price > 0 %}
{{ (selectedBoardService.price / 100)|format_currency(ctx.accommodation.currency) }} pro Person und Nacht
{% endif %}
{% if selectedBoardService.description %}
<div class="text-xs text-gray-500">{{ selectedBoardService.description|nl2br }}</div>
{% endif %}
{% else %}
Selbstversorgung
{% endif %}
</div>
{% if selectedAdditionalServices is not empty %}
<div>
<span class="text-gray-600 font-semibold">Zusatzleistungen:</span>
<ul class="list-disc list-inside">
{% for service in selectedAdditionalServices %}
<li>
{{ service.label }}
{{ (service.price / 100)|format_currency(ctx.accommodation.currency) }} {{ service.type.label|trans }}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
<div class="border border-primary-bg mb-4">
<div class="p-2 bg-primary-bg uppercase font-semibold">Persönliche Daten</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-x-4 gap-y-2 p-2 text-sm">
<div>
<span class="text-gray-600 font-semibold">Gruppenname:</span>
{{ dto.groupName }}
</div>
<div>
<span class="text-gray-600 font-semibold">Name:</span>
{{ dto.salutation }} {{ dto.firstName }} {{ dto.lastName }}
</div>
<div>
<span class="text-gray-600 font-semibold">E-Mail:</span>
{{ dto.email }}
</div>
<div>
<span class="text-gray-600 font-semibold">Telefon:</span>
{{ dto.phone }}
</div>
<div class="md:col-span-2">
<span class="text-gray-600 font-semibold">Adresse:</span>
{{ dto.street }}, {{ dto.zip }} {{ dto.city }}
</div>
{% if dto.remarks %}
<div class="md:col-span-2">
<span class="text-gray-600 font-semibold">Anmerkungen:</span>
{{ dto.remarks }}
</div>
{% endif %}
</div>
</div>
</div> </div>
</div> </div>
@@ -12,7 +12,7 @@
</p> </p>
{{ form_start(confirmationForm, { {{ form_start(confirmationForm, {
'action': path('app_groups_booking_offer_confirm', { uuid: booking.uuid }), 'action': path('app_groups_offer_confirm', { uuid: booking.uuid }),
'attr': { 'attr': {
'hx-target': '#htmx-modal', 'hx-target': '#htmx-modal',
'hx-swap': 'outerHTML', 'hx-swap': 'outerHTML',
@@ -37,7 +37,7 @@
<div id="booking-summary-wrapper" <div id="booking-summary-wrapper"
class="order-1 lg:order-2 lg:flex-1 lg:min-h-0 lg:col-span-2" class="order-1 lg:order-2 lg:flex-1 lg:min-h-0 lg:col-span-2"
{{ stimulus_controller('toggle', { 'open': false }, { 'closed': 'hidden', 'open': 'absolute inset-0 z-20', 'iconOpen': 'rotate-180' }) }}> {{ stimulus_controller('toggle', { 'open': false }, { 'closed': 'hidden', 'open': 'absolute inset-0 z-20', 'iconOpen': 'rotate-180' }) }}>
{% include 'groups/booking/_offer_summary.html.twig' with { {% include 'groups/offer/_summary.html.twig' with {
booking: booking, booking: booking,
ctx: ctx, ctx: ctx,
currency: currency, currency: currency,
@@ -78,7 +78,7 @@
<div> <div>
<button type="button" <button type="button"
class="button button--primary w-full" class="button button--primary w-full"
hx-get="{{ path('app_groups_booking_offer_confirm', { uuid: booking.uuid }) }}" hx-get="{{ path('app_groups_offer_confirm', { uuid: booking.uuid }) }}"
hx-target="body" hx-target="body"
hx-swap="beforeend"> hx-swap="beforeend">
Angebot verbindlich buchen Angebot verbindlich buchen
@@ -2,9 +2,9 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Tests\Controller\Accommodation; namespace App\Tests\Controller\Groups\Booking;
use App\Controller\Groups\IndexController; use App\Controller\Groups\Booking\IndexController;
use App\Service\AccommodationBookingService; use App\Service\AccommodationBookingService;
use App\Service\AccommodationSessionManager; use App\Service\AccommodationSessionManager;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@@ -2,14 +2,14 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Tests\Controller\Groups; namespace App\Tests\Controller\Groups\Booking;
use App\BpnConnect\ContingentsClient; use App\BpnConnect\ContingentsClient;
use App\BpnConnect\Model\ContingentCalendarEntry; use App\BpnConnect\Model\ContingentCalendarEntry;
use App\BpnConnect\Model\ContingentCalendarMeta; use App\BpnConnect\Model\ContingentCalendarMeta;
use App\BpnConnect\Model\ContingentCalendarResponse; use App\BpnConnect\Model\ContingentCalendarResponse;
use App\BpnConnect\Model\ContingentStatus; use App\BpnConnect\Model\ContingentStatus;
use App\Controller\Groups\Step1Controller; use App\Controller\Groups\Booking\Step1Controller;
use App\Entity\Groups\AccommodationPrice; use App\Entity\Groups\AccommodationPrice;
use App\Repository\Groups\AccommodationPriceRepository; use App\Repository\Groups\AccommodationPriceRepository;
use App\Service\AccommodationBookingService; use App\Service\AccommodationBookingService;
@@ -2,10 +2,10 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Tests\Controller\Accommodation; namespace App\Tests\Controller\Groups\Booking;
use App\BpnConnect\ContingentsClient; use App\BpnConnect\ContingentsClient;
use App\Controller\Groups\Step1Controller; use App\Controller\Groups\Booking\Step1Controller;
use App\Entity\Groups\Accommodation; use App\Entity\Groups\Accommodation;
use App\Form\Model\AccommodationBookingDto; use App\Form\Model\AccommodationBookingDto;
use App\Repository\Groups\AccommodationPriceRepository; use App\Repository\Groups\AccommodationPriceRepository;
@@ -2,9 +2,9 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Tests\Controller\Accommodation; namespace App\Tests\Controller\Groups\Booking;
use App\Controller\Groups\Step2Controller; use App\Controller\Groups\Booking\Step2Controller;
use App\Entity\Groups\Accommodation; use App\Entity\Groups\Accommodation;
use App\Form\Model\AccommodationBookingDto; use App\Form\Model\AccommodationBookingDto;
use App\Model\InquiryStatus; use App\Model\InquiryStatus;
@@ -2,9 +2,9 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Tests\Controller\Accommodation; namespace App\Tests\Controller\Groups\Booking;
use App\Controller\Groups\Step3Controller; use App\Controller\Groups\Booking\Step3Controller;
use App\Entity\Groups\Accommodation; use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AdditionalService; use App\Entity\Groups\AdditionalService;
use App\Entity\Groups\BoardService; use App\Entity\Groups\BoardService;
@@ -2,9 +2,9 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Tests\Controller\Groups; namespace App\Tests\Controller\Groups\Booking;
use App\Controller\Groups\Step4Controller; use App\Controller\Groups\Booking\Step4Controller;
use App\Entity\Groups\Accommodation; use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AccommodationBooking; use App\Entity\Groups\AccommodationBooking;
use App\Enum\Groups\AccommodationBookingOrigin; use App\Enum\Groups\AccommodationBookingOrigin;
@@ -192,7 +192,7 @@ class Step4ControllerTest extends TestCase
$response = $controller->confirmInquiry($request); $response = $controller->confirmInquiry($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
self::assertSame('groups/booking/_step4_inquiry_confirmation_modal.html.twig', $controller->renderedView); self::assertSame('groups/booking/modal_inquiry_confirmation.html.twig', $controller->renderedView);
} }
public function testConfirmInquiryRedirectsToStep3WhenNotYetReached(): void public function testConfirmInquiryRedirectsToStep3WhenNotYetReached(): void
@@ -251,7 +251,7 @@ class Step4ControllerTest extends TestCase
$response = $controller->confirm($request); $response = $controller->confirm($request);
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
self::assertSame('groups/booking/_step4_booking_confirmation_modal.html.twig', $controller->renderedView); self::assertSame('groups/booking/modal_booking_confirmation.html.twig', $controller->renderedView);
self::assertSame($confirmationForm, $controller->renderedParameters['confirmationForm']); self::assertSame($confirmationForm, $controller->renderedParameters['confirmationForm']);
self::assertSame($dto, $sessionManager->getDto($request)); self::assertSame($dto, $sessionManager->getDto($request));
} }
@@ -335,7 +335,7 @@ class Step4ControllerTest extends TestCase
self::assertSame(200, $response->getStatusCode()); self::assertSame(200, $response->getStatusCode());
self::assertFalse($response->headers->has('HX-Redirect')); self::assertFalse($response->headers->has('HX-Redirect'));
self::assertSame('groups/booking/_step4_booking_confirmation_modal.html.twig', $controller->renderedView); self::assertSame('groups/booking/modal_booking_confirmation.html.twig', $controller->renderedView);
self::assertNotNull($sessionManager->getDto($request)); self::assertNotNull($sessionManager->getDto($request));
} }
} }
@@ -2,9 +2,9 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Tests\Controller\Groups; namespace App\Tests\Controller\Groups\Offer;
use App\Controller\Groups\OfferController; use App\Controller\Groups\Offer\IndexController;
use App\Entity\Groups\Accommodation; use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AccommodationBooking; use App\Entity\Groups\AccommodationBooking;
use App\Enum\Groups\AccommodationBookingStatus; use App\Enum\Groups\AccommodationBookingStatus;
@@ -22,7 +22,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
class OfferControllerTest extends TestCase class IndexControllerTest extends TestCase
{ {
public function testAccessAuthorizesSessionAndRedirectsToView(): void public function testAccessAuthorizesSessionAndRedirectsToView(): void
{ {
@@ -46,7 +46,7 @@ class OfferControllerTest extends TestCase
$response = $controller->access($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid())); $response = $controller->access($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid()));
self::assertInstanceOf(RedirectResponse::class, $response); self::assertInstanceOf(RedirectResponse::class, $response);
self::assertSame('/app_groups_booking_offer_view?uuid='.$booking->getUuid(), $response->getTargetUrl()); self::assertSame('/app_groups_offer_view?uuid='.$booking->getUuid(), $response->getTargetUrl());
} }
public function testAccessRendersUnavailableForInvalidLink(): void public function testAccessRendersUnavailableForInvalidLink(): void
@@ -70,7 +70,7 @@ class OfferControllerTest extends TestCase
$response = $controller->access($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid())); $response = $controller->access($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid()));
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertSame('groups/booking/offer_unavailable.html.twig', $controller->renderedView); self::assertSame('groups/offer/unavailable.html.twig', $controller->renderedView);
} }
public function testAccessRendersUnavailableForUnknownUuid(): void public function testAccessRendersUnavailableForUnknownUuid(): void
@@ -91,7 +91,7 @@ class OfferControllerTest extends TestCase
$response = $controller->access('unknown-uuid', Request::create('/groups/booking/offer/unknown-uuid')); $response = $controller->access('unknown-uuid', Request::create('/groups/booking/offer/unknown-uuid'));
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertSame('groups/booking/offer_unavailable.html.twig', $controller->renderedView); self::assertSame('groups/offer/unavailable.html.twig', $controller->renderedView);
} }
/** /**
@@ -119,7 +119,7 @@ class OfferControllerTest extends TestCase
$response = $controller->access($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid())); $response = $controller->access($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid()));
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertSame('groups/booking/offer_unavailable.html.twig', $controller->renderedView); self::assertSame('groups/offer/unavailable.html.twig', $controller->renderedView);
} }
/** /**
@@ -167,7 +167,7 @@ class OfferControllerTest extends TestCase
$response = $controller->view($booking->getUuid(), $request); $response = $controller->view($booking->getUuid(), $request);
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertSame('groups/booking/offer_unavailable.html.twig', $controller->renderedView); self::assertSame('groups/offer/unavailable.html.twig', $controller->renderedView);
} }
public function testViewRendersOfferWhenSessionAuthorized(): void public function testViewRendersOfferWhenSessionAuthorized(): void
@@ -197,7 +197,7 @@ class OfferControllerTest extends TestCase
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertSame('<html>offer</html>', $response->getContent()); self::assertSame('<html>offer</html>', $response->getContent());
self::assertSame('groups/booking/offer.html.twig', $controller->renderedView); self::assertSame('groups/offer/view.html.twig', $controller->renderedView);
self::assertSame($booking, $controller->renderedParameters['booking']); self::assertSame($booking, $controller->renderedParameters['booking']);
self::assertSame(['total' => 1000], $controller->renderedParameters['priceBreakdown']); self::assertSame(['total' => 1000], $controller->renderedParameters['priceBreakdown']);
self::assertSame($booking->getAccommodation(), $controller->renderedParameters['ctx']->accommodation); self::assertSame($booking->getAccommodation(), $controller->renderedParameters['ctx']->accommodation);
@@ -223,7 +223,7 @@ class OfferControllerTest extends TestCase
$response = $controller->view($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid().'/view')); $response = $controller->view($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid().'/view'));
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertSame('groups/booking/offer_unavailable.html.twig', $controller->renderedView); self::assertSame('groups/offer/unavailable.html.twig', $controller->renderedView);
} }
public function testConfirmGetRendersModalWithFreshForm(): void public function testConfirmGetRendersModalWithFreshForm(): void
@@ -253,7 +253,7 @@ class OfferControllerTest extends TestCase
$response = $controller->confirm($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid().'/confirm')); $response = $controller->confirm($booking->getUuid(), Request::create('/groups/booking/offer/'.$booking->getUuid().'/confirm'));
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertSame('groups/booking/_offer_accept_confirmation_modal.html.twig', $controller->renderedView); self::assertSame('groups/offer/modal_accept_confirmation.html.twig', $controller->renderedView);
self::assertSame($booking, $controller->renderedParameters['booking']); self::assertSame($booking, $controller->renderedParameters['booking']);
self::assertSame($confirmationForm, $controller->renderedParameters['confirmationForm']); self::assertSame($confirmationForm, $controller->renderedParameters['confirmationForm']);
@@ -294,7 +294,7 @@ class OfferControllerTest extends TestCase
$response = $controller->confirm($booking->getUuid(), $request); $response = $controller->confirm($booking->getUuid(), $request);
self::assertInstanceOf(RedirectResponse::class, $response); self::assertInstanceOf(RedirectResponse::class, $response);
self::assertSame('/app_groups_booking_offer_view?uuid='.$booking->getUuid(), $response->getTargetUrl()); self::assertSame('/app_groups_offer_view?uuid='.$booking->getUuid(), $response->getTargetUrl());
self::assertSame([['type' => 'success', 'message' => 'Deine Buchung ist bei uns eingegangen. Sobald sie geprüft ist, erhältst du eine Bestätigung per E-Mail.']], $controller->flashes); self::assertSame([['type' => 'success', 'message' => 'Deine Buchung ist bei uns eingegangen. Sobald sie geprüft ist, erhältst du eine Bestätigung per E-Mail.']], $controller->flashes);
} }
@@ -365,7 +365,7 @@ class OfferControllerTest extends TestCase
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
self::assertFalse($response->headers->has('HX-Redirect')); self::assertFalse($response->headers->has('HX-Redirect'));
self::assertSame('groups/booking/_offer_accept_confirmation_modal.html.twig', $controller->renderedView); self::assertSame('groups/offer/modal_accept_confirmation.html.twig', $controller->renderedView);
} }
public function testConfirmRedirectsWhenAlreadyAccepted(): void public function testConfirmRedirectsWhenAlreadyAccepted(): void
@@ -434,7 +434,7 @@ class OfferControllerTest extends TestCase
} }
} }
final class TestableOfferController extends OfferController final class TestableOfferController extends IndexController
{ {
public ?string $renderedView = null; public ?string $renderedView = null;
@@ -494,7 +494,7 @@ final class TestableOfferController extends OfferController
$this->renderedView = $view; $this->renderedView = $view;
$this->renderedParameters = $parameters; $this->renderedParameters = $parameters;
if ('groups/booking/offer.html.twig' === $view) { if ('groups/offer/view.html.twig' === $view) {
$content = null !== $parameters['booking']->getAcceptedAt() ? '<html>confirmed</html>' : '<html>offer</html>'; $content = null !== $parameters['booking']->getAcceptedAt() ? '<html>confirmed</html>' : '<html>offer</html>';
} else { } else {
$content = '<html>unavailable</html>'; $content = '<html>unavailable</html>';