diff --git a/LehrerApp.Desktop.Tests/PlanningTabViewModelTests.cs b/LehrerApp.Desktop.Tests/PlanningTabViewModelTests.cs index 89b9e40..6b478e7 100644 --- a/LehrerApp.Desktop.Tests/PlanningTabViewModelTests.cs +++ b/LehrerApp.Desktop.Tests/PlanningTabViewModelTests.cs @@ -294,4 +294,44 @@ public class PlanningTabViewModelTests Assert.Single(sessions.GetByGroup(groupId)); Assert.Equal("Für diese Stunde existiert bereits eine Sitzung.", notified); } + + [Fact] + public void CreateParticipationSession_AndereStundeAmSelbenTagBereitsVerknuepft_LegtKeineZweiteSitzungAn() + { + // Nutzer-Feedback: eine dritte Stunde am selben Tag (z.B. Vertretung) soll die bereits + // bestehende Sitzung des Tages weiterverwenden statt eine zweite anzulegen. + var groupId = Guid.NewGuid(); + var group = new LearningGroup { Id = groupId, Name = "Testgruppe" }; + var groups = new FakeGroups([group]); + var units = new FakeUnits(); + var lessons = new FakeLessons(); + var sessions = new FakeSessions([]); + var vm = new PlanningTabViewModel(units, lessons, groups, new FakeSubjects([]), + new FakeCompetencyDomains(), TestSupport.BuildAiSettingsService(), sessions); + vm.Initialize(groupId); + + var unit = new Unit { GroupId = groupId, Title = "Optik" }; + units.Add(unit); + var date = new DateOnly(2025, 9, 1); + var doubleLesson = new Lesson + { UnitId = unit.Id, GroupId = groupId, Date = date, Topic = "Brechung" }; + var thirdLesson = new Lesson + { UnitId = unit.Id, GroupId = groupId, Date = date, Topic = "Vertretung" }; + lessons.Add(doubleLesson); + lessons.Add(thirdLesson); + + vm.RefreshPlanning(unit.Id, doubleLesson.Id); + vm.SelectedLesson = vm.Lessons.Single(l => l.Id == doubleLesson.Id); + vm.CreateParticipationSessionCommand.Execute(null); + + string? notified = null; + vm.OnNotify = m => notified = m; + vm.RefreshPlanning(unit.Id, thirdLesson.Id); + vm.SelectedLesson = vm.Lessons.Single(l => l.Id == thirdLesson.Id); + vm.CreateParticipationSessionCommand.Execute(null); + + var created = Assert.Single(sessions.GetByGroup(groupId)); + Assert.Equal(doubleLesson.Id, created.LessonId); + Assert.Equal("Für diesen Tag existiert bereits eine Sitzung.", notified); + } } diff --git a/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs b/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs index 2f748be..475c2cd 100644 --- a/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs +++ b/LehrerApp.Desktop.Tests/SeatingPlanViewModelTests.cs @@ -256,6 +256,30 @@ public sealed class SeatingPlanViewModelTests Assert.Single(sessions.GetByGroup(groupId)); } + [Fact] + public void SelectOrCreateSessionForLesson_AndereStundeAmSelbenTagBereitsVerknuepft_LegtKeineZweiteSitzungAn() + { + // Nutzer-Feedback: eine dritte Stunde am selben Tag (z.B. durch Vertretung, eigene Lesson- + // Id) soll die bereits bestehende Sitzung der Doppelstunde weiterverwenden statt eine + // zweite, unabhängige Sitzung für denselben Tag anzulegen. + var groupId = Guid.NewGuid(); + var today = DateOnly.FromDateTime(DateTime.Today); + var doubleLesson = new Lesson { GroupId = groupId, Date = today, Topic = "Redox" }; + var thirdLesson = new Lesson { GroupId = groupId, Date = today, Topic = "Vertretung" }; + var existingSession = new ParticipationSession + { GroupId = groupId, Date = today, LessonId = doubleLesson.Id, Comment = "Redox" }; + var sessions = new FakeSessions([existingSession]); + var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 }; + var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([]), + new FakeMemberships([]), sessions, new FakeEntries(), new FakeAspects()); + vm.Initialize(groupId, isReadOnly: false); + + vm.SelectOrCreateSessionForLesson(thirdLesson); + + Assert.Equal(existingSession.Id, vm.SelectedSession?.Id); + Assert.Single(sessions.GetByGroup(groupId)); + } + [Fact] public void SelectOrCreateSessionForLesson_KeineSitzungVorhanden_LegtVerknuepfteAnUndWaehltSieAus() { diff --git a/LehrerApp.Desktop/ViewModels/Groups/PlanningViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/PlanningViewModels.cs index f4365d1..deeec62 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/PlanningViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/PlanningViewModels.cs @@ -364,16 +364,25 @@ public partial class PlanningTabViewModel : ObservableObject /// Übernimmt Datum + Thema der Stunde in eine neue Mitarbeitssitzung (3.3.1) — verknüpft über /// das bisher ungenutzte Lesson.LessonId-Feld auf ParticipationSession, damit ein zweiter Klick /// auf dieselbe Stunde keine doppelte Sitzung anlegt, sondern nur darauf hinweist. + /// + /// Prüft dabei zusätzlich auf JEDE bereits an diesem Tag bestehende Sitzung, nicht nur eine + /// exakt mit `lesson.Id` verknüpfte (Nutzer-Feedback, analog + /// ): kommt neben einer + /// Doppelstunde noch eine dritte Stunde desselben Tages hinzu (eigene `Lesson`, z.B. durch + /// Vertretung), soll das nicht zu einer zweiten Mitarbeitssitzung für den Tag führen. [RelayCommand(CanExecute = nameof(HasSelectedLesson))] private void CreateParticipationSession() { if (SelectedLesson is null) return; var lesson = SelectedLesson.Model; - var existing = _participationSessions.GetByGroup(lesson.GroupId) - .FirstOrDefault(s => s.LessonId == lesson.Id); + var sessionsForGroup = _participationSessions.GetByGroup(lesson.GroupId); + var existing = sessionsForGroup.FirstOrDefault(s => s.LessonId == lesson.Id) + ?? sessionsForGroup.FirstOrDefault(s => s.Date == lesson.Date); if (existing is not null) { - OnNotify?.Invoke("Für diese Stunde existiert bereits eine Sitzung."); + OnNotify?.Invoke(existing.LessonId == lesson.Id + ? "Für diese Stunde existiert bereits eine Sitzung." + : "Für diesen Tag existiert bereits eine Sitzung."); return; } diff --git a/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs index e89ccc3..5a79c9e 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/SeatingPlanViewModels.cs @@ -141,10 +141,18 @@ public partial class SeatingPlanTabViewModel : ObservableObject /// erlaubt: welche Stunde gemeint ist, steht durch die explizite Auswahl der Lehrkraft /// (Klick auf "Unterrichtsmodus starten" für genau diese Stunde) bereits unzweideutig fest - /// keine Geistersitzungs-Gefahr wie beim bloßen Öffnen eines Tabs. + /// + /// Fällt bewusst auf JEDE an diesem Tag bereits bestehende Sitzung zurück, nicht nur auf eine + /// exakt mit `lesson.Id` verknüpfte (Nutzer-Feedback): kommt neben einer Doppelstunde noch eine + /// dritte Stunde am selben Tag hinzu (z.B. Vertretung, eigene `Lesson` mit eigener Id), soll + /// keine zweite Mitarbeitssitzung für denselben Tag entstehen — die Lehrkraft passt stattdessen + /// die Einschätzung der bereits bestehenden Sitzung an. Das entspricht dem Verhalten von + /// , das schon immer pro Tag statt pro Stunde arbeitet. /// public void SelectOrCreateSessionForLesson(Lesson lesson) { - var existing = TodaySessions.FirstOrDefault(s => s.LessonId == lesson.Id); + var existing = TodaySessions.FirstOrDefault(s => s.LessonId == lesson.Id) + ?? TodaySessions.FirstOrDefault(s => s.Date == lesson.Date); if (existing is not null) { SelectedSession = existing; return; } if (!IsEditable) return; diff --git a/LehrerApp.Desktop/Views/Groups/WebUntisLessonAbsenceComparisonDialog.axaml b/LehrerApp.Desktop/Views/Groups/WebUntisLessonAbsenceComparisonDialog.axaml index 7339d58..43ac676 100644 --- a/LehrerApp.Desktop/Views/Groups/WebUntisLessonAbsenceComparisonDialog.axaml +++ b/LehrerApp.Desktop/Views/Groups/WebUntisLessonAbsenceComparisonDialog.axaml @@ -12,9 +12,9 @@ FontSize="12" Opacity="0.65" TextWrapping="Wrap"/> - + - +