pdf erstellung aufhrbung der 50 Personen Grenze
This commit is contained in:
+12
-4
@@ -275,7 +275,8 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array
|
|||||||
ts.sheet_window_days,
|
ts.sheet_window_days,
|
||||||
ts.negative_warning_cents,
|
ts.negative_warning_cents,
|
||||||
ts.pdf_show_empty_rows,
|
ts.pdf_show_empty_rows,
|
||||||
ts.pdf_split_mode
|
ts.pdf_split_mode,
|
||||||
|
ts.pdf_row_height_px
|
||||||
FROM tenants t
|
FROM tenants t
|
||||||
LEFT JOIN tenant_settings ts ON ts.tenant_id = t.id
|
LEFT JOIN tenant_settings ts ON ts.tenant_id = t.id
|
||||||
WHERE t.id = ?
|
WHERE t.id = ?
|
||||||
@@ -310,6 +311,7 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array
|
|||||||
'negative_warning_cents' => (int)$settings['negative_warning_cents'],
|
'negative_warning_cents' => (int)$settings['negative_warning_cents'],
|
||||||
'pdf_show_empty_rows' => (int)$settings['pdf_show_empty_rows'],
|
'pdf_show_empty_rows' => (int)$settings['pdf_show_empty_rows'],
|
||||||
'pdf_split_mode' => (string)$settings['pdf_split_mode'],
|
'pdf_split_mode' => (string)$settings['pdf_split_mode'],
|
||||||
|
'pdf_row_height_px' => (int)$settings['pdf_row_height_px'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +326,7 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
$negativeWarningCents = saas_parse_money_cents($input['negative_warning'] ?? '');
|
$negativeWarningCents = saas_parse_money_cents($input['negative_warning'] ?? '');
|
||||||
$paypalUrlTemplate = trim((string)($input['paypal_url_template'] ?? ''));
|
$paypalUrlTemplate = trim((string)($input['paypal_url_template'] ?? ''));
|
||||||
$pdfSplitMode = trim((string)($input['pdf_split_mode'] ?? 'drinking_behavior'));
|
$pdfSplitMode = trim((string)($input['pdf_split_mode'] ?? 'drinking_behavior'));
|
||||||
|
$pdfRowHeightPx = filter_var($input['pdf_row_height_px'] ?? null, FILTER_VALIDATE_INT);
|
||||||
|
|
||||||
$errors = [];
|
$errors = [];
|
||||||
if (strlen($tenantName) < 3 || strlen($tenantName) > 255) {
|
if (strlen($tenantName) < 3 || strlen($tenantName) > 255) {
|
||||||
@@ -353,6 +356,9 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
if (!in_array($pdfSplitMode, ['drinking_behavior', 'alphabetical'], true)) {
|
if (!in_array($pdfSplitMode, ['drinking_behavior', 'alphabetical'], true)) {
|
||||||
$errors[] = 'Die Sortierung für den Ausdruck ist ungültig.';
|
$errors[] = 'Die Sortierung für den Ausdruck ist ungültig.';
|
||||||
}
|
}
|
||||||
|
if ($pdfRowHeightPx === false || $pdfRowHeightPx < 10 || $pdfRowHeightPx > 60) {
|
||||||
|
$errors[] = 'Die Zeilenhöhe im Ausdruck muss zwischen 10 und 60 Pixel liegen.';
|
||||||
|
}
|
||||||
|
|
||||||
if ($errors !== []) {
|
if ($errors !== []) {
|
||||||
return ['ok' => false, 'errors' => $errors];
|
return ['ok' => false, 'errors' => $errors];
|
||||||
@@ -376,8 +382,8 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
'INSERT INTO tenant_settings
|
'INSERT INTO tenant_settings
|
||||||
(tenant_id, mark_price_cents, self_entry_enabled, paypal_enabled,
|
(tenant_id, mark_price_cents, self_entry_enabled, paypal_enabled,
|
||||||
paypal_url_template, sheet_window_days, negative_warning_cents,
|
paypal_url_template, sheet_window_days, negative_warning_cents,
|
||||||
pdf_show_empty_rows, pdf_split_mode)
|
pdf_show_empty_rows, pdf_split_mode, pdf_row_height_px)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
mark_price_cents = VALUES(mark_price_cents),
|
mark_price_cents = VALUES(mark_price_cents),
|
||||||
self_entry_enabled = VALUES(self_entry_enabled),
|
self_entry_enabled = VALUES(self_entry_enabled),
|
||||||
@@ -386,7 +392,8 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
sheet_window_days = VALUES(sheet_window_days),
|
sheet_window_days = VALUES(sheet_window_days),
|
||||||
negative_warning_cents = VALUES(negative_warning_cents),
|
negative_warning_cents = VALUES(negative_warning_cents),
|
||||||
pdf_show_empty_rows = VALUES(pdf_show_empty_rows),
|
pdf_show_empty_rows = VALUES(pdf_show_empty_rows),
|
||||||
pdf_split_mode = VALUES(pdf_split_mode)'
|
pdf_split_mode = VALUES(pdf_split_mode),
|
||||||
|
pdf_row_height_px = VALUES(pdf_row_height_px)'
|
||||||
);
|
);
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
$tenantId,
|
$tenantId,
|
||||||
@@ -398,6 +405,7 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
-abs($negativeWarningCents),
|
-abs($negativeWarningCents),
|
||||||
$pdfShowEmptyRows,
|
$pdfShowEmptyRows,
|
||||||
$pdfSplitMode,
|
$pdfSplitMode,
|
||||||
|
(int)$pdfRowHeightPx,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE tenant_settings
|
||||||
|
ADD COLUMN pdf_row_height_px SMALLINT NOT NULL DEFAULT 16 AFTER pdf_split_mode;
|
||||||
+30
-16
@@ -31,6 +31,7 @@ $windowDays = $settings['sheet_window_days'] ?? 100;
|
|||||||
$markPrice = number_format(($settings['mark_price_cents'] ?? 20) / 100, 2, ',', '.');
|
$markPrice = number_format(($settings['mark_price_cents'] ?? 20) / 100, 2, ',', '.');
|
||||||
$showEmptyRows = (int)($settings['pdf_show_empty_rows'] ?? 1) === 1;
|
$showEmptyRows = (int)($settings['pdf_show_empty_rows'] ?? 1) === 1;
|
||||||
$splitMode = (string)($settings['pdf_split_mode'] ?? 'drinking_behavior');
|
$splitMode = (string)($settings['pdf_split_mode'] ?? 'drinking_behavior');
|
||||||
|
$adminRowHeightPx = (int)($settings['pdf_row_height_px'] ?? 16);
|
||||||
|
|
||||||
// Ab dieser Mitgliederzahl wird auf zwei Seiten (Vorder-/Rueckseite) statt
|
// Ab dieser Mitgliederzahl wird auf zwei Seiten (Vorder-/Rueckseite) statt
|
||||||
// einer einzelnen Seite gedruckt.
|
// einer einzelnen Seite gedruckt.
|
||||||
@@ -38,33 +39,46 @@ define('EXPORT_MULTI_PAGE_THRESHOLD', 50);
|
|||||||
// Platzbudget in TCPDF-HTML-"px" fuer die Datenzeilen einer Seite, kalibriert
|
// Platzbudget in TCPDF-HTML-"px" fuer die Datenzeilen einer Seite, kalibriert
|
||||||
// an der bisherigen Ausgabe (63 Zeilen a 16px auf einer vollen A4-Seite).
|
// an der bisherigen Ausgabe (63 Zeilen a 16px auf einer vollen A4-Seite).
|
||||||
define('EXPORT_PAGE_ROW_BUDGET_PX', 63 * 16);
|
define('EXPORT_PAGE_ROW_BUDGET_PX', 63 * 16);
|
||||||
define('EXPORT_MIN_ROW_HEIGHT_PX', 16);
|
// Technischer Mindestwert, nur als letzte Bremse gegen 0/negative Hoehen bei
|
||||||
define('EXPORT_MAX_ROW_HEIGHT_PX', 40);
|
// absurd hohen Teilnehmerzahlen - kein gestalterisches Minimum.
|
||||||
// Ziel-Zeilenzahl je Seite im Zweiseiten-Modus, wenn freie Zeilen erwuenscht
|
define('EXPORT_HARD_MIN_ROW_HEIGHT_PX', 6);
|
||||||
// sind - identisch zur bisherigen, getesteten Dichte (63 Zeilen a 16px).
|
|
||||||
define('EXPORT_MULTI_PAGE_FILL_ROWS', 63);
|
|
||||||
|
|
||||||
$allActive = ledger_fetch_participant_summaries($pdo, $tenantId, ['active_only' => true]);
|
$allActive = ledger_fetch_participant_summaries($pdo, $tenantId, ['active_only' => true]);
|
||||||
$memberCount = count($allActive);
|
$memberCount = count($allActive);
|
||||||
$isMultiPage = $memberCount >= EXPORT_MULTI_PAGE_THRESHOLD;
|
$isMultiPage = $memberCount >= EXPORT_MULTI_PAGE_THRESHOLD;
|
||||||
|
|
||||||
function export_row_height_px(int $targetRows): float
|
/**
|
||||||
|
* Ermittelt Zeilenanzahl und -hoehe fuer eine Seite: Ausgangspunkt ist die
|
||||||
|
* vom Admin gewuenschte Zeilenhoehe. Sind Fuellzeilen erwuenscht, wird die
|
||||||
|
* Seite bis zu dieser Hoehe komplett aufgefuellt (weniger Mitglieder ->
|
||||||
|
* groessere, statt immer gleich viele Zeilen). Passt die Mitgliederzahl bei
|
||||||
|
* der gewuenschten Hoehe nicht auf eine Seite, wird bei jeder Generierung
|
||||||
|
* automatisch so weit verkleinert, dass garantiert alle Teilnehmer passen.
|
||||||
|
*
|
||||||
|
* @return array{0: int, 1: float} [targetRows, rowHeightPx]
|
||||||
|
*/
|
||||||
|
function export_compute_layout(int $memberCount, bool $showEmptyRows, int $adminRowHeightPx): array
|
||||||
{
|
{
|
||||||
$height = EXPORT_PAGE_ROW_BUDGET_PX / max(1, $targetRows);
|
$adminRowHeightPx = max(1, $adminRowHeightPx);
|
||||||
|
$capacityAtAdminHeight = (int)floor(EXPORT_PAGE_ROW_BUDGET_PX / $adminRowHeightPx);
|
||||||
|
|
||||||
return max(EXPORT_MIN_ROW_HEIGHT_PX, min(EXPORT_MAX_ROW_HEIGHT_PX, $height));
|
$targetRows = $showEmptyRows ? max($memberCount, $capacityAtAdminHeight) : $memberCount;
|
||||||
|
$targetRows = max(1, $targetRows);
|
||||||
|
|
||||||
|
$rowHeight = min((float)$adminRowHeightPx, EXPORT_PAGE_ROW_BUDGET_PX / $targetRows);
|
||||||
|
$rowHeight = max(EXPORT_HARD_MIN_ROW_HEIGHT_PX, $rowHeight);
|
||||||
|
|
||||||
|
return [$targetRows, $rowHeight];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rendert eine Teilnehmerseite als HTML-Tabelle fuer TCPDF. Die Zeilenhoehe
|
* Rendert eine Teilnehmerseite als HTML-Tabelle fuer TCPDF.
|
||||||
* richtet sich nach der Ziel-Zeilenzahl (Mitglieder plus ggf. Fuellzeilen),
|
|
||||||
* damit wenige Mitglieder groessere statt winziger Zeilen ergeben.
|
|
||||||
*
|
*
|
||||||
* @param list<array> $teilnehmer
|
* @param list<array> $teilnehmer
|
||||||
*/
|
*/
|
||||||
function export_render_page_html(array $teilnehmer, string $titel, string $hinweisText, string $markPrice, int $targetRows, bool $showEmptyRows, ?string $seitenHinweis): string
|
function export_render_page_html(array $teilnehmer, string $titel, string $hinweisText, string $markPrice, bool $showEmptyRows, int $adminRowHeightPx, ?string $seitenHinweis): string
|
||||||
{
|
{
|
||||||
$rowHeight = export_row_height_px($showEmptyRows ? $targetRows : max(1, count($teilnehmer)));
|
[$targetRows, $rowHeight] = export_compute_layout(count($teilnehmer), $showEmptyRows, $adminRowHeightPx);
|
||||||
|
|
||||||
$html = '
|
$html = '
|
||||||
<table border="1" style="white-space:nowrap;">
|
<table border="1" style="white-space:nowrap;">
|
||||||
@@ -146,8 +160,8 @@ if (!$isMultiPage) {
|
|||||||
'Kaffeeliste',
|
'Kaffeeliste',
|
||||||
'background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);',
|
'background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);',
|
||||||
$markPrice,
|
$markPrice,
|
||||||
EXPORT_MULTI_PAGE_THRESHOLD,
|
|
||||||
$showEmptyRows,
|
$showEmptyRows,
|
||||||
|
$adminRowHeightPx,
|
||||||
null
|
null
|
||||||
),
|
),
|
||||||
true, false, true, false, ''
|
true, false, true, false, ''
|
||||||
@@ -168,13 +182,13 @@ if (!$isMultiPage) {
|
|||||||
|
|
||||||
$pdf->AddPage();
|
$pdf->AddPage();
|
||||||
$pdf->writeHTML(
|
$pdf->writeHTML(
|
||||||
export_render_page_html($front, $frontTitel, 'background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);', $markPrice, EXPORT_MULTI_PAGE_FILL_ROWS, $showEmptyRows, 'Rückseite beachten!'),
|
export_render_page_html($front, $frontTitel, 'background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);', $markPrice, $showEmptyRows, $adminRowHeightPx, 'Rückseite beachten!'),
|
||||||
true, false, true, false, ''
|
true, false, true, false, ''
|
||||||
);
|
);
|
||||||
|
|
||||||
$pdf->AddPage();
|
$pdf->AddPage();
|
||||||
$pdf->writeHTML(
|
$pdf->writeHTML(
|
||||||
export_render_page_html($back, $backTitel, 'background-color: rgb(91, 209, 215);color: rgb(0, 0, 0);', $markPrice, EXPORT_MULTI_PAGE_FILL_ROWS, $showEmptyRows, 'Vorderseite beachten!'),
|
export_render_page_html($back, $backTitel, 'background-color: rgb(91, 209, 215);color: rgb(0, 0, 0);', $markPrice, $showEmptyRows, $adminRowHeightPx, 'Vorderseite beachten!'),
|
||||||
true, false, true, false, ''
|
true, false, true, false, ''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ if ($canManageSettings) {
|
|||||||
'negative_warning_cents' => -abs(saas_parse_money_cents($_POST['negative_warning'] ?? '') ?? 0),
|
'negative_warning_cents' => -abs(saas_parse_money_cents($_POST['negative_warning'] ?? '') ?? 0),
|
||||||
'pdf_show_empty_rows' => !empty($_POST['pdf_show_empty_rows']) ? 1 : 0,
|
'pdf_show_empty_rows' => !empty($_POST['pdf_show_empty_rows']) ? 1 : 0,
|
||||||
'pdf_split_mode' => $_POST['pdf_split_mode'] ?? 'drinking_behavior',
|
'pdf_split_mode' => $_POST['pdf_split_mode'] ?? 'drinking_behavior',
|
||||||
|
'pdf_row_height_px' => $_POST['pdf_row_height_px'] ?? 16,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -127,6 +128,10 @@ include 'nav.php';
|
|||||||
<option value="alphabetical" <?php echo $settings['pdf_split_mode'] === 'alphabetical' ? 'selected' : ''; ?>>Alphabetisch</option>
|
<option value="alphabetical" <?php echo $settings['pdf_split_mode'] === 'alphabetical' ? 'selected' : ''; ?>>Alphabetisch</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6 col-12-small">
|
||||||
|
<label for="pdf_row_height_px">Zeilenhöhe im Ausdruck (10–60px)</label>
|
||||||
|
<input type="number" name="pdf_row_height_px" id="pdf_row_height_px" min="10" max="60" value="<?php echo saas_html($settings['pdf_row_height_px']); ?>" required>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="actions">
|
<ul class="actions">
|
||||||
<li><button type="submit">Speichern</button></li>
|
<li><button type="submit">Speichern</button></li>
|
||||||
|
|||||||
Reference in New Issue
Block a user