namespace LehrerApp.Core.Models; public class Grade { public Guid Id { get; set; } = Guid.NewGuid(); public Guid StudentId { get; set; } public Guid GroupId { get; set; } public GradeCategory Category { get; set; } public string Value { get; set; } = ""; public DateOnly Date { get; set; } public double Weight { get; set; } = 1.0; public string? Note { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } public enum GradeCategory { Oral, Homework, Participation, Project, Other } /// /// Prozentuale Gewichtung von Klausuren/Mitarbeit/sonstigen Leistungen für die Zeugnisnote. /// Entweder gruppenspezifisch ( gesetzt) oder als Voreinstellung je /// Gruppentyp ( gesetzt, null). /// public class GradingScheme { public Guid Id { get; set; } = Guid.NewGuid(); public Guid? GroupId { get; set; } public GroupType? GroupType { get; set; } public double ExamsPercent { get; set; } public double ParticipationPercent { get; set; } public double OtherPercent { get; set; } public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } public class Unit { public Guid Id { get; set; } = Guid.NewGuid(); public Guid GroupId { get; set; } public string Title { get; set; } = ""; public DateOnly? StartDate { get; set; } public DateOnly? EndDate { get; set; } public List Competencies { get; set; } = []; public UnitStatus Status { get; set; } = UnitStatus.Planned; public string? Notes { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } public class Lesson : IHasAttachments { public Guid Id { get; set; } = Guid.NewGuid(); public Guid UnitId { get; set; } public Guid GroupId { get; set; } public DateOnly Date { get; set; } public int? LessonNumber { get; set; } public string Topic { get; set; } = ""; /// Optionaler Stundenbeginn — solange kein Stundenplan (Kapitel 4.3) existiert, manuell /// gepflegt. Dient nur der abgeleiteten Uhrzeit-Anzeige je Phase in . public TimeOnly? StartTime { get; set; } public List Phases { get; set; } = []; public TeachingTimelineState? TeachingTimeline { get; set; } public string? Homework { get; set; } /// Markiert, dass die hier eingetragene Hausaufgabe in einer Folgestunde besprochen/kontrolliert /// wurde — treibt das Stundenplan-Badge "Hausaufgabe kontrollieren" (4.5.4). public bool HomeworkChecked { get; set; } /// Bewusstes Abschalten der Erinnerung, ohne eine tatsächliche Kontrolle vorzutäuschen (z.B. /// wenn die Hausaufgabe absichtlich nicht mehr kontrolliert wird). public bool HomeworkCheckDismissed { get; set; } public string? Reflection { get; set; } /// Kompetenzcodes () aus dem Katalog, die dieser Stunde als /// Ganzes zugeordnet sind — analog zu , aber auf Stundenebene statt /// Einheitenebene. Bewusst noch keine Verknüpfung je einzelner /// (siehe TODO.md 4.5.8, weiterhin offen); diese Liste deckt nur die gröbere Zuordnung ab. public List Competencies { get; set; } = []; public LessonStatus Status { get; set; } = LessonStatus.Planned; /// Material/Arbeitsblätter sowie fachspezifische Anhänge (z.B. Experiment- und /// Gefährdungsbeurteilungs-Dokumente im Chemieunterricht) — dieselbe Anhang-Infrastruktur wie /// bei . public List Attachments { get; set; } = []; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } /// /// Eine Zeile im tabellarischen Stundenverlaufsplan (Phase/Dauer/Tätigkeit/Material/Kurzsymbol). /// ist die primäre Eingabe (man plant in Zeitblöcken); die Uhrzeit /// je Phase wird im Editor daraus abgeleitet, wenn gesetzt ist. /// ist bewusst ein einzelnes Freitextfeld statt einer erzwungenen /// Von/Nach-Struktur: manchmal ist es ein Materialfluss-Pfeil ("AB001->S"), manchmal nur eine /// Sozialform ohne Pfeil ("Plenum", "LDE"). Vorschläge kommen sowohl aus dem in den Einstellungen /// gepflegten Kürzel-Katalog () als auch aus bereits in anderen Stunden /// verwendeten Werten. /// public class LessonPhaseStep { public Guid Id { get; set; } = Guid.NewGuid(); public string Name { get; set; } = ""; public int DurationMinutes { get; set; } public string Activity { get; set; } = ""; public string Material { get; set; } = ""; public string Shorthand { get; set; } = ""; /// /// null = Hauptweg. Sonst Verweis auf einen benannten aus /// dem Katalog, über den Phasen alternativer Unterrichtsverläufe zusammengehören — /// Verlaufsplan-Editor und -Ansicht gruppieren danach. Bewusst kein Fork-Punkt-Bezug zum /// Hauptweg: eine Alternative beginnt in der Anzeige unabhängig ab dem Stundenbeginn, nicht ab /// einer gemeinsamen Verzweigungsstelle — für den schnellen Überblick ausreichend, siehe TODO.md. /// public Guid? AlternativePathId { get; set; } } public enum UnitStatus { Planned, Active, Completed } // Planned=0 und Conducted=1 bleiben absichtlich an ihren bisherigen numerischen Positionen: // LiteDB hat diese Werte bereits gespeichert. Die neuen Zustände werden nur angehängt, damit // vorhandene Daten ohne Migration weiterhin korrekt gelesen werden. public enum LessonStatus { Planned = 0, Conducted = 1, Draft = 2, Ready = 3, Cancelled = 4 } /// /// Katalogeintrag für einen wiederverwendbaren "alternativen Ablauf" (z.B. "Kurzversion" bei /// Zeitmangel), dem einzelne -Zeilen über /// zugeordnet werden. Wird direkt beim Zuweisen im /// Verlaufsplan-Editor angelegt (kein separates Verwaltungs-UI in den Einstellungen bisher). /// public class AlternativeLessonPath { public Guid Id { get; set; } = Guid.NewGuid(); public string Name { get; set; } = ""; /// Freitext, wann/wofür dieser Ablauf gedacht ist, z.B. "Bei Zeitmangel, wenn Aufgabe 3 nicht /// mehr passt." Absichtlich kein strukturiertes Bedingungsfeld (z.B. "wenn an Stelle X weniger /// als Y Minuten übrig sind") — das setzt eine Live-Zeiterfassung während des Unterrichtens /// voraus, die es noch nicht gibt (siehe Live-Unterrichtsmodus-Ideensammlung in TODO.md). public string? Description { get; set; } public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } /// /// Ein fester Termin im wöchentlichen Stundenplan (4.3): eine Lerngruppe trifft sich an einem /// Wochentag zu einer bestimmten Stunde. Wiederkehrendes Muster, kein konkretes Datum — für /// tatsächlich gehaltene Einzelstunden siehe . Pro Wochentag/Stunde ist /// höchstens eine Gruppe eingetragen (ein Lehrer kann nicht gleichzeitig an zwei Orten sein). /// public class TimetableSlot { public Guid Id { get; set; } = Guid.NewGuid(); public Guid GroupId { get; set; } public DayOfWeek Weekday { get; set; } public int PeriodNumber { get; set; } public string? Room { get; set; } } /// /// Unterrichtsfreier Zeitraum (4.3.5): Schulferien werden manuell gepflegt (nicht algorithmisch /// herleitbar, jährlich neu von den Bundesländern festgelegt). Gesetzliche Feiertage werden /// dagegen berechnet (PublicHolidayService) und nicht in der Datenbank gespeichert. /// public class SchoolHoliday { public Guid Id { get; set; } = Guid.NewGuid(); public string Name { get; set; } = ""; public DateOnly StartDate { get; set; } public DateOnly EndDate { get; set; } } public enum GermanState { BW, BY, BE, BB, HB, HH, HE, MV, NI, NW, RP, SL, SN, ST, SH, TH } /// /// Wiederkehrende Pausenaufsicht (kein Bezug zu einer Lerngruppe, anders als /// ). = 0 bedeutet "vor der 1. Stunde" /// (Frühaufsicht), sonst "in der Pause nach dieser Stunde". Pro Wochentag/Pause höchstens eine /// Aufsicht (ein Lehrer kann nicht an zwei Orten gleichzeitig Aufsicht führen). /// public class SupervisionDuty { public Guid Id { get; set; } = Guid.NewGuid(); public DayOfWeek Weekday { get; set; } public int AfterPeriod { get; set; } public string Location { get; set; } = ""; } public enum SubstitutionKind { Supervision, Lesson, SpecialAssignment, Cancelled } /// /// Einmalige Ausnahme vom regulären Plan an einem konkreten Datum: eine Vertretungsaufsicht /// (zusätzlich zur oder anstelle einer regulären ), eine /// Vertretungsstunde in einer eigenen oder fremden Lerngruppe, ein Sondereinsatz (Ausflug, /// Berufsmesse, Exkursion, ...), der einen Teil des Tages oder den ganzen Tag blockiert, oder ein /// schlichter Stundenausfall ohne Ersatz (z.B. weil die betroffene Gruppe selbst auf Klassenfahrt /// ist). Bewusst getrennt von : die meisten dieser Einträge sind nicht Teil der /// durchgeplanten Einheiten-Reihenfolge (siehe TODO.md, Nachtrag zu 4.3) — nur bei /// kann beim Anlegen ausdrücklich "als Stunde in der Einheit /// übernehmen" gewählt werden, was zusätzlich eine echte erzeugt; dieser /// Eintrag hier bleibt trotzdem bestehen, da er (unabhängig von der Einheiten-Fortschrittsanzeige) /// das, was tatsächlich im Plan an diesem Tag stattfand, festhält. /// public class SubstitutionEntry { public Guid Id { get; set; } = Guid.NewGuid(); public DateOnly Date { get; set; } public SubstitutionKind Kind { get; set; } /// Bei und /// gesetzt — bei Cancelled wird Gruppe/Fach zur Anzeige aus dem an dieser Stelle regulär /// eingetragenen abgeleitet, nicht hier gespeichert. public int? PeriodNumber { get; set; } /// Nur bei gesetzt — wie bei /// , 0 = vor der 1. Stunde. public int? AfterPeriod { get; set; } /// Nur bei und nicht : /// der belegte Stundenbereich (inklusive). public int? FromPeriod { get; set; } public int? ToPeriod { get; set; } /// Nur bei : blockiert den ganzen Tag statt /// nur . public bool IsAllDay { get; set; } /// Gesetzt, wenn es sich um eine eigene Lerngruppe handelt — bei fremden/unbekannten Gruppen /// oder Sondereinsätzen ohne Gruppenbezug (z.B. Berufsmesse) bleibt es null und nur /// beschreibt ggf., um welche Gruppe es ging. public Guid? GroupId { get; set; } public string GroupLabel { get; set; } = ""; /// Thema (bei Lesson), Grund/Ort (bei Supervision, z.B. "Vertretung für Hr. Müller") bzw. /// Bezeichnung (bei SpecialAssignment, z.B. "Ausflug ins Museum", "Berufsmesse"). public string Description { get; set; } = ""; public string? Notes { get; set; } /// Gesetzt, wenn dieser Eintrag automatisch aus dem WebUntis-iCal-Abgleich entstanden ist — /// trägt die stabile iCal-UID des auslösenden Termins. Macht wiederholte Abgleich-Läufe /// idempotent (Update statt Duplikat, siehe ISubstitutionEntryRepository.GetByExternalId) und /// unterscheidet automatisch erzeugte von von Hand eingetragenen Ausnahmen. Bei Handeinträgen /// (SubstitutionEntryDialogViewModel) bleibt es null. public string? ExternalId { get; set; } } /// /// Zeugnisnote eines Schülers in einer Lerngruppe für einen Zeitraum (Halbjahr/Gesamtjahr). /// ist das zuletzt berechnete Ergebnis; /// überschreibt es bei pädagogischem Ermessen (erfordert ). /// Nach dem Festschreiben () wird der Datensatz nicht mehr neu berechnet. /// public class ReportGrade { public Guid Id { get; set; } = Guid.NewGuid(); public Guid StudentId { get; set; } public Guid GroupId { get; set; } public string Period { get; set; } = ""; public string CalculatedValue { get; set; } = ""; public string? OverrideValue { get; set; } public string? OverrideReason { get; set; } public bool IsLocked { get; set; } public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } /// Live timing is separate from the original lesson plan. public class TeachingTimelineState { public DateTime StartUtc { get; set; } public DateTime EndUtc { get; set; } public DateTime? HeldSinceUtc { get; set; } public Guid? HeldPhaseId { get; set; } public List Phases { get; set; } = []; public List TransferredPhaseIds { get; set; } = []; } public class TeachingPhaseTiming { public Guid PhaseId { get; set; } public double Minutes { get; set; } public bool ExplicitlyStarted { get; set; } }