Module tasks + knowledgecenter_update aus Kundenprojekt übernehmen (bereinigt)

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>
This commit is contained in:
2026-06-22 09:20:02 +02:00
parent 2e75ff7d59
commit 743476f64a
136 changed files with 38100 additions and 627 deletions

View File

@@ -0,0 +1,79 @@
# 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
```sql
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)
```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:
```sql
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.