using LehrerApp.Core.Models; namespace LehrerApp.Core.Interfaces; public interface IStudentRepository { Student? GetById(Guid id); List GetAll(bool includeInactive = false); List GetByGroup(Guid groupId); StudentReferenceSummary GetReferenceSummary(Guid studentId); void Save(Student student); void Delete(Guid id); } public interface IGroupRepository { LearningGroup? GetById(Guid id); List GetAll(bool includeInactive = false); List GetBySchoolYear(string schoolYear, bool includeInactive = false); void Save(LearningGroup group); void Delete(Guid id); } public interface ISeatingPlanRepository { SeatingPlan? GetById(Guid id); List GetByGroup(Guid groupId); void Save(SeatingPlan plan); void Delete(Guid id); /// Stellt einen über in den Papierkorb verschobenen Sitzplan /// wieder her (14.3). Tut nichts, falls der Papierkorb-Eintrag nicht (mehr) existiert. void Restore(Guid trashId); } public interface IGroupMembershipRepository { List GetByStudent(Guid studentId); List GetByGroup(Guid groupId); GroupMembership? GetByStudentAndGroup(Guid studentId, Guid groupId); void Save(GroupMembership membership); void Delete(Guid id); } public interface IExamRepository { Exam? GetById(Guid id); List GetAll(); List GetByGroup(Guid groupId); void Save(Exam exam); void Delete(Guid id); } public interface IExamResultRepository { List GetByExam(Guid examId); List GetByStudent(Guid studentId); ExamResult? GetByExamAndStudent(Guid examId, Guid studentId); void Save(ExamResult result); void SaveMany(List results); } public interface IGradingKeyTemplateRepository { List GetAll(); List GetByGradingSystem(GradingSystem system); GradingKeyTemplate? GetById(Guid id); void Save(GradingKeyTemplate template); void Delete(Guid id); /// Siehe ISeatingPlanRepository.Restore (14.3). void Restore(Guid trashId); } public interface IGradeRepository { List GetByStudentAndGroup(Guid studentId, Guid groupId); List GetByGroup(Guid groupId); void Save(Grade grade); void Delete(Guid id); /// Siehe ISeatingPlanRepository.Restore (14.3). void Restore(Guid trashId); } public interface IGradingSchemeRepository { GradingScheme? GetByGroup(Guid groupId); GradingScheme? GetDefaultForType(GroupType type); void Save(GradingScheme scheme); void Delete(Guid id); } public interface IReportGradeRepository { List GetByGroup(Guid groupId); ReportGrade? GetByStudentGroupPeriod(Guid studentId, Guid groupId, string period); void Save(ReportGrade grade); void Delete(Guid id); } public interface IUnitRepository { Unit? GetById(Guid id); List GetByGroup(Guid groupId); void Save(Unit unit); void Delete(Guid id); } public interface ILessonRepository { Lesson? GetById(Guid id); List GetByUnit(Guid unitId); List GetByGroupAndDate(Guid groupId, DateOnly date); List GetByGroupAndRange(Guid groupId, DateOnly from, DateOnly to); void Save(Lesson lesson); void Delete(Guid id); } public interface ITimetableSlotRepository { List GetAll(); List GetByGroup(Guid groupId); void Save(TimetableSlot slot); void Delete(Guid id); } public interface ISchoolHolidayRepository { List GetAll(); void Save(SchoolHoliday holiday); void Delete(Guid id); } public interface ISupervisionDutyRepository { List GetAll(); void Save(SupervisionDuty duty); void Delete(Guid id); } public interface ISubstitutionEntryRepository { List GetAll(); List GetByDate(DateOnly date); /// Für den WebUntis-Abgleich (idempotentes Update statt Duplikat je iCal-UID). SubstitutionEntry? GetByExternalId(string externalId); void Save(SubstitutionEntry entry); void Delete(Guid id); } /// Zuletzt bekannter Zustand aller WebUntis-iCal-Termine, für den Abgleich bei jedem Abruf. public interface IUntisSnapshotRepository { List GetAll(); void Save(UntisSnapshotEntry entry); void Delete(Guid id); } /// Lokaler Cache der Fehlzeiten-Berichtszeilen fürs Klassenlehrer-Feature (siehe TODO.md) — /// bewusst nicht synchronisiert (siehe Implementierung), jedes Gerät ruft WebUntis selbst ab. public interface IUntisAbsenceCacheRepository { List GetByClassAndRange(string className, int startDate, int endDate); /// Löscht vorhandene Zeilen im Bereich und fügt die übergebenen neu ein — fürs "heiße" Fenster, /// dessen Inhalt sich seit dem letzten Abruf geändert haben kann. void ReplaceRange(string className, int startDate, int endDate, IEnumerable entries); /// Fügt nur ein, ohne zu löschen — fürs Erweitern der als endgültig angenommenen "kalten" Historie. void InsertRange(IEnumerable entries); } /// Lokaler Cache der Klassenbuch-Berichtszeilen anderer Lehrkräfte fürs Klassenlehrer-Feature — /// gleiches Muster wie . public interface IUntisClassRegisterCacheRepository { List GetByClassAndRange(string className, int startDate, int endDate); void ReplaceRange(string className, int startDate, int endDate, IEnumerable entries); void InsertRange(IEnumerable entries); } /// Lokaler Cache der aktuellen Klassenliste (Roster) fürs Klassenlehrer-Feature — anders als /// Fehlzeiten/Klassenbuch keine Historie, deshalb kein ReplaceRange/InsertRange, sondern immer der /// komplette Ersatz des zuletzt bekannten Standes einer Klasse. public interface IUntisStudentRosterCacheRepository { List GetByClass(string className); void ReplaceAll(string className, IEnumerable entries); } /// Merkt sich je Klasse+Berichtsart, wann das heiße Fenster zuletzt aufgefrischt wurde und wie weit /// die kalte Historie bereits abgedeckt ist (siehe UntisReportCacheService). public interface IUntisCacheFetchStateRepository { UntisCacheFetchState? Get(string className, UntisCacheKind kind); void Save(UntisCacheFetchState state); } /// Zuletzt-Lauf-Status der Untis-Hub-Jobs (siehe TODO.md) - je (Kind, GroupId), GroupId null bei /// den dashboard-weiten Jobs. public interface IUntisHubJobStateRepository { UntisHubJobState? Get(UntisHubJobKind kind, Guid? groupId); List GetAll(); void Save(UntisHubJobState state); } /// Vom Nutzer bestätigte Zuordnungen WebUntis-Wochenmuster → LearningGroup. public interface IUntisSlotMappingRepository { List GetAll(); void Save(UntisSlotMapping mapping); void Delete(Guid id); } /// Lokal importierter, rein informativer Schuljahresplan. Bewusst getrennt von WebUntis- /// Stundenplanabweichungen und nicht über den App-Sync repliziert; jedes Gerät bezieht denselben /// externen Feed selbst. public interface IAnnualPlanEventRepository { List GetAll(); List GetByRange(DateOnly from, DateOnly to); AnnualPlanEvent? GetByExternalId(string externalId); void Save(AnnualPlanEvent entry); void Delete(Guid id); } public interface IDocumentationRepository { List GetByStudent(Guid studentId); List GetByStudentAndType(Guid studentId, DocumentationType type); /// Alle nicht gelöschten Einträge, über alle Schüler hinweg (z.B. für Dashboard-Auswertungen). List GetAll(); void Save(Documentation doc); /// Markiert den Eintrag als gelöscht, statt ihn hart zu entfernen (5.1.4). void Delete(Guid id); /// Entfernt den Eintrag endgültig — nur für die Löschfristen-Bereinigung (5.4.2). void HardDelete(Guid id); } public interface IVorgangRepository { List GetAll(); List GetByStudent(Guid studentId); Vorgang? GetById(Guid id); void Save(Vorgang vorgang); /// Markiert den Vorgang als gelöscht, statt ihn hart zu entfernen (gleiches Muster wie Documentation). void Delete(Guid id); } public interface IWorkTaskRepository { List GetByStatus(WorkTaskStatus status); List GetAll(); /// Für das "Anstehende Aufgaben"-Widget im Kurs-Dashboard (9.2/7.2). List GetByGroup(Guid groupId); void Save(WorkTask task); void Delete(Guid id); /// Siehe ISeatingPlanRepository.Restore (14.3). void Restore(Guid trashId); } public interface ITimeEntryRepository { List GetByDate(DateOnly date); List GetByDateRange(DateOnly from, DateOnly to); List GetByTask(Guid taskId); void Save(TimeEntry entry); void Delete(Guid id); /// Siehe ISeatingPlanRepository.Restore (14.3). void Restore(Guid trashId); } public interface IParticipationSessionRepository { List GetByGroup(Guid groupId); ParticipationSession? GetById(Guid id); // Für Aggregationen über alle Gruppen (z.B. Dashboard-Fehlzeiten-Warnung), die sonst pro // Eintrag einzeln GetById aufrufen müssten — ein Bulk-Laden vermeidet dieses N+1-Muster. List GetAll(); void Save(ParticipationSession session); void Delete(Guid id); } public interface IParticipationRepository { List GetBySession(Guid sessionId); List GetByStudent(Guid studentId); ParticipationEntry? GetBySessionAndStudent(Guid sessionId, Guid studentId); void Save(ParticipationEntry entry); void SaveMany(List entries); void DeleteBySession(Guid sessionId); } public interface IParticipationAspectRepository { List GetDefaults(); List GetByGroup(Guid groupId); // Wie GetByGroup, aber inkl. deaktivierter Aspekte — für die Verwaltungsansicht (3.1), // damit ein deaktivierter Aspekt dort sichtbar bleibt und wieder aktiviert werden kann. List GetAllByGroup(Guid groupId); void Save(ParticipationAspect aspect); void Delete(Guid id); } public interface IParticipationSectionRepository { List GetByGroup(Guid groupId); void Save(ParticipationSection section); void Delete(Guid id); } public interface ISubjectRepository { List GetAll(); Subject? GetById(Guid id); Subject? GetByName(string name); void Save(Subject subject); void Delete(Guid id); } public interface ICompetencyDomainRepository { List GetBySubjectAndGrade(Guid subjectId, int gradeLevel); CompetencyDomain? GetById(Guid id); void Save(CompetencyDomain domain); void Delete(Guid id); void DeleteBySubjectAndGrade(Guid subjectId, int gradeLevel); void ReplaceForSubjectAndGrade(Guid subjectId, int gradeLevel, List domains); } public interface IShorthandCodeRepository { List GetAll(); void Save(ShorthandCode code); void Delete(Guid id); } public interface IAlternativeLessonPathRepository { List GetAll(); AlternativeLessonPath? GetById(Guid id); void Save(AlternativeLessonPath path); void Delete(Guid id); } /// Papierkorb (14.3) — reine Übersicht/Aufräumen; das eigentliche Wiederherstellen läuft /// über die jeweilige Fach-Repository (z.B. IGradeRepository.Restore), da nur die kennt, wie ein /// Schnappschuss ihres Modells korrekt gespeichert wird (Validierung, OnChange-Ereignis). public interface ITrashRepository { List GetAll(); void PurgeOlderThan(DateTime cutoffUtc); }