Beide Module wurden aus einem anderen Kundenprojekt kopiert und bereinigt: Knowledgecenter: - Bild-Cache (1.985 Dateien) geleert, Ordnerstruktur mit .gitkeep behalten - Files-Gallery-Lizenzschlüssel entfernt (config.php) - Kundenspezifische Kategorien gelöscht: Teil I/II/III QM-Struktur, nummerierte QM-Kapitel, Gremien (Präsidium/Finanzausschuss/Landesausschuss), Sitzungsservice-Serie, Protokoll-Abteilungen, Testeinträge - 56 generische Kategorien bleiben (Downloads, Onboarding, Personalthemen …) Tasks: - Alle Betriebsdaten gelöscht (114 Tasks, 914 Submissions, 579 Assignments) - Task-Definitionen und Verlinkungen geleert - Kategoriestruktur bleibt (Allgemein, IT, Personal, Buchhaltung …) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.5 KiB
2.5 KiB
Badge-Query: Überfällige & eskalierte Aufgaben pro Benutzer
Gibt die Anzahl offener Aufgaben zurück, die überfällig oder eskaliert sind — ideal für einen Navigations-Badge.
Query
SELECT COUNT(*) AS badge_count
FROM task_assignment ta
INNER JOIN task_definition td
ON td.id = ta.task_id
AND td.active = 1
WHERE ta.main_contact_id = :contact_id
AND ta.status IN ('overdue', 'open', 'in_progress', 'approval_pending', 'rejected')
AND (
ta.status = 'overdue'
OR ta.escalation_level > 0
OR (ta.due_at IS NOT NULL AND ta.due_at < NOW())
)
Warum diese Bedingungen?
| Bedingung | Grund |
|---|---|
td.active = 1 |
Deaktivierte Aufgaben sollen keinen Badge erzeugen |
ta.status IN (...) |
Nur nicht-abgeschlossene Status — completed und expired sind erledigt |
ta.status = 'overdue' |
Wurde bereits vom EscalationService als überfällig markiert |
ta.escalation_level > 0 |
Eskalierte Aufgaben unabhängig vom Status (z.B. open aber schon eskaliert) |
ta.due_at < NOW() |
Safety-Net: fängt Aufgaben, bei denen der Cronjob den Status noch nicht aktualisiert hat |
Prepared-Statement (PHP)
$count = TaskCertDb::fetchOne(
"SELECT COUNT(*) AS badge_count
FROM task_assignment ta
INNER JOIN task_definition td
ON td.id = ta.task_id
AND td.active = 1
WHERE ta.main_contact_id = ?
AND ta.status IN ('overdue','open','in_progress','approval_pending','rejected')
AND (
ta.status = 'overdue'
OR ta.escalation_level > 0
OR (ta.due_at IS NOT NULL AND ta.due_at < NOW())
)",
'i',
$contactId
);
$badgeCount = (int) ($count['badge_count'] ?? 0);
Variante: Aufschlüsselung nach Typ
Falls du im Badge oder Tooltip zwischen überfällig und eskaliert unterscheiden willst:
SELECT
SUM(ta.status = 'overdue' OR (ta.due_at IS NOT NULL AND ta.due_at < NOW())) AS overdue_count,
SUM(ta.escalation_level > 0) AS escalated_count,
COUNT(*) AS total_badge_count
FROM task_assignment ta
INNER JOIN task_definition td
ON td.id = ta.task_id
AND td.active = 1
WHERE ta.main_contact_id = :contact_id
AND ta.status IN ('overdue', 'open', 'in_progress', 'approval_pending', 'rejected')
AND (
ta.status = 'overdue'
OR ta.escalation_level > 0
OR (ta.due_at IS NOT NULL AND ta.due_at < NOW())
)
Performance
Der Index idx_task_assignment_contact_status_due (main_contact_id, status, due_at) deckt diese Query optimal ab. Kein Full-Table-Scan nötig.