feat: booking details pdf

This commit is contained in:
Björn Fromme
2026-08-18 14:26:24 +02:00
parent d3666c4618
commit 2d7a02341d
19 changed files with 1054 additions and 100 deletions
+26 -1
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Service;
use App\Email\EmailAttachmentInterface;
use App\Email\Mailer;
use App\Entity\Groups\Accommodation;
use App\Entity\Groups\AccommodationBooking;
@@ -39,6 +40,7 @@ class AccommodationBookingService
private readonly CmsDataProvider $cmsDataProvider,
private readonly AccommodationBookingLinkSigner $linkSigner,
private readonly AccommodationBookingBreakdownCalculator $breakdownCalculator,
private readonly AccommodationBookingPdfGenerator $pdfGenerator,
private readonly string $accommodationEmail,
) {
}
@@ -396,6 +398,7 @@ class AccommodationBookingService
string $subject,
string $template,
string $errorMessage,
bool $withPdf = false,
): void {
if (null === $to || '' === trim($to)) {
$this->logger->warning($errorMessage, [
@@ -421,7 +424,7 @@ class AccommodationBookingService
'to' => $to,
'subject' => $subject,
'template' => $template,
'attachments' => [],
'attachments' => $withPdf ? $this->bookingPdfAttachment($booking) : [],
],
);
} catch (\Throwable $e) {
@@ -562,9 +565,31 @@ class AccommodationBookingService
'Deine Buchung ist bestätigt',
'email/booking_confirmed_customer.html.twig',
'Failed to send booking confirmed customer email',
withPdf: true,
);
}
/**
* A missing price snapshot must not cost the customer their confirmation, so a failed
* render degrades to sending the email without the document. Called only once a
* recipient is known, so no PDF is rendered for a mail that never goes out.
*
* @return list<EmailAttachmentInterface>
*/
private function bookingPdfAttachment(AccommodationBooking $booking): array
{
try {
return [$this->pdfGenerator->createAttachment($booking)];
} catch (\Throwable $e) {
$this->logger->warning('Failed to attach the booking PDF to the confirmation email', [
'booking_id' => $booking->getId(),
'error' => $e->getMessage(),
]);
return [];
}
}
private function accessLinkOrNull(AccommodationBooking $booking): ?string
{
return null !== $booking->getAccessLinkIssuedAt() ? $this->linkSigner->sign($booking) : null;