Klassenlehrer-Übersicht scheiterte komplett mit "Ungültige Zahl in Spalte externKey", sobald ein Schüler der Klasse keinen gepflegten externen Schlüssel hat (in echten Schuldaten vorkommend). externKey ist jetzt optional statt Pflichtfeld (UntisStudent/UntisStudentDto.ExternKey -> int?); betraf denselben Bericht wie der bestehende WebUntis-Klassenimport, der das aber schon immer beim Weiterimport toleriert hatte. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
220 lines
6.0 KiB
C#
220 lines
6.0 KiB
C#
using System.Text.Json;
|
|
|
|
namespace LehrerApp.WebUntis;
|
|
|
|
public sealed class WebUntisOptions
|
|
{
|
|
public string School { get; set; } = "";
|
|
public string Host { get; set; } = "";
|
|
public string Username { get; set; } = "";
|
|
public string Password { get; set; } = "";
|
|
public string Client { get; set; } = "LehrerApp";
|
|
public int SessionIdleTimeoutMinutes { get; set; } = 10;
|
|
}
|
|
|
|
public sealed record UntisSchoolYear(int UntisId, string Name, int StartDate, int EndDate);
|
|
|
|
public sealed record UntisClass(
|
|
int UntisId,
|
|
string Name,
|
|
string? LongName,
|
|
string? ForeColor,
|
|
string? BackColor,
|
|
int? DepartmentUntisId,
|
|
int? Teacher1UntisId,
|
|
int? Teacher2UntisId);
|
|
|
|
public sealed record UntisTeacher(
|
|
int UntisId,
|
|
string Name,
|
|
string? ForeName,
|
|
string? LongName,
|
|
string? Title,
|
|
bool Active,
|
|
IReadOnlyList<int> DepartmentUntisIds);
|
|
|
|
public sealed record UntisStudentAddress(
|
|
string? Email,
|
|
string? Mobile,
|
|
string? Phone,
|
|
string? City,
|
|
string? PostCode,
|
|
string? Street);
|
|
|
|
// ExternKey optional: reale Schuldaten enthalten Schüler*innen (z.B. frisch angelegt/übernommen)
|
|
// ohne gepflegten externen Schlüssel - ein fehlender Wert bei einer/einem soll nicht den Abruf der
|
|
// gesamten Klassenliste zum Absturz bringen (siehe WebUntisStudentReportParser).
|
|
public sealed record UntisStudent(
|
|
int UntisId,
|
|
int? ExternKey,
|
|
string ClassName,
|
|
string? Name,
|
|
string? LongName,
|
|
string? ForeName,
|
|
string DisplayName,
|
|
string? Gender,
|
|
int? BirthDate,
|
|
string? BirthDateRaw,
|
|
int? EntryDate,
|
|
string? EntryDateRaw,
|
|
int? ExitDate,
|
|
string? ExitDateRaw,
|
|
string? Text,
|
|
string? MedicalReportDuty,
|
|
string? Schulpflicht,
|
|
string? Majority,
|
|
UntisStudentAddress Address,
|
|
string? AttributeIL);
|
|
|
|
public sealed record UntisStudentReport(
|
|
int Count,
|
|
string? ClassNameFilter,
|
|
IReadOnlyList<UntisStudent> Students);
|
|
|
|
public sealed record UntisTimeUnit(string Name, int StartTime, int EndTime);
|
|
|
|
public sealed record UntisTimeGridDay(
|
|
int Day,
|
|
IReadOnlyList<UntisTimeUnit> TimeUnits,
|
|
JsonElement Raw);
|
|
|
|
public sealed record UntisHoliday(
|
|
int UntisId,
|
|
string Name,
|
|
string? LongName,
|
|
int StartDate,
|
|
int EndDate);
|
|
|
|
public sealed record UntisEntity(
|
|
int Id,
|
|
string Name,
|
|
int? OriginalId,
|
|
string? OriginalName,
|
|
string? ExternalKey);
|
|
|
|
public sealed record UntisReschedule(int Date, int StartTime, int EndTime);
|
|
|
|
public sealed record UntisSubstitution(
|
|
string Type,
|
|
int? LessonId,
|
|
string? LessonType,
|
|
int Date,
|
|
int StartTime,
|
|
int EndTime,
|
|
string? Text,
|
|
IReadOnlyList<UntisEntity> Classes,
|
|
IReadOnlyList<UntisEntity> Teachers,
|
|
IReadOnlyList<UntisEntity> Subjects,
|
|
IReadOnlyList<UntisEntity> Rooms,
|
|
UntisReschedule? Reschedule,
|
|
JsonElement Raw);
|
|
|
|
public enum UntisTimetableElementType
|
|
{
|
|
Class = 1,
|
|
Teacher = 2,
|
|
Subject = 3,
|
|
Room = 4,
|
|
Student = 5,
|
|
}
|
|
|
|
public sealed record UntisTimetablePeriod(
|
|
int Id,
|
|
int Date,
|
|
int StartTime,
|
|
int EndTime,
|
|
string? Code,
|
|
string? ActivityType,
|
|
string? Info,
|
|
string? LessonText,
|
|
string? SubstitutionText,
|
|
string? StudentGroup,
|
|
IReadOnlyList<UntisEntity> Classes,
|
|
IReadOnlyList<UntisEntity> Teachers,
|
|
IReadOnlyList<UntisEntity> Subjects,
|
|
IReadOnlyList<UntisEntity> Rooms,
|
|
JsonElement Raw);
|
|
|
|
public sealed record UntisLessonAbsence(
|
|
string StudentName,
|
|
int Date,
|
|
int AbsentPeriods,
|
|
int UnexcusedAbsentPeriods,
|
|
int AbsentMinutes,
|
|
int UnexcusedAbsentMinutes,
|
|
int? StartTime,
|
|
int? EndTime,
|
|
string? Reason,
|
|
int? ExternKey,
|
|
bool ExternKeyInParentheses,
|
|
string? HandledOn,
|
|
bool Counts);
|
|
|
|
// Undokumentierter Bericht "AbsencePerStudent" (Fehlzeiten der ganzen Klasse über alle Fächer,
|
|
// nicht nur den eigenen Unterricht wie AbsencePerLesson) - eigenes Spaltenschema, eine Zeile pro
|
|
// Fehlstunde. Anders als bei AbsencePerLesson liefert "Status" hier einen Klartext-Wert direkt
|
|
// (im Sample nur "nicht entsch." beobachtet, andere Werte nicht bestätigt - Rohwert durchreichen).
|
|
// "Fehltage" ist der auf eine ganze Zahl abgerundete Fehlzeit-Tagesanteil (Nutzer-Angabe, nicht
|
|
// durch WebUntis-Dokumentation bestätigt): bleibt 0, bis auch die letzte Unterrichtsstunde des
|
|
// Tages als versäumt gilt - erst dann springt er auf 1. Pro Schüler*in/Tag trägt deshalb genau die
|
|
// Zeile der letzten Stunde des Tages den Wert 1, alle vorherigen Stunden dieses Tages bleiben 0.
|
|
public sealed record UntisClassAbsenceEntry(
|
|
string StudentName,
|
|
int? ExternKey,
|
|
string ClassName,
|
|
int Date,
|
|
int AbsentPeriods,
|
|
int AbsentMinutes,
|
|
string? TeacherUsernames,
|
|
string? Subject,
|
|
string? AbsenceReason,
|
|
string? Note,
|
|
int? EntryId,
|
|
string? HandledOn,
|
|
bool Counts,
|
|
string? ExcuseNote,
|
|
int? PeriodNumber,
|
|
string? Status,
|
|
bool CountsAsFullDay);
|
|
|
|
// "-alle-"-Bericht ohne externe Schülerkennung - anders als bei AbsencePerLesson bleibt für den
|
|
// Abgleich mit lokalen Schülern nur der Name (siehe Namens-Fallback im Desktop-Abgleich).
|
|
public sealed record UntisClassRegisterEventReportEntry(
|
|
string ClassName,
|
|
int Date,
|
|
string? Subject,
|
|
string StudentName,
|
|
string? TeacherUsername,
|
|
string? CategoryName,
|
|
string? CategoryGroup,
|
|
string? Text);
|
|
|
|
public sealed record UntisClassRegisterEntry(
|
|
int? StudentKey,
|
|
string? Surname,
|
|
string? ForeName,
|
|
string DisplayName,
|
|
int Date,
|
|
string? Subject,
|
|
int? CategoryId,
|
|
string? Reason,
|
|
string? Text,
|
|
JsonElement Raw);
|
|
|
|
public sealed record UntisClassRegisterCategory(
|
|
int Id,
|
|
string Name,
|
|
string? LongName,
|
|
int? GroupId,
|
|
JsonElement Raw);
|
|
|
|
public sealed record UntisClassRegisterCategoryGroup(
|
|
int Id,
|
|
string Name,
|
|
JsonElement Raw);
|
|
|
|
public sealed class WebUntisException(string message, Exception? innerException = null)
|
|
: Exception(message, innerException);
|
|
|
|
public sealed class WebUntisConfigurationException(string message) : Exception(message);
|