Unterrichtsplanung: Serienerzeugung, Stundenraster, Aufsichten & Vertretung (Kapitel 4.2/4.3 Nachtrag)

Stunden serienweise aus dem Stundenplan erzeugen (4.2.5); Stundenraster
(Uhrzeiten je Stunde) in den Einstellungen mit Zeitbedarf-Rückmeldung im
Verlaufsplan-Editor; wiederkehrende Pausenaufsicht; neuer "Vertretung
eintragen"-Dialog für einmalige Vertretungsaufsicht, Vertretungsstunde,
Sondereinsätze (Ausflüge, Berufsmessen) und schlichten Stundenausfall.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 21:59:07 +02:00
co-authored by Claude Sonnet 5
parent 99b2de6519
commit d6dee72acc
30 changed files with 2743 additions and 48 deletions
+144 -9
View File
@@ -248,10 +248,20 @@ gruppenspezifischen Tab "Planung" (`GroupDetailView`), siehe unten.
ins Schülerheft übertragen).
- [x] **4.2.3** Status `Planned → Conducted` setzen, Reflexionsfeld nach der Stunde.
- [x] **4.2.4** Stunden verschieben (z.B. bei Ausfall) — Folgestunden automatisch nachrücken.
- [ ] **4.2.5** Stunden serienweise aus dem Stundenplan (4.3) erzeugen. Bewusst nicht mit einem
Ersatz-Mechanismus vorgezogen — hängt an 4.3 (Wochentag/Stunden-Muster aus dem Stundenplan),
ein selbstgebautes "N Wochenstunden anlegen" wäre nur Mehrarbeit, die 4.3 später doppelt.
Einzige Möglichkeit, Stunden anzulegen, bleibt vorerst der manuelle " Stunde"-Dialog (4.2.2).
- [x] **4.2.5** Stunden serienweise aus dem Stundenplan (4.3) erzeugen — neuer Button
"Serie erzeugen" in der Stunden-Toolbar der Planung
([GenerateLessonSeriesDialog.axaml](LehrerApp.Desktop/Views/Groups/GenerateLessonSeriesDialog.axaml),
`GenerateLessonSeriesDialogViewModel` in
[PlanningViewModels.cs](LehrerApp.Desktop/ViewModels/Groups/PlanningViewModels.cs)). Legt für
jeden Wochentag/Stunde, den die Gruppe laut `TimetableSlot` (4.3) hat, im gewählten Zeitraum
eine `Lesson` an; Zeitraum ist standardmäßig `Unit.StartDate``Unit.EndDate`, falls gesetzt.
Schulferien/Feiertage werden übersprungen (dieselbe Prüfung wie im Stundenplan-Wochenraster),
bereits vorhandene Termine (gleiches Datum + gleiche Stundennummer der Gruppe, unabhängig von
der Einheit) nicht doppelt angelegt. Ergebnis ("3 Stunde(n) angelegt, 1 durch Ferien/Feiertage
übersprungen, ...") kommt als Toast (erste tatsächliche Nutzung von
`NotificationService.ShowSuccess`, bis dahin nur `ShowError` im Einsatz). Neue Stunden haben
bewusst kein Thema (Platzhalter zum Ausfüllen) — die "Thema erforderlich"-Pflicht des
manuellen " Stunde"-Dialogs gilt hier nicht.
Umgesetzt über den neuen Tab "Planung" in
[GroupDetailView.axaml](LehrerApp.Desktop/Views/Groups/GroupDetailView.axaml)
@@ -306,6 +316,31 @@ Design-Entscheidungen:
typisierte `Lessons`-Collection, da die alten Felder nach der Modelländerung beim typisierten
Deserialisieren sonst bereits verworfen wären, bevor sie gelesen werden können.
**Nachtrag zu 4.2.2 (Stundenraster + Zeitbedarf-Rückmeldung):** Der Verlaufsplan-Editor kannte bis
dahin nur die geplante Gesamtdauer, nicht wie viel Zeit die Stunde laut Stundenplan tatsächlich
hat. Neuer Tab "Stundenraster" in den Einstellungen pflegt Beginn/Ende je Stundennummer (1.10.
Stunde, `PeriodScheduleService` — JSON-Datei, gleiches Muster wie
`SchoolCalendarSettingsService`/`PrivacySettingsService`). Nicht jede Stunde muss eingetragen sein.
- **Doppelstunden-Erkennung:** Ausgehend von der eingetragenen Stundennummer wird so lange die
jeweils nächste Periode addiert, wie der Stundenplan (4.3, `TimetableSlot`) für dieselbe Gruppe
am selben Wochentag *dort ebenfalls* einen Slot hat — eine Lesson mit Stundennummer 3 bekommt
bei einer Doppelstunde 3./4. also automatisch 90 statt 45 Minuten als Vergleichsbasis, ohne dass
das irgendwo separat markiert werden muss. Gehört die Folgeperiode einer anderen Gruppe, wird sie
korrekt nicht mitgezählt.
- **Farbskala** (`LessonDialogViewModel.TimeBudgetColor`, Nutzer-Vorgabe): 9396 % Auslastung ist
der Zielbereich (grün) — ein kleiner Puffer, da 100 % laut Nutzer "meist schon knapp" ist. Von
dort Richtung 100 % wird es zunehmend orange, darüber (überplant) kräftiger rot. Für "deutlich zu
wenig geplant" (unter 70 %) hatte der Nutzer noch keine feste Vorstellung — hier bewusst ein
neutrales Blaugrau statt Rot gewählt (kein Fehler, nur "hier geht noch was"); Grenzwerte/Farben
sind über die switch-Ausdrücke leicht nachjustierbar.
- **Beginn wird beim Setzen der Stundennummer automatisch aus dem Stundenraster übernommen**,
sofern noch keiner eingetragen ist (überschreibt nie einen bereits vorhandenen Wert) — damit
entfällt die bisher manuelle Pflege des "Beginn"-Felds für Stunden, die im Stundenraster
hinterlegt sind, ganz von selbst.
- Ohne Stundennummer/gültiges Datum oder ohne im Stundenraster hinterlegte Zeiten für die
betroffene(n) Periode(n) bleibt die Rückmeldung schlicht ausgeblendet statt eine erfundene Dauer
vorzutäuschen.
**Ideensammlung "Live-Unterrichtsmodus" (noch nicht geplant, nicht Teil von 4.2):** beim
Besprechen des Verlaufsplan-Redesigns kamen weitergehende Wünsche auf, die bewusst zurückgestellt
wurden, da sie eigene Datenmodelle (Live-Session-Zustand, Phasen-Verschiebung zwischen Stunden)
@@ -467,6 +502,76 @@ gezeigten Datum statt an "heute" — das Bearbeiten-Raster (zeigt ohnehin nur da
Muster ohne Datum) behält die alte, "heute"-verankerte Berechnung. Beim erneuten Navigieren in den
Stundenplan (Sidebar-Klick) springt die Ansicht wieder auf die laufende Woche zurück.
**Nachtrag zu 4.3, fünfte Iteration (Aufsichten + Vertretung):** Nutzer-Feedback: zwischen manchen
Stunden ist auch Pausenaufsicht zu erledigen, und gelegentlich kommen Sonderfälle vor — eine
Vertretungsaufsicht für einen erkrankten Kollegen, oder eine Vertretungsstunde in einer eigenen
oder fremden Lerngruppe.
- **Neue Modelle** ([Planning.cs](LehrerApp.Core/Models/Planning.cs)): `SupervisionDuty`
(wiederkehrend, Wochentag + "Pause nach Stunde X" + Ort — `AfterPeriod = 0` heißt Frühaufsicht
vor der 1. Stunde) und `SubstitutionEntry` (einmalig, an einem konkreten Datum — entweder
`Kind = Supervision` oder `Kind = Lesson`). Bewusst getrennt von `TimetableSlot`/`Lesson`: die
wiederkehrende Aufsicht hat keinen Gruppenbezug, und die meisten Vertretungsstunden sind keine
durchgeplanten Einheiten-Stunden.
- **Wiederkehrende Aufsicht wird nur in den Einstellungen gepflegt** (neuer Tab "Aufsichten",
analog zum Kürzel-Katalog: Liste + Formular, kein Klick-Dialog im Stundenplan-Raster selbst —
anders als bei `TimetableSlot`, weil eine kleine, seltene Liste hier ergonomischer ist als ein
Klick durchs ganze Raster). Pro Wochentag/Pause höchstens eine Aufsicht (eindeutiger Index,
freundliche Fehlermeldung wie bei `TimetableSlot`).
- **Anzeige im Stundenplan:** Aufsicht-Zeilen werden zwischen den betroffenen Stundenzeilen sowohl
im Bearbeiten-Raster als auch im Wochenraster eingefügt (nur wenn für die jeweilige Pause
tatsächlich etwas hinterlegt ist, sonst bleibt die Zeile weg) — `TimetableCellItem`/`WeekCellItem`
bekamen dafür `IsSupervisionRow`/`IsSupervisionCell` als weitere, sich gegenseitig ausschließende
Zellenarten (gleiches Muster wie die bestehenden `IsHeader`/`IsPeriodLabel`/`IsSlotCell`), statt
eine zweite `ItemsControl` neben das bestehende `UniformGrid` zu setzen.
- **"Vertretung eintragen"**-Dialog (neuer Button neben "Stundenplan bearbeiten" im "Heute"-Tab,
[SubstitutionEntryDialogViewModel.cs](LehrerApp.Desktop/ViewModels/Planning/SubstitutionEntryDialogViewModel.cs))
deckt beide Sonderfälle ab. Eine Vertretungsaufsicht/-stunde für ein konkretes Datum überschreibt
in Wochenraster, Bearbeiten-Zeile bzw. Tagesliste die sonst dort angezeigte reguläre Information
für diese eine Stunde/Pause — sie beschreibt ja, was an dem Tag tatsächlich passiert.
Vertretungsstunden ohne passenden `TimetableSlot` (z.B. fremde Gruppe zu einer Zeit, zu der man
sonst frei hat) werden trotzdem ergänzt, nicht verworfen.
- **Entscheidung zur eigenen-Gruppe-Frage** (mit dem Nutzer abgestimmt): Standard bleibt der
einfache Weg — nur ein `SubstitutionEntry` mit Thema, wie bei einer fremden Gruppe. Nur wenn die
gewählte eigene Gruppe mindestens eine `Unit` hat, erscheint zusätzlich eine Checkbox "Direkt als
Stunde in der Einheit übernehmen" (mit Einheiten-Auswahl) — dann entsteht *zusätzlich* eine
echte `Lesson` in dieser Einheit. Der `SubstitutionEntry` bleibt in beiden Fällen bestehen (er
ist die Anzeige-Quelle für den Plan), die `Lesson` ist rein für die Fortschritts-/Reihenfolge-
Bilanz der Einheit gedacht und wird im Stundenplan nicht separat angezeigt.
**Nachtrag zu 4.3, sechste Iteration (Sondereinsätze):** Nutzer-Feedback: neben Vertretung gibt es
auch Sondereinsätze wie Ausflüge oder Berufsmessen, die einen Teil des Tages oder den ganzen Tag
blockieren, ohne dass jemand vertreten wird.
- `SubstitutionKind` um `SpecialAssignment` erweitert; `SubstitutionEntry` bekam `FromPeriod`/
`ToPeriod` (Stundenbereich) und `IsAllDay` (ganztägig statt Stundenbereich). Dieselbe dritte Art
im "Vertretung eintragen"-Dialog (`SubstitutionKindDisplay` jetzt mit drei statt zwei Optionen).
Bewusst **kein** "Als Stunde in der Einheit übernehmen" für Sondereinsätze — ein Ausflug ist
inhaltlich kein Verlaufsplan-Eintrag, anders als eine Vertretungsstunde.
- **Anzeige im Wochenraster:** ein Sondereinsatz überdeckt für seinen Wochentag jede Perioden-Zelle
im belegten Bereich (bei `IsAllDay` alle 10 Stunden) mit derselben Kachel (Farbe `#00838F`,
deutlich von Vertretung-Lila unterscheidbar) — dieselbe Überschreiben-Logik wie bei
Vertretungsstunden, nur über mehrere Perioden statt einer einzelnen.
- **Anzeige in der Tagesliste:** eigener Abschnitt `TodaySpecialAssignments` (wie bei den
Aufsichten) statt Wiederholung über mehrere Zeilen — ein ganztägiger Sondereinsatz würde sonst
zehnmal in der Liste auftauchen.
- **Mehrtägige Sondereinsätze (Klassenfahrt) bewusst nicht als Datumsbereich modelliert** — mit
dem Nutzer abgestimmt: `SubstitutionEntry.Date` bleibt ein einzelnes Datum. Klassenfahrten dauern
laut Nutzer höchstens ~5 Tage und kommen alle ein bis zwei Jahre vor — dafür lohnt sich kein
eigener Datumsbereich mit den nötigen Änderungen an `GetByDate`/Wochenraster-Abfragen; ein
Sondereinsatz über mehrere Tage wird einfach als mehrere Einzeleinträge (einer pro Tag) erfasst.
**Nachtrag zu 4.3, siebte Iteration (Stundenausfall):** Nutzer-Feedback: es kann auch sein, dass
eine Stunde schlicht ausfällt, ohne dass die eigene Abwesenheit der Grund ist — z.B. fällt der
NAT-Unterricht der 6a aus, weil die 6a selbst auf Klassenfahrt ist. Kein Vertretungsfall (niemand
übernimmt), kein Sondereinsatz (die eigene Zeit ist nicht belegt).
- `SubstitutionKind` um `Cancelled` erweitert, vierte Option im "Vertretung eintragen"-Dialog.
Braucht nur Datum + Stundennummer + optionalen Grund — Fach und Gruppe werden beim Anzeigen aus
dem an der Stelle regulär eingetragenen `TimetableSlot` abgeleitet, nicht beim Anlegen manuell
erfasst (die Information steht ja schon im Stundenplan).
Bewusst kein "Als Stunde übernehmen" — ein Ausfall ist per Definition keine gehaltene Stunde.
- **Anzeige:** ersetzt im Wochenraster und in der Tagesliste die normale Stunden-Kachel/-Zeile für
die betroffene Stunde (Grau `#757575`, Aufschrift "Ausfall") — dieselbe Überschreiben-Logik wie
bei Vertretungsstunden und Sondereinsätzen, nur dass hier nichts an die Stelle tritt.
### 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.
@@ -507,6 +612,35 @@ Ausdrücklich als Idee für später festgehalten, **nicht** jetzt umsetzen:
sinnvoll auf die beiden Kacheln/Perioden aufteilen, damit z.B. gezielt nur die zweite Stunde
eines Blocks verschoben werden kann, ohne den ganzen Block anzufassen.
**Architekturentscheidung (Nachtrag, Konzeptgespräch):** Diskutiert wurde, ob eine eigene
Multiplattform-App für die Einheiten-/Stundenplanung sinnvoll ist — analog zum separaten
Tafelbilder-Vorhaben (eigene App, nur eine Schnittstelle zur LehrerApp, weil dort die
Interaktionsform — Zeichnen/Präsentationsmodus — grundsätzlich anders ist als CRUD). Für die
Unterrichtsplanung gilt das **nicht**: Planung findet zu 99,9 % am Desktop-PC oder MacBook statt
(Avalonia läuft dort bereits nativ), es besteht also kein Plattformzwang für eine separate App.
Entscheidung: **kein** eigenes Domainmodell/eigene App für Einheiten-/Stundenplanung — die
folgenden Punkte gehören direkt in `LehrerApp.Desktop`:
- [ ] **4.5.7** Graph über Aktivitätsphasen und Anspruchsniveau im zeitlichen Verlauf einer
Lesson/Einheit (baut auf `LessonPhaseStep`/`Niveau` auf), um die Stundenverteilung besser
einschätzen zu können.
- [ ] **4.5.8** Kompetenzen je Aufgabe/Phase verknüpfen — nutzt den bestehenden
`CompetencyDomain`/`CompetencyItem`-Katalog (siehe Kompetenzen-Tab in den Einstellungen),
bisher nur für Klausuraufgaben (`ExamTask.CompetencyCodes`) verknüpft, nicht für
Verlaufsplan-Phasen.
- [ ] **4.5.9** KI-gestützte Planungsunterstützung über eine Schnittstelle zu einer LLM-API, um
Einheiten/Stunden mit Hilfe vorzuschlagen und weiterzuentwickeln. Bedarf eines abgesicherten
Zwischenelements auf dem eigenen Server (Ablösung/Verbesserung des bisherigen
PHP-Zwischenelements für Elternbriefe) mit interner Abrechnung/Nutzungskontrolle, damit der
API-Schlüssel nicht im Client landet.
- [ ] **4.5.10** Falls doch ein schlanker Companion-/WebApp-Client entstehen soll: bewusst
**minimaler** Funktionsumfang — nur Wochenraster ansehen, eine Stunde verschieben, oder eine
Stunde als "Umplanung nötig" flaggen. Kein Editor für Einheiten/Kompetenzen/KI-Planung dort.
Technisch schon vorbereitet: `LehrerApp.Sync`/`LehrerApp.Api` haben mit `PlainSyncEvent` und
`DeviceType.Companion` bereits eine Klartext-Sync-Schiene für genau diese Art von leichtem,
nicht-Desktop-Client (siehe `PlainEventStore`, `MapPlainSyncEndpoints`) — ein "Umplanung
nötig"-Flag käme darüber rein und würde nach dem Sync als Hinweis/Badge an der betroffenen
Stunde bzw. im Dashboard erscheinen, bis es am Desktop bearbeitet oder bewusst abgehakt wird.
---
## 5. Schülerdokumentation
@@ -1025,9 +1159,10 @@ Die Abschnitte sind thematisch, nicht chronologisch nummeriert. Sinnvolle Bearbe
6. ~~**Kapitel 4.1 + 4.2 + 4.3** (Unterrichtsplanung: Einheiten, Einzelstunden, Stundenplan)~~
erledigt, inkl. mehrerer Nachtrag-Iterationen aus Nutzer-Feedback (Ferien-Pflege in den
Einstellungen, Wochenraster mit Wochennavigation, Ferientage ausgegraut). ~~**Kapitel 4.4.1/
4.4.2**~~ — erledigt (im Zuge der 4.3-Nachträge miterledigt). Offen bleiben **4.4.3**
(Abgabefristen im Kalender), **4.2.5** (Serienerzeugung von Stunden aus dem Stundenplan) und
**4.5** (engere Vernetzung Stundenplan ↔ Lesson-Planung — ausdrücklich vom Nutzer
zurückgestellt, nicht aus Unklarheit).
**→ nächster sinnvoller Schritt: 4.4.3 oder 4.2.5, je nach Bedarf.**
4.4.2**~~ — erledigt (im Zuge der 4.3-Nachträge miterledigt). ~~**4.2.5**~~ (Serienerzeugung
von Stunden aus dem Stundenplan) — erledigt. Offen bleiben **4.4.3** (Abgabefristen im
Kalender) und **4.5** (engere Vernetzung Stundenplan ↔ Lesson-Planung — ausdrücklich vom
Nutzer zurückgestellt, nicht aus Unklarheit; Desktop bekommt dort perspektivisch Graph/
Kompetenz-Verknüpfung/KI-Planung, ein möglicher Companion-Client bleibt bewusst minimal).
**→ nächster sinnvoller Schritt: 4.4.3, sonst weiter mit Kapitel 6/10/11.**
7. **Kapitel 6** (Arbeitszeit), **11** (Export), **10** (Sync) — danach.