feat: Anhänge je Stunde, Klausur-Sitzplan mischen, Gefährdungsbeurteilungs-Assistent
Lesson bekommt dieselbe Anhang-Infrastruktur wie Documentation (Material, Arbeitsblätter, Experimentunterlagen), samt Fix einer Sync-Lücke, die Anhang- Dateibytes bisher nur für Documentation statt generisch übertragen hat (IHasAttachments). Sitzplan-Tab bekommt einen "Plätze mischen"-Button für Klausursitzpläne. Neu: mehrschrittiger Gefährdungsbeurteilungs-Assistent mit optionalem KI-Entwurf (ai-backend/gbu.php) und PDF-Export, Format bewusst als JSON-Anhang statt eigener Datenbank-Entität. Details und Architekturentscheidungen in TODO.md (4.2, 7.1.5, 10.1.8). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using LehrerApp.Core.Interfaces;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Core.Services;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
@@ -18,7 +19,7 @@ public sealed class LessonDialogViewModelTests
|
||||
private static LessonDialogViewModel BuildVm(Guid unitId, Guid groupId, Lesson? editing = null,
|
||||
FakeTimetableSlots? slots = null, PeriodScheduleService? periodSchedule = null) =>
|
||||
new(new FakeLessons(), new FakeShorthandCodes([]), new FakeAlternativeLessonPaths([]),
|
||||
slots ?? new FakeTimetableSlots(), periodSchedule ?? NewPeriodSchedule(),
|
||||
slots ?? new FakeTimetableSlots(), periodSchedule ?? NewPeriodSchedule(), new FakeAttachmentStorage(),
|
||||
unitId, groupId, "10c", "Chemie", [], [], editing);
|
||||
|
||||
/// Nutzer-Feedback: bei einer Klasse, die in mehreren Fächern unterrichtet wird (mehrere
|
||||
@@ -92,7 +93,7 @@ public sealed class LessonDialogViewModelTests
|
||||
{
|
||||
var codes = new FakeShorthandCodes([new ShorthandCode { Code = "Tb" }, new ShorthandCode { Code = "SH" }]);
|
||||
var vm = new LessonDialogViewModel(new FakeLessons(), codes, new FakeAlternativeLessonPaths([]),
|
||||
new FakeTimetableSlots(), NewPeriodSchedule(),
|
||||
new FakeTimetableSlots(), NewPeriodSchedule(), new FakeAttachmentStorage(),
|
||||
Guid.NewGuid(), Guid.NewGuid(), "10c", "Chemie", [], ["Plenum", "LDE", "Tb"], null); // "Tb" doppelt (Katalog + Historie), soll nur einmal erscheinen
|
||||
|
||||
Assert.Equal(["LDE", "Plenum", "SH", "Tb"], vm.ShorthandSuggestions);
|
||||
@@ -155,7 +156,7 @@ public sealed class LessonDialogViewModelTests
|
||||
var groupId = Guid.NewGuid();
|
||||
var lessons = new FakeLessons();
|
||||
var vm = new LessonDialogViewModel(lessons, new FakeShorthandCodes([]), new FakeAlternativeLessonPaths([]),
|
||||
new FakeTimetableSlots(), NewPeriodSchedule(), unitId, groupId, "10c", "Chemie", [], [], null)
|
||||
new FakeTimetableSlots(), NewPeriodSchedule(), new FakeAttachmentStorage(), unitId, groupId, "10c", "Chemie", [], [], null)
|
||||
{
|
||||
Topic = "Brechung", DateText = "01.09.2025", StartTimeText = "11:45",
|
||||
};
|
||||
@@ -179,6 +180,58 @@ public sealed class LessonDialogViewModelTests
|
||||
Assert.Single(lessons.GetByUnit(unitId));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddAttachment_LaedtHochUndSaveUebernimmtIhnInDasErgebnis()
|
||||
{
|
||||
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid());
|
||||
vm.Topic = "Thema"; vm.DateText = "01.09.2025";
|
||||
|
||||
vm.AddAttachment("gbu-natrium.pdf", new MemoryStream([1, 2, 3]));
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.NotNull(vm.Result);
|
||||
var attachment = Assert.Single(vm.Result!.Attachments);
|
||||
Assert.Equal("gbu-natrium.pdf", attachment.FileName);
|
||||
Assert.Equal(3, attachment.SizeBytes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddAttachment_ZuGrosseDateiWirdAbgelehnt()
|
||||
{
|
||||
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid());
|
||||
|
||||
vm.AddAttachment("riesig.pdf", new MemoryStream(new byte[IAttachmentStorage.MaxSizeBytes + 1]));
|
||||
|
||||
Assert.Empty(vm.Attachments);
|
||||
Assert.NotEqual("", vm.AttachmentError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveAttachmentCommand_EntferntDenAnhangAusDerListe()
|
||||
{
|
||||
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid());
|
||||
vm.AddAttachment("gbu-natrium.pdf", new MemoryStream([1, 2, 3]));
|
||||
var item = vm.Attachments[0];
|
||||
|
||||
vm.RemoveAttachmentCommand.Execute(item);
|
||||
|
||||
Assert.Empty(vm.Attachments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BearbeiteteStunde_LaedtVorhandeneAnhaengeVor()
|
||||
{
|
||||
var editing = new Lesson
|
||||
{
|
||||
Attachments = [new DocumentAttachment { StorageId = "abc", FileName = "gbu.pdf", SizeBytes = 42 }],
|
||||
};
|
||||
|
||||
var vm = BuildVm(Guid.NewGuid(), Guid.NewGuid(), editing);
|
||||
|
||||
var attachment = Assert.Single(vm.Attachments);
|
||||
Assert.Equal("gbu.pdf", attachment.FileName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasHomeworkText_OhneHausaufgabe_IstFalse()
|
||||
{
|
||||
@@ -305,7 +358,7 @@ public sealed class LessonDialogViewModelTests
|
||||
};
|
||||
|
||||
var vm = new LessonDialogViewModel(new FakeLessons(), new FakeShorthandCodes([]), alternativePaths,
|
||||
new FakeTimetableSlots(), NewPeriodSchedule(), Guid.NewGuid(), Guid.NewGuid(), "10c", "Chemie", [], [], editing);
|
||||
new FakeTimetableSlots(), NewPeriodSchedule(), new FakeAttachmentStorage(), Guid.NewGuid(), Guid.NewGuid(), "10c", "Chemie", [], [], editing);
|
||||
|
||||
Assert.True(vm.Phases[0].HasAlternativePath);
|
||||
Assert.Equal("Kurzversion", vm.Phases[0].AlternativePathName);
|
||||
@@ -466,7 +519,7 @@ public sealed class LessonDialogViewModelTests
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = DayOfWeek.Tuesday, PeriodNumber = 3 });
|
||||
|
||||
var vm = new LessonDialogViewModel(lessons, new FakeShorthandCodes([]), new FakeAlternativeLessonPaths([]),
|
||||
slots, NewPeriodSchedule(), unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
slots, NewPeriodSchedule(), new FakeAttachmentStorage(), unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
|
||||
// Nächster Dienstag nach dem 06.01.2099 (einem Dienstag) ist der 13.01.2099.
|
||||
Assert.Equal("13.01.2099", vm.DateText);
|
||||
@@ -485,7 +538,7 @@ public sealed class LessonDialogViewModelTests
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = weekday, PeriodNumber = 3 });
|
||||
|
||||
var vm = new LessonDialogViewModel(lessons, new FakeShorthandCodes([]), new FakeAlternativeLessonPaths([]),
|
||||
slots, NewPeriodSchedule(), unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
slots, NewPeriodSchedule(), new FakeAttachmentStorage(), unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
|
||||
var suggested = DateOnly.ParseExact(vm.DateText, "dd.MM.yyyy");
|
||||
Assert.True(suggested >= DateOnly.FromDateTime(DateTime.Today));
|
||||
@@ -506,7 +559,7 @@ public sealed class LessonDialogViewModelTests
|
||||
slots.Add(new TimetableSlot { GroupId = groupId, Weekday = DayOfWeek.Tuesday, PeriodNumber = 3 });
|
||||
|
||||
var vm = new LessonDialogViewModel(lessons, new FakeShorthandCodes([]), new FakeAlternativeLessonPaths([]),
|
||||
slots, NewPeriodSchedule(), unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
slots, NewPeriodSchedule(), new FakeAttachmentStorage(), unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
|
||||
Assert.Equal(3, vm.LessonNumber); // frühere Periode, nicht 4
|
||||
}
|
||||
@@ -523,7 +576,7 @@ public sealed class LessonDialogViewModelTests
|
||||
periodSchedule.SetPeriods([new PeriodTimeEntry { PeriodNumber = 2, Start = new TimeOnly(8, 50), End = new TimeOnly(9, 35) }]);
|
||||
|
||||
var vm = new LessonDialogViewModel(new FakeLessons(), new FakeShorthandCodes([]), new FakeAlternativeLessonPaths([]),
|
||||
slots, periodSchedule, unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
slots, periodSchedule, new FakeAttachmentStorage(), unitId, groupId, "10c", "Chemie", [], [], null);
|
||||
|
||||
Assert.Equal(2, vm.LessonNumber);
|
||||
Assert.Equal("08:50", vm.StartTimeText);
|
||||
|
||||
Reference in New Issue
Block a user