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>
86 lines
2.9 KiB
PHP
86 lines
2.9 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
require_once __DIR__ . '/bootstrap.php';
|
||
|
||
/**
|
||
* @return list<array{id: int, question: string, answer: string, sort_order: int}>
|
||
*/
|
||
function faq_fetch_all(PDO $pdo, int $tenantId): array
|
||
{
|
||
$stmt = $pdo->prepare(
|
||
'SELECT id, question, answer, sort_order
|
||
FROM faq_entries
|
||
WHERE tenant_id = ?
|
||
AND deleted_at IS NULL
|
||
ORDER BY sort_order, id'
|
||
);
|
||
$stmt->execute([$tenantId]);
|
||
|
||
return $stmt->fetchAll();
|
||
}
|
||
|
||
function faq_create(PDO $pdo, int $tenantId, string $question, string $answer): bool
|
||
{
|
||
$question = trim($question);
|
||
$answer = trim($answer);
|
||
if ($question === '' || $answer === '') {
|
||
return false;
|
||
}
|
||
|
||
$stmt = $pdo->prepare('SELECT COALESCE(MAX(sort_order), 0) + 1 FROM faq_entries WHERE tenant_id = ? AND deleted_at IS NULL');
|
||
$stmt->execute([$tenantId]);
|
||
$nextOrder = (int)$stmt->fetchColumn();
|
||
|
||
$stmt = $pdo->prepare('INSERT INTO faq_entries (tenant_id, question, answer, sort_order) VALUES (?, ?, ?, ?)');
|
||
|
||
return $stmt->execute([$tenantId, $question, $answer, $nextOrder]);
|
||
}
|
||
|
||
function faq_update(PDO $pdo, int $tenantId, int $id, string $question, string $answer): bool
|
||
{
|
||
$question = trim($question);
|
||
$answer = trim($answer);
|
||
if ($question === '' || $answer === '') {
|
||
return false;
|
||
}
|
||
|
||
$stmt = $pdo->prepare(
|
||
'UPDATE faq_entries SET question = ?, answer = ? WHERE id = ? AND tenant_id = ? AND deleted_at IS NULL'
|
||
);
|
||
$stmt->execute([$question, $answer, $id, $tenantId]);
|
||
|
||
return $stmt->rowCount() > 0;
|
||
}
|
||
|
||
function faq_soft_delete(PDO $pdo, int $tenantId, int $id): bool
|
||
{
|
||
$stmt = $pdo->prepare(
|
||
'UPDATE faq_entries SET deleted_at = NOW() WHERE id = ? AND tenant_id = ? AND deleted_at IS NULL'
|
||
);
|
||
$stmt->execute([$id, $tenantId]);
|
||
|
||
return $stmt->rowCount() > 0;
|
||
}
|
||
|
||
/**
|
||
* Seeds two example questions for a brand-new tenant, damit die FAQ-Seite
|
||
* nicht voellig leer startet und sofort erkennbar ist, wie ein Eintrag
|
||
* aussieht. Bewusst nur zwei Beispiele statt eines fertigen Katalogs: die
|
||
* Antworten sind Platzhalter, die jeder Mandant ohnehin auf seine eigene
|
||
* Teekueche umschreibt. Beide Eintraege sind frei editier- und loeschbar.
|
||
*/
|
||
function faq_seed_default_entries(PDO $pdo, int $tenantId): void
|
||
{
|
||
$starters = [
|
||
['Wie starten wir mit unserer Kaffeeliste?', 'Beispielantwort – bitte anpassen: Mitglieder unter „Mitglieder verwalten" anlegen, danach direkt Striche und Einzahlungen erfassen.'],
|
||
['Wie erfahre ich meinen aktuellen Stand?', 'Beispielantwort – bitte anpassen: Unter „Meine Kaffeeliste" ist der aktuelle Stand jederzeit sichtbar.'],
|
||
];
|
||
|
||
$stmt = $pdo->prepare('INSERT INTO faq_entries (tenant_id, question, answer, sort_order) VALUES (?, ?, ?, ?)');
|
||
foreach ($starters as $index => [$question, $answer]) {
|
||
$stmt->execute([$tenantId, $question, $answer, $index + 1]);
|
||
}
|
||
}
|