chore: adopt namespace pattern for accommodation booking controllers
This commit is contained in:
+3
-3
@@ -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
-2
@@ -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
-2
@@ -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
-2
@@ -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
-2
@@ -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,
|
||||||
+4
-4
@@ -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,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
+13
-13
@@ -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,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>
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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
-2
@@ -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
-2
@@ -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
-2
@@ -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
-2
@@ -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
-2
@@ -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;
|
||||||
+5
-5
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+15
-15
@@ -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>';
|
||||||
Reference in New Issue
Block a user