fix: WebUntis-Vertretungen für kombinierte Gruppen und Karteileichen

- ClassToken-Vergleich normalisiert jetzt symmetrisch (beide Seiten) und
  ExtractClassTokens akzeptiert ";" und "," als Trennzeichen zwischen
  Klassen, da nie an einem echten kombinierten Termin verifiziert wurde,
  welches WebUntis tatsächlich verwendet.
- Abweichende Vertretungen tragen jetzt den genauen Vergleichsgrund
  (Fach/Klasse, roh vs. erwartet) in ihrer Beschreibung.
- Automatisch erzeugte Vertretungen, die bei einem späteren Poll nicht
  mehr abweichen, werden jetzt aktiv wieder entfernt statt als
  Karteileichen stehen zu bleiben (UntisDiffResult.SubstitutionExternalIdsToDelete).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 18:43:36 +02:00
co-authored by Claude Sonnet 5
parent 4eb4d0a946
commit 4b9bcfe85d
7 changed files with 240 additions and 14 deletions
+30
View File
@@ -1130,6 +1130,36 @@ wurde bei jedem Poll erneut als "abweichend" gemeldet.
(`"10c"` in `"10c HED"`) waren nie betroffen, da dort kein Trennzeichen im Spiel ist; deshalb
ist der Fehler dem Nutzer erst bei diesem speziellen Kurs aufgefallen.
**Nachtrag zu 4.3, sechzehnte Iteration (Bugfix: falsche Vertretungen für kombinierte Gruppen
blieben trotz behobenem Vergleich stehen):** Nutzer-Feedback nach der fünfzehnten Iteration: "Es
klappt nicht. [...] Die falschen Vertretungen stehen noch bei den Kursen. Immer die Kurse mit
Lerngruppen, die aus mehreren Klassen zusammengesetzt sind." Zwei Ursachen, nacheinander gefunden:
- Der Fix aus der fünfzehnten Iteration entfernte Leerzeichen nur auf der `evt.Description`-Seite,
nicht auf `mapping.ClassToken` selbst — schlug also weiterhin fehl, sobald `ClassToken` ein
eingebettetes Leerzeichen trägt (z.B. wenn `ExtractClassTokens` die Klassen mangels bekanntem
Trennzeichen nicht aufsplitten konnte). Fix: `RemoveWhitespace` symmetrisch auf beide Seiten
angewendet; `ExtractClassTokens` akzeptiert jetzt zusätzlich `,` als Trennzeichen (nicht nur
`;`), da nie an einem echten kombinierten Termin verifiziert wurde, welches WebUntis tatsächlich
verwendet. Zur Eingrenzung ohne weitere Rateversuche schreibt eine abweichende Vertretung jetzt
außerdem den genauen fehlgeschlagenen Vergleich (roher Fach-/Klassen-Wert) in ihre eigene
Beschreibung (`UntisDiffService.DeviationReason`).
- Der eigentliche, tiefere Bug: der Nutzer bestätigte danach neu und der Vergleich lief
nachweislich mit aktuellem Code (die neue Diagnose-Beschreibung erschien auf einer anderen,
echten Abweichung), aber die falschen Vertretungen für Mathe-E-Kurs/Chemie G blieben ohne die
neue Diagnose-Beschreibung stehen — sie waren Karteileichen aus einem Poll VOR dem Fix.
`UntisDiffService.Diff` schrieb bislang ausschließlich neu erkannte/weiterhin bestehende
Abweichungen; es gab keinen Pfad, der eine zuvor automatisch erzeugte `SubstitutionEntry`
wieder entfernt, sobald ein späterer Poll dieselbe Zeile nicht mehr als Abweichung einstuft.
Fix: `UntisDiffResult` bekommt `SubstitutionExternalIdsToDelete` — befüllt für (a) eine
Unterrichtsstunde, die nicht mehr abweicht, (b) eine Aufsicht, die jetzt einer regulären
`SupervisionDuty` entspricht, und (c) eine zuvor als fehlend gemeldete Stunde, die im Feed
wieder auftaucht. `UntisSyncService.ProcessIcsText` löscht dafür den vorhandenen Eintrag über
`ISubstitutionEntryRepository.GetByExternalId`/`Delete` (no-op, falls keiner existiert).
- Damit räumen sich einmal fälschlich erzeugte automatische Vertretungen künftig von selbst auf,
sobald der zugrundeliegende Vergleich beim nächsten Poll keine Abweichung mehr findet — nicht
nur bei diesem konkreten Bugfix, sondern auch bei jeder künftigen Korrektur der Zuordnung durch
den Nutzer selbst.
### 4.4 Wochen-/Tagesansicht
- [x] **4.4.1** Kalenderansicht über alle Gruppen: Woche und Tag — siehe Nachtrag zu 4.3
("Heute"-Tab: Tagesliste unten angedockt, gruppenübergreifendes Wochenraster darüber, inkl.