Kaffeeliste-Ausdruck: adaptives Layout nach Mitgliederzahl
Der PDF-Export war bisher immer zweiseitig (Vieltrinker-/Wenigtrinker) mit fester Mindestzeilenzahl, unabhängig von der tatsächlichen Mitgliederzahl. Umgestellt auf: - Bis 49 aktive Mitglieder: eine Seite ohne Trennung. - Ab 50 Mitgliedern: weiterhin zwei Seiten (Vorder-/Rückseite). - Zeilenhöhe richtet sich nach der Mitgliederzahl (16-40px), statt fest 16px für alle. - Neue Mandanten-Einstellungen: freie Zeilen für neue Mitglieder an/aus, Trennmodus bei zwei Seiten (Trinkverhalten oder alphabetisch). Migration 0015 ergänzt die dafür nötigen tenant_settings-Spalten. Gegen die Dev-DB verifiziert: 8 Mitglieder -> einseitiges PDF, 53 Mitglieder (temporäre Testdaten) -> zweiseitiges PDF, Einstellungen inkl. Validierung geprüft.
This commit is contained in:
+18
-4
@@ -273,7 +273,9 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array
|
|||||||
ts.paypal_enabled,
|
ts.paypal_enabled,
|
||||||
ts.paypal_url_template,
|
ts.paypal_url_template,
|
||||||
ts.sheet_window_days,
|
ts.sheet_window_days,
|
||||||
ts.negative_warning_cents
|
ts.negative_warning_cents,
|
||||||
|
ts.pdf_show_empty_rows,
|
||||||
|
ts.pdf_split_mode
|
||||||
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 = ?
|
||||||
@@ -306,6 +308,8 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array
|
|||||||
'paypal_url_template' => (string)$settings['paypal_url_template'],
|
'paypal_url_template' => (string)$settings['paypal_url_template'],
|
||||||
'sheet_window_days' => (int)$settings['sheet_window_days'],
|
'sheet_window_days' => (int)$settings['sheet_window_days'],
|
||||||
'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_split_mode' => (string)$settings['pdf_split_mode'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,6 +323,7 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
$sheetWindowDays = filter_var($input['sheet_window_days'] ?? null, FILTER_VALIDATE_INT);
|
$sheetWindowDays = filter_var($input['sheet_window_days'] ?? null, FILTER_VALIDATE_INT);
|
||||||
$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'));
|
||||||
|
|
||||||
$errors = [];
|
$errors = [];
|
||||||
if (strlen($tenantName) < 3 || strlen($tenantName) > 255) {
|
if (strlen($tenantName) < 3 || strlen($tenantName) > 255) {
|
||||||
@@ -345,6 +350,9 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
if (strlen($paypalUrlTemplate) > 1000) {
|
if (strlen($paypalUrlTemplate) > 1000) {
|
||||||
$errors[] = 'Der PayPal-Link ist zu lang.';
|
$errors[] = 'Der PayPal-Link ist zu lang.';
|
||||||
}
|
}
|
||||||
|
if (!in_array($pdfSplitMode, ['drinking_behavior', 'alphabetical'], true)) {
|
||||||
|
$errors[] = 'Die Sortierung für den Ausdruck ist ungültig.';
|
||||||
|
}
|
||||||
|
|
||||||
if ($errors !== []) {
|
if ($errors !== []) {
|
||||||
return ['ok' => false, 'errors' => $errors];
|
return ['ok' => false, 'errors' => $errors];
|
||||||
@@ -352,6 +360,7 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
|
|
||||||
$selfEntryEnabled = !empty($input['self_entry_enabled']) ? 1 : 0;
|
$selfEntryEnabled = !empty($input['self_entry_enabled']) ? 1 : 0;
|
||||||
$paypalEnabled = !empty($input['paypal_enabled']) ? 1 : 0;
|
$paypalEnabled = !empty($input['paypal_enabled']) ? 1 : 0;
|
||||||
|
$pdfShowEmptyRows = !empty($input['pdf_show_empty_rows']) ? 1 : 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$pdo->beginTransaction();
|
$pdo->beginTransaction();
|
||||||
@@ -366,15 +375,18 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
'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,
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
pdf_show_empty_rows, pdf_split_mode)
|
||||||
|
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),
|
||||||
paypal_enabled = VALUES(paypal_enabled),
|
paypal_enabled = VALUES(paypal_enabled),
|
||||||
paypal_url_template = VALUES(paypal_url_template),
|
paypal_url_template = VALUES(paypal_url_template),
|
||||||
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_split_mode = VALUES(pdf_split_mode)'
|
||||||
);
|
);
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
$tenantId,
|
$tenantId,
|
||||||
@@ -384,6 +396,8 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
|
|||||||
$paypalUrlTemplate,
|
$paypalUrlTemplate,
|
||||||
(int)$sheetWindowDays,
|
(int)$sheetWindowDays,
|
||||||
-abs($negativeWarningCents),
|
-abs($negativeWarningCents),
|
||||||
|
$pdfShowEmptyRows,
|
||||||
|
$pdfSplitMode,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE tenant_settings
|
||||||
|
ADD COLUMN pdf_show_empty_rows TINYINT(1) NOT NULL DEFAULT 1 AFTER negative_warning_cents,
|
||||||
|
ADD COLUMN pdf_split_mode VARCHAR(20) NOT NULL DEFAULT 'drinking_behavior' AFTER pdf_show_empty_rows;
|
||||||
@@ -22,35 +22,21 @@ Noch nicht entschieden/umgesetzt.
|
|||||||
|
|
||||||
## Kaffeeliste-Ausdruck (PDF-Export) als zentrale Funktion
|
## Kaffeeliste-Ausdruck (PDF-Export) als zentrale Funktion
|
||||||
|
|
||||||
Der PDF-Ausdruck (`exportKaffeeliste.php`, siehe
|
**Erledigt (2026-07-19)**, siehe `docs/m6-import-export-mail.md` Abschnitt
|
||||||
`docs/m6-import-export-mail.md` für den aktuellen Umsetzungsstand) soll
|
„Nachtrag: Adaptives Layout nach Mitgliederzahl" für Details:
|
||||||
zu einer zentralen, prominent beworbenen Funktion werden – aktuell fixe
|
|
||||||
zweiseitige Vieltrinker-/Wenigtrinker-Ausgabe mit fester Mindestzeilenzahl
|
|
||||||
(63/64), ohne Rücksicht auf die tatsächliche Mitgliederzahl.
|
|
||||||
|
|
||||||
Neue Anforderungen:
|
- ✅ Adaptives Layout nach Mitgliederanzahl (Zeilenhöhe 16–40px je nach
|
||||||
|
Mitgliederzahl).
|
||||||
|
- ✅ Vorder-/Rückseite bzw. mehrere Seiten erst ab 50 Mitgliedern
|
||||||
|
(`EXPORT_MULTI_PAGE_THRESHOLD`), darunter eine einseitige Liste.
|
||||||
|
- ✅ Admin-Einstellung „Freie Zeilen für neue Mitglieder"
|
||||||
|
(`tenant_settings.pdf_show_empty_rows`, Formular in
|
||||||
|
`mandant-einstellungen.php`).
|
||||||
|
- ✅ Trennmodus bei mehreren Seiten wählbar: Trinkverhalten oder
|
||||||
|
alphabetisch (`tenant_settings.pdf_split_mode`).
|
||||||
|
|
||||||
- **Adaptives Layout nach Mitgliederanzahl.** Bis 50 Mitglieder passen
|
Die Kaffeeliste als zentrale, prominent beworbene Funktion auf der
|
||||||
auf eine Seite; die Zeilenhöhe/-größe soll sich an der Mitgliederzahl
|
Landingpage darzustellen (siehe unten) ist noch offen.
|
||||||
orientieren (weniger Mitglieder → größere, besser lesbare Zeilen statt
|
|
||||||
fester Zeilenhöhe wie bisher).
|
|
||||||
- **Vorder-/Rückseite bzw. mehrere Seiten erst ab 50 Mitgliedern.**
|
|
||||||
Unterhalb dieser Schwelle reicht eine einseitige Liste; die bestehende
|
|
||||||
Vieltrinker-/Wenigtrinker-Aufteilung auf zwei Seiten wird zur Option ab
|
|
||||||
50 Mitgliedern, nicht mehr Standard für alle Mandanten.
|
|
||||||
- **Admin-Einstellung: freie Zeilen für neue Mitglieder.** Der Admin soll
|
|
||||||
konfigurieren können, ob die Liste zusätzliche leere Zeilen für neue
|
|
||||||
Mitglieder enthält (aktuelles Verhalten: Auffüllen bis `minRows`) oder
|
|
||||||
nur die tatsächlich vorhandenen Mitglieder zeigt.
|
|
||||||
- **Trennmodus bei mehreren Seiten wählbar.** Zur Auswahl: Trennung nach
|
|
||||||
Trinkverhalten (wie bisher: vorne Vieltrinker, hinten Wenigtrinker) oder
|
|
||||||
einfach alphabetisch über alle Seiten.
|
|
||||||
|
|
||||||
Technisch vermutlich als neue Spalten in `tenant_settings`
|
|
||||||
(vgl. `database/migrations/0002_saas_identity_tenants.sql`) abzubilden,
|
|
||||||
z. B. `pdf_show_empty_rows`, `pdf_multi_page_threshold`,
|
|
||||||
`pdf_split_mode` (`drinking_behavior` | `alphabetical`) – noch nicht
|
|
||||||
entschieden, nur als naheliegender Ansatzpunkt notiert.
|
|
||||||
|
|
||||||
### RFID-Kartenerfassung (zukünftig, nicht öffentlich bewerben)
|
### RFID-Kartenerfassung (zukünftig, nicht öffentlich bewerben)
|
||||||
|
|
||||||
|
|||||||
@@ -99,6 +99,32 @@ Live getestet: gültiges zweiseitiges PDF (58 KB) mit korrektem
|
|||||||
stichprobenartig verifiziert (unkomprimierte Testausgabe), Vieltrinker-/
|
stichprobenartig verifiziert (unkomprimierte Testausgabe), Vieltrinker-/
|
||||||
Wenigtrinker-Aufteilung stimmt mit den Ledger-Daten überein.
|
Wenigtrinker-Aufteilung stimmt mit den Ledger-Daten überein.
|
||||||
|
|
||||||
|
### Nachtrag: Adaptives Layout nach Mitgliederzahl (2026-07-19)
|
||||||
|
|
||||||
|
Der Export war bis dahin immer zweiseitig mit fester Mindestzeilenzahl
|
||||||
|
(63/64 Zeilen a 16px), unabhängig von der tatsächlichen Mitgliederzahl.
|
||||||
|
Umgestellt auf:
|
||||||
|
|
||||||
|
- Bis 49 aktive Mitglieder: eine Seite, keine Vieltrinker-/Wenigtrinker-
|
||||||
|
Trennung. Ab 50 (`EXPORT_MULTI_PAGE_THRESHOLD` in
|
||||||
|
`exportKaffeeliste.php`): zwei Seiten wie bisher.
|
||||||
|
- Zeilenhöhe wird aus einem festen Platzbudget pro Seite errechnet
|
||||||
|
(`export_row_height_px()`), begrenzt auf 16–40px – weniger Mitglieder
|
||||||
|
ergeben größere statt winziger Zeilen.
|
||||||
|
- Neue Mandanten-Einstellungen (`tenant_settings.pdf_show_empty_rows`,
|
||||||
|
`tenant_settings.pdf_split_mode`, Migration
|
||||||
|
`0015_saas_pdf_export_settings.sql`, Formular in
|
||||||
|
`mandant-einstellungen.php`): Admin legt fest, ob freie Zeilen für neue
|
||||||
|
Mitglieder aufgefüllt werden, und ob die Zweiseiten-Trennung nach
|
||||||
|
Trinkverhalten (wie bisher) oder alphabetisch erfolgt.
|
||||||
|
- Verifiziert gegen die Dev-DB: 8 aktive Mitglieder ergeben ein
|
||||||
|
einseitiges PDF (`/Count 1`), 53 aktive Mitglieder ein zweiseitiges
|
||||||
|
(`/Count 2`); `saas_update_tenant_settings()` speichert und validiert
|
||||||
|
die neuen Felder korrekt (ungültiger `pdf_split_mode` wird abgelehnt).
|
||||||
|
- RFID-Kartenerfassung als künftige Erfassungsmethode ist weiterhin nur
|
||||||
|
im Backlog vermerkt (`docs/backlog-druck-und-landingpage.md`), nicht
|
||||||
|
umgesetzt und nicht beworben.
|
||||||
|
|
||||||
## Mailversand
|
## Mailversand
|
||||||
|
|
||||||
Umgesetzte Dateien:
|
Umgesetzte Dateien:
|
||||||
|
|||||||
+120
-61
@@ -29,9 +29,88 @@ if (!$hasAccess) {
|
|||||||
$settings = saas_fetch_tenant_settings($pdo, $tenantId);
|
$settings = saas_fetch_tenant_settings($pdo, $tenantId);
|
||||||
$windowDays = $settings['sheet_window_days'] ?? 100;
|
$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;
|
||||||
|
$splitMode = (string)($settings['pdf_split_mode'] ?? 'drinking_behavior');
|
||||||
|
|
||||||
$vieltrinker = ledger_fetch_participants_by_window_marks($pdo, $tenantId, $windowDays, true);
|
// Ab dieser Mitgliederzahl wird auf zwei Seiten (Vorder-/Rueckseite) statt
|
||||||
$wenigtrinker = ledger_fetch_participants_by_window_marks($pdo, $tenantId, $windowDays, false);
|
// 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);
|
||||||
|
define('EXPORT_MIN_ROW_HEIGHT_PX', 16);
|
||||||
|
define('EXPORT_MAX_ROW_HEIGHT_PX', 40);
|
||||||
|
// Ziel-Zeilenzahl je Seite im Zweiseiten-Modus, wenn freie Zeilen erwuenscht
|
||||||
|
// 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]);
|
||||||
|
$memberCount = count($allActive);
|
||||||
|
$isMultiPage = $memberCount >= EXPORT_MULTI_PAGE_THRESHOLD;
|
||||||
|
|
||||||
|
function export_row_height_px(int $targetRows): float
|
||||||
|
{
|
||||||
|
$height = EXPORT_PAGE_ROW_BUDGET_PX / max(1, $targetRows);
|
||||||
|
|
||||||
|
return max(EXPORT_MIN_ROW_HEIGHT_PX, min(EXPORT_MAX_ROW_HEIGHT_PX, $height));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rendert eine Teilnehmerseite als HTML-Tabelle fuer TCPDF. Die Zeilenhoehe
|
||||||
|
* richtet sich nach der Ziel-Zeilenzahl (Mitglieder plus ggf. Fuellzeilen),
|
||||||
|
* damit wenige Mitglieder groessere statt winziger Zeilen ergeben.
|
||||||
|
*
|
||||||
|
* @param list<array> $teilnehmer
|
||||||
|
*/
|
||||||
|
function export_render_page_html(array $teilnehmer, string $titel, string $hinweisText, string $markPrice, int $targetRows, bool $showEmptyRows, ?string $seitenHinweis): string
|
||||||
|
{
|
||||||
|
$rowHeight = export_row_height_px($showEmptyRows ? $targetRows : max(1, count($teilnehmer)));
|
||||||
|
|
||||||
|
$html = '
|
||||||
|
<table border="1" style="white-space:nowrap;">
|
||||||
|
<tr style="height: 25px;' . $hinweisText . '" valign="bottom">
|
||||||
|
<th style="width:30%;font-size: 13px;" colspan="2"><b>' . $titel . '</b></th>
|
||||||
|
<th style="width:70%;" valign="bottom">1 Strich = ' . $markPrice . '€. Bitte bezahlen bei 10 € zahlen. ' . date("d.m.Y H:s") . '</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="width:20%"><b>Name</b></td>
|
||||||
|
<td style="width:10%"><b>Guthaben</b></td>
|
||||||
|
<td><b>Striche</b></td>
|
||||||
|
</tr>';
|
||||||
|
|
||||||
|
$rowCount = 0;
|
||||||
|
foreach ($teilnehmer as $person) {
|
||||||
|
$rowCount++;
|
||||||
|
$name = saas_html($person['display_name']);
|
||||||
|
$balanceCents = (int)$person['balance_cents'];
|
||||||
|
$balance = number_format($balanceCents / 100, 2, ',', '.');
|
||||||
|
|
||||||
|
$html .= '<tr style="height: ' . $rowHeight . 'px;">';
|
||||||
|
$html .= "<td>{$name}</td>";
|
||||||
|
if ($balanceCents < -1000) {
|
||||||
|
$html .= '<td style="background-color: rgb(204, 0, 0); color: rgb(255, 255, 255);">' . $balance . ' €</td>';
|
||||||
|
} elseif ($balanceCents > 500) {
|
||||||
|
$html .= '<td style="background-color: rgb(0, 102, 0); color: rgb(255, 255, 255);">' . $balance . ' €</td>';
|
||||||
|
} else {
|
||||||
|
$html .= "<td>{$balance} €</td>";
|
||||||
|
}
|
||||||
|
$html .= "<td></td>";
|
||||||
|
$html .= "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($showEmptyRows) {
|
||||||
|
for ($i = $rowCount; $i < $targetRows; $i++) {
|
||||||
|
$html .= '<tr style="height: ' . $rowHeight . 'px;"><td> </td><td> </td><td> </td></tr>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($seitenHinweis !== null) {
|
||||||
|
$html .= '<tr><td> </td><td> </td><td style="background-color: rgb(255, 255, 0);text-align: right;"><b>' . $seitenHinweis . '</b></td></tr>';
|
||||||
|
}
|
||||||
|
$html .= '</table>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
// TCPDF-Bibliothek einbinden
|
// TCPDF-Bibliothek einbinden
|
||||||
require_once(__DIR__ . '/TCPDF/tcpdf.php');
|
require_once(__DIR__ . '/TCPDF/tcpdf.php');
|
||||||
@@ -52,55 +131,6 @@ class MyCustomPDFWithWatermark extends TCPDF {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Rendert eine Teilnehmerseite (Vieltrinker/Wenigtrinker) als HTML-Tabelle
|
|
||||||
* fuer TCPDF, inklusive Fuellzeilen bis zur Mindesthoehe.
|
|
||||||
*
|
|
||||||
* @param list<array> $teilnehmer
|
|
||||||
*/
|
|
||||||
function export_render_page_html(array $teilnehmer, string $titel, string $hinweisText, string $markPrice, int $minRows, string $rueckseitenHinweis): string
|
|
||||||
{
|
|
||||||
$html = '
|
|
||||||
<table border="1" style="white-space:nowrap;">
|
|
||||||
<tr style="height: 25px;' . $hinweisText . '" valign="bottom">
|
|
||||||
<th style="width:30%;font-size: 13px;" colspan="2"><b>' . $titel . '</b></th>
|
|
||||||
<th style="width:70%;" valign="bottom">1 Strich = ' . $markPrice . '€. Bitte bezahlen bei 10 € zahlen. ' . date("d.m.Y H:s") . '</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="width:20%"><b>Name</b></td>
|
|
||||||
<td style="width:10%"><b>Guthaben</b></td>
|
|
||||||
<td><b>Striche</b></td>
|
|
||||||
</tr>';
|
|
||||||
|
|
||||||
$rowCount = 0;
|
|
||||||
foreach ($teilnehmer as $person) {
|
|
||||||
$rowCount++;
|
|
||||||
$name = saas_html($person['display_name']);
|
|
||||||
$balanceCents = (int)$person['balance_cents'];
|
|
||||||
$balance = number_format($balanceCents / 100, 2, ',', '.');
|
|
||||||
|
|
||||||
$html .= '<tr style="height: 16px;">';
|
|
||||||
$html .= "<td>{$name}</td>";
|
|
||||||
if ($balanceCents < -1000) {
|
|
||||||
$html .= '<td style="background-color: rgb(204, 0, 0); color: rgb(255, 255, 255);">' . $balance . ' €</td>';
|
|
||||||
} elseif ($balanceCents > 500) {
|
|
||||||
$html .= '<td style="background-color: rgb(0, 102, 0); color: rgb(255, 255, 255);">' . $balance . ' €</td>';
|
|
||||||
} else {
|
|
||||||
$html .= "<td>{$balance} €</td>";
|
|
||||||
}
|
|
||||||
$html .= "<td></td>";
|
|
||||||
$html .= "</tr>";
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = $rowCount; $i < $minRows; $i++) {
|
|
||||||
$html .= '<tr><td> </td><td> </td><td> </td></tr>';
|
|
||||||
}
|
|
||||||
$html .= '<tr><td> </td><td> </td><td style="background-color: rgb(255, 255, 0);text-align: right;"><b>' . $rueckseitenHinweis . '</b></td></tr>';
|
|
||||||
$html .= '</table>';
|
|
||||||
|
|
||||||
return $html;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdf = new MyCustomPDFWithWatermark(PDF_PAGE_ORIENTATION, 'mm', 'A4', true, 'UTF-8', false);
|
$pdf = new MyCustomPDFWithWatermark(PDF_PAGE_ORIENTATION, 'mm', 'A4', true, 'UTF-8', false);
|
||||||
$pdf->SetHeaderData("", 0, "Kaffeestrichliste", "");
|
$pdf->SetHeaderData("", 0, "Kaffeestrichliste", "");
|
||||||
$pdf->SetPrintFooter(false);
|
$pdf->SetPrintFooter(false);
|
||||||
@@ -108,16 +138,45 @@ $pdf->SetMargins('5', '5', '5');
|
|||||||
$pdf->SetAutoPageBreak(true, 5);
|
$pdf->SetAutoPageBreak(true, 5);
|
||||||
$pdf->SetFont('helvetica', '', 9.5);
|
$pdf->SetFont('helvetica', '', 9.5);
|
||||||
|
|
||||||
$pdf->AddPage();
|
if (!$isMultiPage) {
|
||||||
$pdf->writeHTML(
|
$pdf->AddPage();
|
||||||
export_render_page_html($vieltrinker, 'Kaffeeliste - Vieltrinker', 'background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);', $markPrice, 63, 'Rückseite beachten!'),
|
$pdf->writeHTML(
|
||||||
true, false, true, false, ''
|
export_render_page_html(
|
||||||
);
|
$allActive,
|
||||||
|
'Kaffeeliste',
|
||||||
|
'background-color: rgb(0, 94, 63);color: rgb(255, 255, 255);',
|
||||||
|
$markPrice,
|
||||||
|
EXPORT_MULTI_PAGE_THRESHOLD,
|
||||||
|
$showEmptyRows,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
true, false, true, false, ''
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if ($splitMode === 'alphabetical') {
|
||||||
|
$mid = (int)ceil($memberCount / 2);
|
||||||
|
$front = array_slice($allActive, 0, $mid);
|
||||||
|
$back = array_slice($allActive, $mid);
|
||||||
|
$frontTitel = 'Kaffeeliste – Teil 1';
|
||||||
|
$backTitel = 'Kaffeeliste – Teil 2';
|
||||||
|
} else {
|
||||||
|
$front = ledger_fetch_participants_by_window_marks($pdo, $tenantId, $windowDays, true);
|
||||||
|
$back = ledger_fetch_participants_by_window_marks($pdo, $tenantId, $windowDays, false);
|
||||||
|
$frontTitel = 'Kaffeeliste - Vieltrinker';
|
||||||
|
$backTitel = 'Kaffeeliste - Wenigtrinker';
|
||||||
|
}
|
||||||
|
|
||||||
$pdf->AddPage();
|
$pdf->AddPage();
|
||||||
$pdf->writeHTML(
|
$pdf->writeHTML(
|
||||||
export_render_page_html($wenigtrinker, 'Kaffeeliste - Wenigtrinker', 'background-color: rgb(91, 209, 215);color: rgb(0, 0, 0);', $markPrice, 64, 'Vorderseite beachten!'),
|
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!'),
|
||||||
true, false, true, false, ''
|
true, false, true, false, ''
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$pdf->AddPage();
|
||||||
|
$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!'),
|
||||||
|
true, false, true, false, ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$pdf->Output('Kaffeestrichliste.pdf', 'D');
|
$pdf->Output('Kaffeestrichliste.pdf', 'D');
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ if ($canManageSettings) {
|
|||||||
'paypal_url_template' => $_POST['paypal_url_template'] ?? '',
|
'paypal_url_template' => $_POST['paypal_url_template'] ?? '',
|
||||||
'sheet_window_days' => $_POST['sheet_window_days'] ?? 100,
|
'sheet_window_days' => $_POST['sheet_window_days'] ?? 100,
|
||||||
'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_split_mode' => $_POST['pdf_split_mode'] ?? 'drinking_behavior',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -114,6 +116,17 @@ include 'nav.php';
|
|||||||
<input type="checkbox" id="paypal_enabled" name="paypal_enabled" value="1" <?php echo (int)$settings['paypal_enabled'] === 1 ? 'checked' : ''; ?>>
|
<input type="checkbox" id="paypal_enabled" name="paypal_enabled" value="1" <?php echo (int)$settings['paypal_enabled'] === 1 ? 'checked' : ''; ?>>
|
||||||
<label for="paypal_enabled">PayPal anzeigen</label>
|
<label for="paypal_enabled">PayPal anzeigen</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6 col-12-small">
|
||||||
|
<input type="checkbox" id="pdf_show_empty_rows" name="pdf_show_empty_rows" value="1" <?php echo (int)$settings['pdf_show_empty_rows'] === 1 ? 'checked' : ''; ?>>
|
||||||
|
<label for="pdf_show_empty_rows">Freie Zeilen für neue Mitglieder im Ausdruck</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 col-12-small">
|
||||||
|
<label for="pdf_split_mode">Sortierung im Ausdruck (bei mehreren Seiten)</label>
|
||||||
|
<select name="pdf_split_mode" id="pdf_split_mode">
|
||||||
|
<option value="drinking_behavior" <?php echo $settings['pdf_split_mode'] === 'drinking_behavior' ? 'selected' : ''; ?>>Nach Trinkverhalten (Vieltrinker vorne)</option>
|
||||||
|
<option value="alphabetical" <?php echo $settings['pdf_split_mode'] === 'alphabetical' ? 'selected' : ''; ?>>Alphabetisch</option>
|
||||||
|
</select>
|
||||||
|
</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