Klassenlehrer: Verspätungen nicht mehr als fehlende Entschuldigung, echter Ferienkalender für Fehlquote
CI / build-and-test (push) Canceled after 0s

Verspätungen sind i.d.R. nicht entschuldigungsfähig - "Offene Entschuldigungen" erinnert dafür
nicht mehr, stattdessen eskaliert die Mustererkennung ab 5 Verspätungen im Schuljahr zu einem
Elterngespräch/Brief-Hinweis mit Wiedervorlage-Option.

Die Jahresfehlquote nutzte bislang den 1. August als fest verdrahteten Schuljahresbeginn und
zählte damit noch laufende Sommerferien als Schultage mit, was die Quote kurz nach
Schuljahresbeginn stark verfälschte (~57% statt ~100% bei durchgehend fehlenden Schülern). Nutzt
jetzt den echten WebUntis-Ferienkalender (GetHolidaysAsync, gecacht in WebUntisSettingsService).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-31 11:56:35 +02:00
co-authored by Claude Sonnet 5
parent 527c186090
commit cdbed69d8b
6 changed files with 304 additions and 21 deletions
+54
View File
@@ -1679,6 +1679,60 @@ eigenen Unterricht abfragt und deshalb mit den regulären Lehrkraft-Rechten funk
`IStudentRepository`, `IParticipationRepository`, `IParticipationSessionRepository` (alle schon
als Singleton registriert, nur Konstruktor-Injection ergänzt).
**Bewusst zurückgestellt:** Elterngesprächs-Blatt als PDF — Konzept noch nicht geschärft genug.
- [x] **"Klassenlehrer"-Feature — Verspätungen nicht mehr als fehlende Entschuldigung, sondern als
eigenes Muster (August 2026):** Nutzer-Feedback: "Offene Entschuldigungen" erinnerte auch bei
Verspätungen, die aber i.d.R. gar nicht entschuldigungsfähig sind — die Erinnerung "Entschuldigung
fehlt" war hier gegenstandslos.
- `ClassTeacherOpenExcuseRow.Build` filtert jetzt zusätzlich `!a.IsLate` heraus — Verspätungen
tauchen nicht mehr in der Karte "Offene Entschuldigungen" auf und lösen darüber auch keine
Wiedervorlage mehr aus.
- Stattdessen zweite Eskalationsstufe in der Mustererkennung: die bestehende Kurzfrist-Regel
(≥2 Verspätungen in 7 Tagen → Warning-Hinweis ohne Aktion) bleibt, kommt aber erst zum Zug,
wenn eine neue Jahresschwelle (`LateYearEscalationThreshold = 5`, Verspätungen seit
Schuljahresbeginn) nicht bereits gerissen ist — dann Danger-Hinweis "Elterngespräch oder Brief
erwägen" mit eigenem "+"-Button (`CreateReminderForPatternNoticeCommand`, legt wie bei "Offene
Entschuldigungen" eine `WorkTask` an). Kernlogik aus dem bisher privaten `BuildPatternNotices`
in ein neues öffentliches, statisches `DetectLatePatterns` gezogen (gleiches Muster wie
`DetectWeekdayPatterns`), damit die Schwellenwerte ohne ViewModel-Instanz testbar sind.
`ClassTeacherPatternNotice` hat dafür ein neues `CanCreateReminder`-Flag (Default `false`,
steuert Sichtbarkeit des "+"-Buttons in der XAML).
- [x] **"Klassenlehrer"-Feature — Fehlquote seit Schuljahresbeginn zu niedrig kurz nach Schuljahres-
start (August 2026):** Nutzer-Feedback: Schüler*innen, die seit Unterrichtsbeginn nachweislich an
jedem Tag fehlten, zeigten trotzdem nur ~57 % statt der erwarteten ~100 % in
`ClassTeacherRosterRow.YearSummaryLabel`. Ursache: der Nenner (`SchoolDaysElapsed`) zählte
Werktage ab dem fest verdrahteten 1. August (`SchoolYearService.SchoolYearStart`) — die
tatsächlichen Sommerferien enden je nach Bundesland/Jahr aber erst Wochen später, und kurz nach
Schuljahresbeginn macht diese Restferienzeit einen großen Teil des bis dahin "verstrichenen"
Zeitraums aus (rechnerisch: absolut korrekte Fehlzeiten-Zähler, aber ein um mehrere Wochen zu
großer Nenner). Erster Fix-Versuch (`EstimateTermStart`, frühester Fehlzeiten-Eintrag der Klasse
als Näherung für den ersten Unterrichtstag) kam ohne zusätzlichen WebUntis-Abruf aus, war aber
nur eine Näherung. Nutzer-Hinweis: WebUntis kennt den echten Ferienkalender bereits
(`getHolidays`-Bericht, in `LehrerApp.WebUntis/WebUntisClient.GetHolidaysAsync` schon
implementiert, aber bis dahin nirgends im Desktop verdrahtet) — `EstimateTermStart` durch den
echten Kalender ersetzt:
- `WebUntisIntegrationService.GetHolidaysAsync` (neuer `UntisHolidayDto`) als dünner Wrapper,
gleiches Muster wie `GetSchoolYearsAsync`.
- Cache dafür bewusst nicht über die LiteDB-Tabellen von `UntisReportCacheService` (deren
heißes/kaltes Fenster ist auf sich laufend ändernde Fehlzeiten/Klassenbucheinträge
zugeschnitten) — Ferien ändern sich innerhalb eines Schuljahrs praktisch nie. Stattdessen
einfacher tagesgenauer Cache direkt in `WebUntisSettingsService`
(`CachedUntisHoliday`-Liste + `HolidaysFetchedAt`, unverschlüsselt, kein Geheimnis anders als
iCal-URL/API-Zugangsdaten in derselben Datei). Schlägt der Live-Abruf fehl, wird der zuletzt
bekannte Stand weiterverwendet statt die ganze Übersicht mit einem Fehler zu blockieren.
- `ClassTeacherOverviewViewModel.CountSchoolWeekdays` (ersetzt `CountWeekdays`) zählt Werktage
zwischen Schuljahresbeginn und heute abzüglich aller Ferienzeiträume — behebt damit nicht nur
die große Verzerrung kurz nach Schuljahresbeginn, sondern nebenbei auch die bislang akzeptierte
kleinere Ungenauigkeit durch Herbst-/Weihnachts-/Osterferien im weiteren Jahresverlauf (oben
unter "Trend & Fehlquote" noch als bewusste Vereinfachung dokumentiert — damit erledigt).
Reine, ohne ViewModel-Zustand testbare Kernlogik, gleiches Muster wie
`DetectWeekdayPatterns`/`DetectLatePatterns`.
Neue Abhängigkeit `WebUntisIntegrationService` in `ClassTeacherOverviewViewModel` (bereits als
Singleton registriert, nur Konstruktor-Injection ergänzt).
**Nicht behoben, weil mit den vorhandenen Daten nicht erkennbar:** Kolleg*innen, die die
Anwesenheitsliste nur sporadisch führen, drücken die Quote auf dieselbe Weise (fehlende
Fehlzeiten-Einträge an Tagen mit tatsächlichem Unterricht) — von echter Anwesenheit ist das aus
dem WebUntis-Fehlzeitenbericht allein nicht unterscheidbar, dafür bräuchte es Daten darüber, ob
für eine Stunde überhaupt eine Anwesenheitsprüfung stattfand.
### 4.4 Wochen-/Tagesansicht
- [x] **4.4.1** Kalenderansicht über alle Gruppen: Woche und Tag — siehe Nachtrag zu 4.3