Files
clemensandClaude Sonnet 5 aeb687f42e M5: Hinweise auf tenant-scoped Notices umziehen, Mitgliederzugang auf Rollen umstellen
Hinweise:
- Neue Tabelle notices (tenant-scoped, Soft-Delete via deleted_at) loest
  die global unscoped kl_hinweise als aktive Datenquelle ab; Migration
  uebernimmt einmalig aktuell gueltige kl_hinweise-Eintraege fuer den
  Default-Mandanten. kl_hinweise bleibt als Golden-Master-Referenz stehen.
- hinweise.php und der Banner in header.php sind tenant-scoped umgestellt.

Mitgliederverwaltung:
- mitarbeiterverwalten.php verwaltet jetzt participants (tenant-scoped)
  statt der global unscoped kl_Mitarbeiter-Tabelle als primaere Quelle.
  Das behebt nebenbei ein Mandanten-Datenleck: jeder SaaS-Mandant mit
  Owner/Admin-Rolle haette zuvor die komplette Default-Mandanten-
  Mitgliederliste sehen und bearbeiten koennen.
- Fuer den Default-Mandanten bleibt Dual-Write nach kl_Mitarbeiter
  bestehen, damit stricheintragen.php/einzahlung.php weiter funktionieren;
  andere Mandanten werden rein participant-nativ verwaltet.
- Die Legacy-Administrator-Checkbox ist raus. Stattdessen kann ein Admin
  je Mitglied unabhaengig von Name/E-Mail einen Login-Zugang mit Rolle
  (member/treasurer/admin) gewaehren oder entziehen
  (saas_grant_participant_access / saas_revoke_participant_access).
  Einladung laeuft ueber den bestehenden Passwort-Reset-Mechanismus,
  Entzug setzt die Mitgliedschaft auf revoked statt sie zu loeschen.
- Kompletter Flow live getestet: anlegen, Zugang gewaehren, Einladungsmail,
  Passwort setzen, Login, Rollenschutz, Zugang entziehen, Login-Sperre.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 00:18:55 +02:00

73 lines
1.8 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
/**
* @return array{id: int, message: string, valid_from: string, valid_until: string}|null
*/
function notices_fetch_active(PDO $pdo, int $tenantId): ?array
{
$stmt = $pdo->prepare(
"SELECT id, message, valid_from, valid_until
FROM notices
WHERE tenant_id = ?
AND deleted_at IS NULL
AND valid_from <= NOW()
AND valid_until >= NOW()
ORDER BY valid_until ASC
LIMIT 1"
);
$stmt->execute([$tenantId]);
$row = $stmt->fetch();
return $row !== false ? $row : null;
}
/**
* @return list<array{id: int, message: string, valid_from: string, valid_until: string}>
*/
function notices_fetch_all(PDO $pdo, int $tenantId): array
{
$stmt = $pdo->prepare(
"SELECT id, message, valid_from, valid_until
FROM notices
WHERE tenant_id = ?
AND deleted_at IS NULL
ORDER BY valid_until DESC"
);
$stmt->execute([$tenantId]);
return $stmt->fetchAll();
}
function notices_create(PDO $pdo, int $tenantId, string $message, string $validUntil, ?int $createdByUserId): bool
{
$message = trim($message);
if ($message === '' || $validUntil === '') {
return false;
}
$stmt = $pdo->prepare(
'INSERT INTO notices (tenant_id, message, valid_from, valid_until, created_by_user_id)
VALUES (?, ?, NOW(), ?, ?)'
);
return $stmt->execute([$tenantId, $message, $validUntil, $createdByUserId]);
}
function notices_soft_delete(PDO $pdo, int $tenantId, int $noticeId): bool
{
$stmt = $pdo->prepare(
'UPDATE notices
SET deleted_at = NOW()
WHERE id = ?
AND tenant_id = ?
AND deleted_at IS NULL'
);
$stmt->execute([$noticeId, $tenantId]);
return $stmt->rowCount() > 0;
}