From 6127d84d1131fb74b65e73ef4abb8927ad1339e3 Mon Sep 17 00:00:00 2001 From: Clemens Creutzburg Date: Sun, 19 Jul 2026 23:39:52 +0200 Subject: [PATCH] =?UTF-8?q?PDF=20Fusszeile=20und=20watermak=20mandantenf?= =?UTF-8?q?=C3=A4hig=20gemacht.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/saas-auth.php | 25 ++++++++++-- .../0017_saas_pdf_footer_watermark.sql | 3 ++ exportKaffeeliste.php | 40 ++++++++++++++++--- mandant-einstellungen.php | 10 +++++ 4 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 database/migrations/0017_saas_pdf_footer_watermark.sql diff --git a/app/saas-auth.php b/app/saas-auth.php index 682ea90..c6ab1d4 100644 --- a/app/saas-auth.php +++ b/app/saas-auth.php @@ -276,7 +276,9 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array ts.negative_warning_cents, ts.pdf_show_empty_rows, ts.pdf_split_mode, - ts.pdf_row_height_px + ts.pdf_row_height_px, + ts.pdf_watermark_text, + ts.pdf_footer_text FROM tenants t LEFT JOIN tenant_settings ts ON ts.tenant_id = t.id WHERE t.id = ? @@ -312,6 +314,8 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array 'pdf_show_empty_rows' => (int)$settings['pdf_show_empty_rows'], 'pdf_split_mode' => (string)$settings['pdf_split_mode'], 'pdf_row_height_px' => (int)$settings['pdf_row_height_px'], + 'pdf_watermark_text' => (string)$settings['pdf_watermark_text'], + 'pdf_footer_text' => (string)$settings['pdf_footer_text'], ]; } @@ -327,6 +331,8 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr $paypalUrlTemplate = trim((string)($input['paypal_url_template'] ?? '')); $pdfSplitMode = trim((string)($input['pdf_split_mode'] ?? 'drinking_behavior')); $pdfRowHeightPx = filter_var($input['pdf_row_height_px'] ?? null, FILTER_VALIDATE_INT); + $pdfWatermarkText = trim((string)($input['pdf_watermark_text'] ?? '')); + $pdfFooterText = trim((string)($input['pdf_footer_text'] ?? '')); $errors = []; if (strlen($tenantName) < 3 || strlen($tenantName) > 255) { @@ -356,6 +362,12 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr if (!in_array($pdfSplitMode, ['drinking_behavior', 'alphabetical'], true)) { $errors[] = 'Die Sortierung für den Ausdruck ist ungültig.'; } + if (strlen($pdfWatermarkText) > 500) { + $errors[] = 'Der Wasserzeichen-Text im Ausdruck ist zu lang (max. 500 Zeichen).'; + } + if (strlen($pdfFooterText) > 500) { + $errors[] = 'Der Fußzeilen-Hinweis im Ausdruck ist zu lang (max. 500 Zeichen).'; + } if ($pdfRowHeightPx === false || $pdfRowHeightPx < 10 || $pdfRowHeightPx > 60) { $errors[] = 'Die Zeilenhöhe im Ausdruck muss zwischen 10 und 60 Pixel liegen.'; } @@ -382,8 +394,9 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr 'INSERT INTO tenant_settings (tenant_id, mark_price_cents, self_entry_enabled, paypal_enabled, paypal_url_template, sheet_window_days, negative_warning_cents, - pdf_show_empty_rows, pdf_split_mode, pdf_row_height_px) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + pdf_show_empty_rows, pdf_split_mode, pdf_row_height_px, + pdf_watermark_text, pdf_footer_text) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE mark_price_cents = VALUES(mark_price_cents), self_entry_enabled = VALUES(self_entry_enabled), @@ -393,7 +406,9 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr negative_warning_cents = VALUES(negative_warning_cents), pdf_show_empty_rows = VALUES(pdf_show_empty_rows), pdf_split_mode = VALUES(pdf_split_mode), - pdf_row_height_px = VALUES(pdf_row_height_px)' + pdf_row_height_px = VALUES(pdf_row_height_px), + pdf_watermark_text = VALUES(pdf_watermark_text), + pdf_footer_text = VALUES(pdf_footer_text)' ); $stmt->execute([ $tenantId, @@ -406,6 +421,8 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr $pdfShowEmptyRows, $pdfSplitMode, (int)$pdfRowHeightPx, + $pdfWatermarkText, + $pdfFooterText, ]); $pdo->commit(); diff --git a/database/migrations/0017_saas_pdf_footer_watermark.sql b/database/migrations/0017_saas_pdf_footer_watermark.sql new file mode 100644 index 0000000..65d183f --- /dev/null +++ b/database/migrations/0017_saas_pdf_footer_watermark.sql @@ -0,0 +1,3 @@ +ALTER TABLE tenant_settings + ADD COLUMN pdf_watermark_text VARCHAR(500) NOT NULL DEFAULT 'Fragen oder Unklarheiten? Bitte lies zuerst die FAQs hinter dieser Liste!' AFTER pdf_row_height_px, + ADD COLUMN pdf_footer_text VARCHAR(500) NOT NULL DEFAULT '' AFTER pdf_watermark_text; diff --git a/exportKaffeeliste.php b/exportKaffeeliste.php index c01024a..51c1db7 100644 --- a/exportKaffeeliste.php +++ b/exportKaffeeliste.php @@ -32,13 +32,18 @@ $markPrice = number_format(($settings['mark_price_cents'] ?? 20) / 100, 2, ',', $showEmptyRows = (int)($settings['pdf_show_empty_rows'] ?? 1) === 1; $splitMode = (string)($settings['pdf_split_mode'] ?? 'drinking_behavior'); $adminRowHeightPx = (int)($settings['pdf_row_height_px'] ?? 16); +$watermarkText = trim((string)($settings['pdf_watermark_text'] ?? '')); +$footerText = trim((string)($settings['pdf_footer_text'] ?? '')); // Ab dieser Mitgliederzahl wird auf zwei Seiten (Vorder-/Rueckseite) statt // einer einzelnen Seite gedruckt. define('EXPORT_MULTI_PAGE_THRESHOLD', 50); // Platzbudget in TCPDF-HTML-"px" fuer die Datenzeilen einer Seite, kalibriert -// an der bisherigen Ausgabe (63 Zeilen a 16px auf einer vollen A4-Seite). -define('EXPORT_PAGE_ROW_BUDGET_PX', 63 * 16); +// an der bisherigen Ausgabe (63 Zeilen a 16px auf einer vollen A4-Seite). Ist +// eine Fusszeile konfiguriert, wird ihr reservierter Platz abgezogen, damit +// die letzte Tabellenzeile sie nicht ueberlappt. +define('EXPORT_FOOTER_RESERVE_PX', 40); +define('EXPORT_PAGE_ROW_BUDGET_PX', (63 * 16) - ($footerText !== '' ? EXPORT_FOOTER_RESERVE_PX : 0)); // Technischer Mindestwert, nur als letzte Bremse gegen 0/negative Hoehen bei // absurd hohen Teilnehmerzahlen - kein gestalterisches Minimum. define('EXPORT_HARD_MIN_ROW_HEIGHT_PX', 6); @@ -130,24 +135,49 @@ function export_render_page_html(array $teilnehmer, string $titel, string $hinwe require_once(__DIR__ . '/TCPDF/tcpdf.php'); class MyCustomPDFWithWatermark extends TCPDF { + public string $watermarkText = ''; + public string $footerText = ''; + public function Header() { + if (trim($this->watermarkText) === '') { + return; + } + $bMargin = $this->getBreakMargin(); $auto_page_break = $this->AutoPageBreak; $this->SetAutoPageBreak(false, 0); - $img_file = __DIR__ . '/watermark.jpg'; $this->SetAlpha(0.35); - $this->Image($img_file, 0, 0, 223, 280, '', '', '', false, 300, '', false, false, 0); + $this->SetFont('helvetica', '', 14); + $this->SetTextColor(0, 0, 0); + foreach ([40, 140, 240] as $y) { + $this->MultiCell(90, 0, $this->watermarkText, 0, 'L', false, 1, 110, $y); + } $this->SetAlpha(1); + $this->SetFont('helvetica', '', 9.5); $this->SetAutoPageBreak($auto_page_break, $bMargin); $this->setPageMark(); } + + public function Footer() { + if (trim($this->footerText) === '') { + return; + } + + $this->SetY(-15); + $this->SetFont('helvetica', '', 8); + $this->SetTextColor(120, 120, 120); + $this->Cell(0, 10, $this->footerText, 0, 0, 'C'); + $this->SetTextColor(0, 0, 0); + } } $pdf = new MyCustomPDFWithWatermark(PDF_PAGE_ORIENTATION, 'mm', 'A4', true, 'UTF-8', false); +$pdf->watermarkText = $watermarkText; +$pdf->footerText = $footerText; $pdf->SetHeaderData("", 0, "Kaffeestrichliste", ""); -$pdf->SetPrintFooter(false); +$pdf->SetPrintFooter(true); $pdf->SetMargins('5', '5', '5'); $pdf->SetAutoPageBreak(true, 5); $pdf->SetFont('helvetica', '', 9.5); diff --git a/mandant-einstellungen.php b/mandant-einstellungen.php index e756e0a..b89cd1c 100644 --- a/mandant-einstellungen.php +++ b/mandant-einstellungen.php @@ -35,6 +35,8 @@ if ($canManageSettings) { 'pdf_show_empty_rows' => !empty($_POST['pdf_show_empty_rows']) ? 1 : 0, 'pdf_split_mode' => $_POST['pdf_split_mode'] ?? 'drinking_behavior', 'pdf_row_height_px' => $_POST['pdf_row_height_px'] ?? 16, + 'pdf_watermark_text' => $_POST['pdf_watermark_text'] ?? '', + 'pdf_footer_text' => $_POST['pdf_footer_text'] ?? '', ]; } } else { @@ -132,6 +134,14 @@ include 'nav.php'; +
+ + +
+
+ + +