WIP (unstable): WebUntis-iCal-Abgleich für Vertretungen/Ausfälle
Erkennt Vertretungen, Ausfälle und Zusatzaufsichten aus dem persönlichen WebUntis-iCal-Feed und schreibt sie automatisch als SubstitutionEntry. Bekannter offener Bug: es tauchen weiterhin falsche Vertretungen für Stunden auf, die real unverändert sind — wird in einem Folge-Commit untersucht, deshalb vorerst auf diesem Branch statt main. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using LehrerApp.Core.Interfaces;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Core.Services;
|
||||
using LehrerApp.Desktop.Services;
|
||||
using LehrerApp.Desktop.ViewModels.Settings;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
@@ -62,6 +63,8 @@ public partial class TimetableViewModel : ObservableObject
|
||||
private readonly SchoolYearService _schoolYear;
|
||||
private readonly ISupervisionDutyRepository _supervisionDuties;
|
||||
private readonly ISubstitutionEntryRepository _substitutions;
|
||||
private readonly IUntisSlotMappingRepository _untisMappings;
|
||||
private readonly WebUntisSettingsService _untisSettings;
|
||||
|
||||
public ObservableCollection<TimetableCellItem> Cells { get; } = [];
|
||||
public ObservableCollection<WeekCellItem> WeekItems { get; } = [];
|
||||
@@ -86,6 +89,13 @@ public partial class TimetableViewModel : ObservableObject
|
||||
[ObservableProperty] private int _weekOffset;
|
||||
public bool IsCurrentWeek => WeekOffset == 0;
|
||||
|
||||
// ── WebUntis-Abweichung (Nutzer-Feedback: "oder der Stundenplan gar nicht mehr passt") ──────
|
||||
// Kein erneuter iCal-Abruf hier - vergleicht nur den lokal bereits bestätigten
|
||||
// Zuordnungsstand (UntisSlotMapping, siehe UntisMappingReviewDialog) gegen die aktuellen
|
||||
// TimetableSlots. Bleibt komplett verborgen, solange der Abgleich nicht aktiviert ist.
|
||||
[ObservableProperty] private bool _hasUntisMismatch;
|
||||
[ObservableProperty] private string _untisMismatchLabel = "";
|
||||
|
||||
public Func<TimetableCellItem, Task>? OnEditSlot { get; set; }
|
||||
public Action<Guid>? OnNavigateToGroup { get; set; }
|
||||
public Func<Task>? OnAddSubstitution { get; set; }
|
||||
@@ -97,12 +107,14 @@ public partial class TimetableViewModel : ObservableObject
|
||||
ISubjectRepository subjects, ILessonRepository lessons, IExamRepository exams,
|
||||
ISchoolHolidayRepository schoolHolidays, SchoolCalendarSettingsService calendarSettings,
|
||||
PublicHolidayService publicHolidays, SchoolYearService schoolYear,
|
||||
ISupervisionDutyRepository supervisionDuties, ISubstitutionEntryRepository substitutions)
|
||||
ISupervisionDutyRepository supervisionDuties, ISubstitutionEntryRepository substitutions,
|
||||
IUntisSlotMappingRepository untisMappings, WebUntisSettingsService untisSettings)
|
||||
{
|
||||
_slots = slots; _groups = groups; _subjects = subjects; _lessons = lessons; _exams = exams;
|
||||
_schoolHolidays = schoolHolidays; _calendarSettings = calendarSettings;
|
||||
_publicHolidays = publicHolidays; _schoolYear = schoolYear;
|
||||
_supervisionDuties = supervisionDuties; _substitutions = substitutions;
|
||||
_untisMappings = untisMappings; _untisSettings = untisSettings;
|
||||
Load();
|
||||
}
|
||||
|
||||
@@ -143,8 +155,33 @@ public partial class TimetableViewModel : ObservableObject
|
||||
BuildToday(today);
|
||||
BuildHoursWarnings();
|
||||
BuildUpcomingExams(today);
|
||||
LoadUntisMismatch();
|
||||
}
|
||||
|
||||
private void LoadUntisMismatch()
|
||||
{
|
||||
if (!_untisSettings.Enabled || !_untisSettings.IsConfigured) { HasUntisMismatch = false; return; }
|
||||
|
||||
// CoveredPeriods statt nur PeriodNumber: bei einer von WebUntis zu einem Termin
|
||||
// zusammengefassten Doppelstunde bestätigt eine einzige Zuordnung mehrere TimetableSlots
|
||||
// auf einmal (siehe UntisSlotMapping.CoveredPeriods-Dokumentation).
|
||||
var confirmedKeys = _untisMappings.GetAll()
|
||||
.Where(m => m.Confirmed && m.Kind == SubstitutionKind.Lesson && m.GroupId is not null)
|
||||
.SelectMany(m => (m.CoveredPeriods.Count > 0 ? m.CoveredPeriods : m.PeriodNumber is { } p ? [p] : [])
|
||||
.Select(period => (m.Weekday, period, GroupId: m.GroupId!.Value)))
|
||||
.ToHashSet();
|
||||
var mismatchCount = _slots.GetAll()
|
||||
.Count(s => !confirmedKeys.Contains((s.Weekday, s.PeriodNumber, s.GroupId)));
|
||||
|
||||
HasUntisMismatch = mismatchCount > 0;
|
||||
UntisMismatchLabel = mismatchCount == 1
|
||||
? "1 Stundenplan-Eintrag ohne bestätigte WebUntis-Zuordnung."
|
||||
: $"{mismatchCount} Stundenplan-Einträge ohne bestätigte WebUntis-Zuordnung.";
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ReviewUntisMismatch() => OnNavigateToSettings?.Invoke(SettingsTab.WebUntis);
|
||||
|
||||
// ── Anstehende Klausurtermine (4.4.3) ────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user