Unterrichtsplanung: Serienerzeugung, Stundenraster, Aufsichten & Vertretung (Kapitel 4.2/4.3 Nachtrag)
Stunden serienweise aus dem Stundenplan erzeugen (4.2.5); Stundenraster (Uhrzeiten je Stunde) in den Einstellungen mit Zeitbedarf-Rückmeldung im Verlaufsplan-Editor; wiederkehrende Pausenaufsicht; neuer "Vertretung eintragen"-Dialog für einmalige Vertretungsaufsicht, Vertretungsstunde, Sondereinsätze (Ausflüge, Berufsmessen) und schlichten Stundenausfall. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Core.Services;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
/// Tests für die Serienerzeugung von Stunden aus dem Stundenplan (4.2.5).
|
||||
public sealed class GenerateLessonSeriesDialogViewModelTests
|
||||
{
|
||||
private static GenerateLessonSeriesDialogViewModel BuildVm(FakeTimetableSlots slots, FakeLessons lessons,
|
||||
FakeSchoolHolidays holidays, Guid unitId, Guid groupId, DateOnly? from = null, DateOnly? to = null)
|
||||
{
|
||||
// Bewusst kein "using": SchoolCalendarSettingsService liest den Pfad nur bei Bedarf.
|
||||
var tempPath = System.IO.Path.Combine(
|
||||
System.IO.Path.GetTempPath(), $"lehrerapp-lessonseries-tests-{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
var vm = new GenerateLessonSeriesDialogViewModel(slots, lessons, holidays,
|
||||
new PublicHolidayService(), new SchoolCalendarSettingsService(tempPath), unitId, groupId, null, null);
|
||||
if (from is not null) vm.FromDateText = from.Value.ToString("dd.MM.yyyy");
|
||||
if (to is not null) vm.ToDateText = to.Value.ToString("dd.MM.yyyy");
|
||||
return vm;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_ErzeugtStundeProVorkommenDesWochentagsImZeitraum()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var unitId = Guid.NewGuid();
|
||||
var from = new DateOnly(2025, 9, 1);
|
||||
var to = from.AddDays(13); // deckt zwei Vorkommen des Wochentags von "from" ab (Tag 0 und 7)
|
||||
var slots = new FakeTimetableSlots();
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = from.DayOfWeek, PeriodNumber = 1 });
|
||||
var lessons = new FakeLessons();
|
||||
var vm = BuildVm(slots, lessons, new FakeSchoolHolidays(), unitId, groupId, from, to);
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.NotNull(vm.Result);
|
||||
Assert.Equal(2, vm.Result!.Created);
|
||||
Assert.Equal(0, vm.Result.SkippedHoliday);
|
||||
Assert.Equal(0, vm.Result.SkippedExisting);
|
||||
Assert.All(lessons.GetByGroupAndRange(groupId, from, to), l => Assert.Equal(unitId, l.UnitId));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_UeberspringtTerminInSchulferien()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var unitId = Guid.NewGuid();
|
||||
var from = new DateOnly(2025, 9, 1);
|
||||
var to = from.AddDays(13);
|
||||
var secondOccurrence = from.AddDays(7);
|
||||
var slots = new FakeTimetableSlots();
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = from.DayOfWeek, PeriodNumber = 1 });
|
||||
var holidays = new FakeSchoolHolidays();
|
||||
holidays.Add(new SchoolHoliday { Name = "Ferien", StartDate = secondOccurrence, EndDate = secondOccurrence.AddDays(3) });
|
||||
var vm = BuildVm(slots, new FakeLessons(), holidays, unitId, groupId, from, to);
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Equal(1, vm.Result!.Created);
|
||||
Assert.Equal(1, vm.Result.SkippedHoliday);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_UeberspringtBereitsVorhandeneStundeAmSelbenDatumUndPeriode()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var unitId = Guid.NewGuid();
|
||||
var from = new DateOnly(2025, 9, 1);
|
||||
var to = from.AddDays(13);
|
||||
var slots = new FakeTimetableSlots();
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = from.DayOfWeek, PeriodNumber = 1 });
|
||||
var lessons = new FakeLessons();
|
||||
lessons.Add(new Lesson { UnitId = Guid.NewGuid(), GroupId = groupId, Date = from, LessonNumber = 1, Topic = "Bestehend" });
|
||||
var vm = BuildVm(slots, lessons, new FakeSchoolHolidays(), unitId, groupId, from, to);
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Equal(1, vm.Result!.Created);
|
||||
Assert.Equal(1, vm.Result.SkippedExisting);
|
||||
Assert.Equal(2, lessons.GetByGroupAndRange(groupId, from, to).Count); // 1 alt + 1 neu
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_Doppelstunde_ErzeugtZweiStundenAmSelbenTagMitUnterschiedlicherStundennummer()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var unitId = Guid.NewGuid();
|
||||
var from = new DateOnly(2025, 9, 1);
|
||||
var slots = new FakeTimetableSlots();
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = from.DayOfWeek, PeriodNumber = 3 });
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = from.DayOfWeek, PeriodNumber = 4 });
|
||||
var lessons = new FakeLessons();
|
||||
var vm = BuildVm(slots, lessons, new FakeSchoolHolidays(), unitId, groupId, from, from);
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Equal(2, vm.Result!.Created);
|
||||
var created = lessons.GetByGroupAndRange(groupId, from, from).Select(l => l.LessonNumber).OrderBy(n => n).ToList();
|
||||
Assert.Equal([3, 4], created);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_OhneStundenplanEintrag_SetztFehlerUndErzeugtNichts()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var vm = BuildVm(new FakeTimetableSlots(), new FakeLessons(), new FakeSchoolHolidays(), Guid.NewGuid(), groupId,
|
||||
new DateOnly(2025, 9, 1), new DateOnly(2025, 9, 14));
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Null(vm.Result);
|
||||
Assert.NotEqual("", vm.DateError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_UngueltigesDatumsformat_SetztFehler()
|
||||
{
|
||||
var vm = BuildVm(new FakeTimetableSlots(), new FakeLessons(), new FakeSchoolHolidays(), Guid.NewGuid(), Guid.NewGuid());
|
||||
vm.FromDateText = "keinDatum";
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Null(vm.Result);
|
||||
Assert.NotEqual("", vm.DateError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_EndeVorBeginn_SetztFehler()
|
||||
{
|
||||
var vm = BuildVm(new FakeTimetableSlots(), new FakeLessons(), new FakeSchoolHolidays(), Guid.NewGuid(), Guid.NewGuid(),
|
||||
new DateOnly(2025, 9, 10), new DateOnly(2025, 9, 1));
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Null(vm.Result);
|
||||
Assert.NotEqual("", vm.DateError);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user