M8: Loesch-/Anonymisierungsprozess fuer Teilnehmer und Mandanten
Zwei getrennte Flows: - Teilnehmer anonymisieren statt loeschen (ledger_anonymize_participant): Name/E-Mail/PayPal-Name werden durch einen Platzhalter ersetzt, das Mitglied deaktiviert und vom Login-Konto getrennt. Buchungshistorie bleibt fuer die Kassenfuehrung erhalten, konsistent mit dem Storno-statt-Delete-Prinzip. Default-Mandant spiegelt die Anonymisierung in kl_Mitarbeiter (Email dort NOT NULL UNIQUE, bekommt Platzhalter statt NULL). Inhaber kann nicht anonymisiert werden. - Mandant vollstaendig loeschen (mandant-loeschen.php, nur Inhaber): erfordert exakte Eingabe des Kundenkuerzels, loescht die tenants-Zeile; alle tenant-scoped Tabellen kaskadieren per Fremdschluessel. users bleiben bestehen (koennen zu mehreren Mandanten gehoeren). Der migrierte Default-Mandant ist ausgenommen, da seine kl_Mitarbeiter- Historie sonst verwaisen wuerde. Live getestet: Mitglied mit Buchungshistorie anonymisiert (Historie blieb erhalten), Mandantenloeschung mit falscher/richtiger Bestaetigung geprueft, vollstaendiger Cascade-Delete ueber alle tenant-scoped Tabellen verifiziert, globale users-Zeile bleibt korrekt erhalten. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -496,6 +496,52 @@ function ledger_set_participant_active(PDO $pdo, int $tenantId, int $participant
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymizes a participant (GDPR-style erasure) instead of deleting them:
|
||||
* name and email are replaced with a non-identifying placeholder and the
|
||||
* participant is deactivated, but their ledger history stays intact for
|
||||
* the tenant's bookkeeping. For the default tenant, the linked
|
||||
* kl_Mitarbeiter row is anonymized the same way (its email column is
|
||||
* NOT NULL UNIQUE, so it gets a placeholder instead of NULL).
|
||||
*/
|
||||
function ledger_anonymize_participant(PDO $pdo, int $tenantId, int $participantId): bool
|
||||
{
|
||||
$stmt = $pdo->prepare('SELECT legacy_mitarbeiter_id FROM participants WHERE id = ? AND tenant_id = ?');
|
||||
$stmt->execute([$participantId, $tenantId]);
|
||||
$row = $stmt->fetch();
|
||||
if ($row === false) {
|
||||
return false;
|
||||
}
|
||||
$legacyMitarbeiterId = $row['legacy_mitarbeiter_id'] !== null ? (int)$row['legacy_mitarbeiter_id'] : null;
|
||||
$placeholderName = 'Gelöschter Teilnehmer #' . $participantId;
|
||||
$placeholderEmail = "deleted-participant-{$participantId}@invalid.local";
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
if ($legacyMitarbeiterId !== null) {
|
||||
$pdo->prepare('UPDATE kl_Mitarbeiter SET Name = ?, Email = ?, paypalname = NULL, aktiv = 0 WHERE MitarbeiterID = ?')
|
||||
->execute([$placeholderName, $placeholderEmail, $legacyMitarbeiterId]);
|
||||
}
|
||||
|
||||
$pdo->prepare(
|
||||
'UPDATE participants
|
||||
SET display_name = ?, email = NULL, email_norm = NULL, paypal_name = NULL, active = 0, user_id = NULL
|
||||
WHERE id = ? AND tenant_id = ?'
|
||||
)->execute([$placeholderName, $participantId, $tenantId]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
return true;
|
||||
} catch (Throwable $e) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function ledger_mirror_legacy_payment(PDO $pdo, int $tenantId, int $legacyPaymentId): void
|
||||
{
|
||||
$stmt = $pdo->prepare(
|
||||
|
||||
Reference in New Issue
Block a user