feat: offer the accommodation booking PDF download in every status

This commit is contained in:
fromme committed 2026-10-01 08:46:06 +02:00
1 parent 67c0c2fb0c
commit ec10ca3623
4 files changed
+16 -38

No files matched your search

@@ -21,12 +21,8 @@ class PdfController extends AbstractController
#[Route('/admin/accommodation-booking/{id}/pdf', name: 'app_admin_accommodationbooking_pdf')] #[Route('/admin/accommodation-booking/{id}/pdf', name: 'app_admin_accommodationbooking_pdf')]
public function index(AccommodationBooking $booking): Response public function index(AccommodationBooking $booking): Response
{ {
if (false === $booking->isConfirmed()) { // Offered in every status, so the office can check the document before it goes out
$this->addFlash('warning', 'Ein PDF kann nur für bestätigte Buchungen erstellt werden.'); // with the confirmation email; it labels itself Angebot or Buchung accordingly.
return $this->redirectToRoute('app_admin_accommodationbooking_show', ['id' => $booking->getId()]);
}
try { try {
return $this->pdfGenerator->createDownloadResponse($booking); return $this->pdfGenerator->createDownloadResponse($booking);
} catch (\RuntimeException $e) { } catch (\RuntimeException $e) {
@@ -102,11 +102,9 @@
<twig:dropdown:hxbutton url="{{ path('app_admin_accommodationbooking_duplicate', { 'id': booking.id, 'r': return_url() }) }}"> <twig:dropdown:hxbutton url="{{ path('app_admin_accommodationbooking_duplicate', { 'id': booking.id, 'r': return_url() }) }}">
duplizieren duplizieren
</twig:dropdown:hxbutton> </twig:dropdown:hxbutton>
{% if booking.confirmed %} <twig:dropdown:link url="{{ path('app_admin_accommodationbooking_pdf', { 'id': booking.id }) }}">
<twig:dropdown:link url="{{ path('app_admin_accommodationbooking_pdf', { 'id': booking.id }) }}"> PDF herunterladen
PDF herunterladen </twig:dropdown:link>
</twig:dropdown:link>
{% endif %}
{# A record that has been in front of the customer gets discarded, {# A record that has been in front of the customer gets discarded,
not removed — see DeleteController. #} not removed — see DeleteController. #}
{% if booking.draft %} {% if booking.draft %}
@@ -313,12 +313,10 @@
hx-swap="beforeend"> hx-swap="beforeend">
duplizieren duplizieren
</button> </button>
{% if booking.confirmed %} <a href="{{ path('app_admin_accommodationbooking_pdf', { 'id': booking.id }) }}"
<a href="{{ path('app_admin_accommodationbooking_pdf', { 'id': booking.id }) }}" class="button button--neutral button--small w-full">
class="button button--neutral button--small w-full"> PDF herunterladen
PDF herunterladen </a>
</a>
{% endif %}
</div> </div>
{% if not booking.confirmed and not booking.discarded %} {% if not booking.confirmed and not booking.discarded %}
<div class="mt-4 pt-3 border-t border-gray-200 text-center"> <div class="mt-4 pt-3 border-t border-gray-200 text-center">
@@ -18,9 +18,10 @@ use Symfony\Component\HttpFoundation\Response;
*/ */
class PdfControllerTest extends TestCase class PdfControllerTest extends TestCase
{ {
public function testAConfirmedBookingIsDownloadedAsPdf(): void #[DataProvider('statuses')]
public function testABookingInAnyStatusIsDownloadedAsPdf(AccommodationBookingStatus $status): void
{ {
$booking = $this->booking(AccommodationBookingStatus::Confirmed); $booking = $this->booking($status);
$generator = $this->createMock(AccommodationBookingPdfGenerator::class); $generator = $this->createMock(AccommodationBookingPdfGenerator::class);
$generator->expects(self::once()) $generator->expects(self::once())
@@ -33,29 +34,14 @@ class PdfControllerTest extends TestCase
self::assertSame(Response::HTTP_OK, $response->getStatusCode()); self::assertSame(Response::HTTP_OK, $response->getStatusCode());
} }
#[DataProvider('nonConfirmedStatuses')]
public function testABookingThatIsNotConfirmedCannotBeDownloaded(AccommodationBookingStatus $status): void
{
$generator = $this->createMock(AccommodationBookingPdfGenerator::class);
$generator->expects(self::never())->method('createDownloadResponse');
$controller = new TestablePdfController($generator);
$response = $controller->index($this->booking($status));
self::assertSame(Response::HTTP_FOUND, $response->getStatusCode());
self::assertSame(['warning'], array_column($controller->flashes, 'type'));
}
/** /**
* @return iterable<string, array{AccommodationBookingStatus}> * @return iterable<string, array{AccommodationBookingStatus}>
*/ */
public static function nonConfirmedStatuses(): iterable public static function statuses(): iterable
{ {
yield 'draft' => [AccommodationBookingStatus::Draft]; foreach (AccommodationBookingStatus::cases() as $status) {
yield 'open' => [AccommodationBookingStatus::Open]; yield $status->name => [$status];
yield 'received' => [AccommodationBookingStatus::Received]; }
yield 'discarded' => [AccommodationBookingStatus::Discarded];
} }
public function testAFailingGeneratorRedirectsWithAFlash(): void public function testAFailingGeneratorRedirectsWithAFlash(): void