Betreiber-Zentralstelle, Mandanten-Design und schlankerer Einstieg

Funktions-Schalter je Mandant (app/features.php, tenant_features): der
Betreiber schaltet FAQ, Selbsteintrag, PDF, PayPal-Eingang, CSV-Import,
Mailversand, Jahresabschluss, Datenexport und eigenes Design pro Mandant
frei. Gesperrte Funktionen verschwinden aus Menue und Schaltflaechen, ihre
Seiten weisen Aufrufe und POSTs ab. Das Back-Office ist jetzt fuer
Platform-Admins im Menue verlinkt statt nur per URL erreichbar.

Eigenes Design je Mandant: Akzentfarbe und Logo in den Mandant-
Einstellungen, eingebettet ueber app/branding.php; das Logo liegt
geschuetzt in var/tenant_logos und wird nur ueber
tenant-logo-anzeigen.php an den eigenen Mandanten ausgeliefert.

Weniger Startinformationen: Startpaket neuer Mandanten auf zwei
Beispielfragen gekuerzt, Anleitung von ~1400 auf ~750 Woerter gestrafft
und um Abschnitte zu gesperrten Funktionen bereinigt.

Vorder-/Rueckseite erst bei mehr als 50 Personen (vorher schon ab 50).
Die Schwelle liegt jetzt gemeinsam in app/ledger.php und gilt auch fuer
die Vorder-/Rueckseiten-Auswahl beim Erfassen, wo sie bisher unabhaengig
von der Teamgroesse angeboten wurde.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 22:52:55 +02:00
co-authored by Claude Opus 5
parent a93e067e04
commit d24ee9bf91
30 changed files with 881 additions and 172 deletions
+16 -4
View File
@@ -286,7 +286,9 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array
ts.cash_contact,
ts.bank_transfer_enabled,
ts.bank_account_holder,
ts.bank_iban
ts.bank_iban,
ts.brand_logo,
ts.brand_color
FROM tenants t
LEFT JOIN tenant_settings ts ON ts.tenant_id = t.id
WHERE t.id = ?
@@ -332,6 +334,8 @@ function saas_fetch_tenant_settings(PDO $pdo, int $tenantId): ?array
'bank_transfer_enabled' => (int)$settings['bank_transfer_enabled'],
'bank_account_holder' => (string)$settings['bank_account_holder'],
'bank_iban' => (string)$settings['bank_iban'],
'brand_logo' => (string)$settings['brand_logo'],
'brand_color' => (string)$settings['brand_color'],
];
}
@@ -353,8 +357,14 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
$pdfWatermarkText = trim((string)($input['pdf_watermark_text'] ?? ''));
$pdfFooterText = trim((string)($input['pdf_footer_text'] ?? ''));
$paymentReminderIntervalDays = filter_var($input['payment_reminder_interval_days'] ?? null, FILTER_VALIDATE_INT);
$brandColor = strtolower(trim((string)($input['brand_color'] ?? '')));
$errors = [];
// Leer = Standarddesign. Sonst ein vollstaendiger Hex-Wert, der ohne
// weitere Aufbereitung in das erzeugte Stylesheet geschrieben werden kann.
if ($brandColor !== '' && !preg_match('/^#[0-9a-f]{6}$/', $brandColor)) {
$errors[] = 'Die Akzentfarbe muss ein Hex-Wert wie #38761d sein.';
}
if (strlen($tenantName) < 3 || strlen($tenantName) > 255) {
$errors[] = 'Der Kundenname muss zwischen 3 und 255 Zeichen lang sein.';
}
@@ -433,8 +443,8 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
pdf_watermark_text, pdf_footer_text,
payment_reminder_enabled, payment_reminder_interval_days,
cash_enabled, cash_contact, bank_transfer_enabled,
bank_account_holder, bank_iban)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
bank_account_holder, bank_iban, brand_color)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
mark_price_cents = VALUES(mark_price_cents),
self_entry_enabled = VALUES(self_entry_enabled),
@@ -453,7 +463,8 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
cash_contact = VALUES(cash_contact),
bank_transfer_enabled = VALUES(bank_transfer_enabled),
bank_account_holder = VALUES(bank_account_holder),
bank_iban = VALUES(bank_iban)'
bank_iban = VALUES(bank_iban),
brand_color = VALUES(brand_color)'
);
$stmt->execute([
$tenantId,
@@ -475,6 +486,7 @@ function saas_update_tenant_settings(PDO $pdo, int $tenantId, array $input): arr
$bankTransferEnabled,
$bankAccountHolder,
$bankIban,
$brandColor,
]);
$pdo->commit();