feat: Abwesenheits-Hinweise, Fehlquote bei Zeugnisnoten, Gruppen-Dokumentation
- Schnellbewerten-Dialog: abwesende Schüler werden gedimmt und mit ihrem Anwesenheitsstatus statt der Aspektbeschriftung angezeigt, damit keine Mitarbeitsnote für nicht anwesende Schüler vergeben wird. - Zeugnisnoten-Dialog: zeigt je Schüler die Fehlquote im gewählten Zeitraum, ab 50 % hervorgehoben (informativ, keine automatische Notenänderung). - Gruppen-Tab "Dokumentation" (bisher Platzhalter) implementiert: listet alle Dokumentationseinträge der Gruppen-Schüler, mit Schüler-Filter und optionalem "Nur dieser Unterricht"-Schalter. Einträge aus anderen Lerngruppen werden standardmäßig mitangezeigt, aber gedimmt. Der Dokumentationsdialog bekommt dafür einen optionalen Schüler-Picker. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
using LehrerApp.Desktop.ViewModels.Students;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
/// Tests für den bisher als Platzhalter existierenden Gruppen-Tab "Dokumentation" (Nutzer-Feedback):
|
||||
/// listet Dokumentationseinträge aller Gruppen-Schüler, zeigt Einträge aus anderen Lerngruppen
|
||||
/// standardmäßig mit an (optisch abgesetzt statt versteckt), mit optionalem Filter darauf.
|
||||
public sealed class GroupDocumentationTabViewModelTests
|
||||
{
|
||||
private static GroupDocumentationTabViewModel BuildVm(
|
||||
List<Student> students, List<LearningGroup> groups, FakeDocumentation? docs = null)
|
||||
{
|
||||
var vm = new GroupDocumentationTabViewModel(docs ?? new FakeDocumentation(),
|
||||
new FakeStudents(students), new FakeGroups(groups));
|
||||
return vm;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Initialize_ZeigtEintraegeAllerGruppenschuelerSortiertNachDatumAbsteigend()
|
||||
{
|
||||
var group = new LearningGroup { Name = "9c" };
|
||||
var anna = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
||||
var ben = new Student { FirstName = "Ben", LastName = "Muster" };
|
||||
var docs = new FakeDocumentation();
|
||||
docs.Add(new Documentation { StudentId = anna.Id, GroupId = group.Id, Title = "Alt", Date = new DateOnly(2025, 9, 1) });
|
||||
docs.Add(new Documentation { StudentId = ben.Id, GroupId = group.Id, Title = "Neu", Date = new DateOnly(2025, 9, 10) });
|
||||
|
||||
var vm = BuildVm([anna, ben], [group], docs);
|
||||
vm.Initialize(group.Id);
|
||||
|
||||
Assert.Equal(2, vm.Entries.Count);
|
||||
Assert.Equal("Neu", vm.Entries[0].Model.Title);
|
||||
Assert.Equal("Alt", vm.Entries[1].Model.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Initialize_EintragAusAndererGruppe_WirdMitangezeigtAberAlsFremdMarkiert()
|
||||
{
|
||||
var group = new LearningGroup { Name = "9c" };
|
||||
var otherGroup = new LearningGroup { Name = "Mathematik 9b" };
|
||||
var anna = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
||||
var docs = new FakeDocumentation();
|
||||
docs.Add(new Documentation { StudentId = anna.Id, GroupId = otherGroup.Id, Title = "Aus anderem Kurs", Date = new DateOnly(2025, 9, 1) });
|
||||
|
||||
var vm = BuildVm([anna], [group, otherGroup], docs);
|
||||
vm.Initialize(group.Id);
|
||||
|
||||
var entry = Assert.Single(vm.Entries);
|
||||
Assert.False(entry.IsOwnGroup);
|
||||
Assert.Equal("Mathematik 9b", entry.OtherGroupLabel);
|
||||
Assert.True(entry.ContentOpacity < 1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Initialize_EintragOhneGruppe_GiltAlsEigen()
|
||||
{
|
||||
var group = new LearningGroup { Name = "9c" };
|
||||
var anna = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
||||
var docs = new FakeDocumentation();
|
||||
docs.Add(new Documentation { StudentId = anna.Id, GroupId = null, Title = "Allgemein", Date = new DateOnly(2025, 9, 1) });
|
||||
|
||||
var vm = BuildVm([anna], [group], docs);
|
||||
vm.Initialize(group.Id);
|
||||
|
||||
var entry = Assert.Single(vm.Entries);
|
||||
Assert.True(entry.IsOwnGroup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnlyThisGroup_Aktiviert_BlendetEintraegeAusAnderenGruppenAus()
|
||||
{
|
||||
var group = new LearningGroup { Name = "9c" };
|
||||
var otherGroup = new LearningGroup { Name = "Mathematik 9b" };
|
||||
var anna = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
||||
var docs = new FakeDocumentation();
|
||||
docs.Add(new Documentation { StudentId = anna.Id, GroupId = group.Id, Title = "Eigen", Date = new DateOnly(2025, 9, 1) });
|
||||
docs.Add(new Documentation { StudentId = anna.Id, GroupId = otherGroup.Id, Title = "Fremd", Date = new DateOnly(2025, 9, 2) });
|
||||
|
||||
var vm = BuildVm([anna], [group, otherGroup], docs);
|
||||
vm.Initialize(group.Id);
|
||||
vm.OnlyThisGroup = true;
|
||||
|
||||
var entry = Assert.Single(vm.Entries);
|
||||
Assert.Equal("Eigen", entry.Model.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectedStudentFilter_AufEinzelnenSchueler_FiltertListe()
|
||||
{
|
||||
var group = new LearningGroup { Name = "9c" };
|
||||
var anna = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
||||
var ben = new Student { FirstName = "Ben", LastName = "Muster" };
|
||||
var docs = new FakeDocumentation();
|
||||
docs.Add(new Documentation { StudentId = anna.Id, GroupId = group.Id, Title = "Anna-Eintrag", Date = new DateOnly(2025, 9, 1) });
|
||||
docs.Add(new Documentation { StudentId = ben.Id, GroupId = group.Id, Title = "Ben-Eintrag", Date = new DateOnly(2025, 9, 1) });
|
||||
|
||||
var vm = BuildVm([anna, ben], [group], docs);
|
||||
vm.Initialize(group.Id);
|
||||
vm.SelectedStudentFilter = vm.StudentFilterOptions.Single(s => s.Id == anna.Id);
|
||||
|
||||
var entry = Assert.Single(vm.Entries);
|
||||
Assert.Equal("Anna-Eintrag", entry.Model.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddDocumentation_SpeichertErgebnisUndLaedtNeu()
|
||||
{
|
||||
var group = new LearningGroup { Name = "9c" };
|
||||
var anna = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
||||
var docs = new FakeDocumentation();
|
||||
var vm = BuildVm([anna], [group], docs);
|
||||
vm.Initialize(group.Id);
|
||||
|
||||
vm.OnEditDocumentation = (groupId, options, editing) =>
|
||||
{
|
||||
Assert.Equal(group.Id, groupId);
|
||||
Assert.Contains(options, o => o.Id == anna.Id);
|
||||
Assert.Null(editing);
|
||||
return Task.FromResult<Documentation?>(new Documentation
|
||||
{ StudentId = anna.Id, GroupId = groupId, Title = "Neu", Date = new DateOnly(2025, 9, 1) });
|
||||
};
|
||||
|
||||
await vm.AddDocumentationCommand.ExecuteAsync(null);
|
||||
|
||||
var entry = Assert.Single(vm.Entries);
|
||||
Assert.Equal("Neu", entry.Model.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteDocumentation_NachBestaetigung_EntferntEintragAusListe()
|
||||
{
|
||||
var group = new LearningGroup { Name = "9c" };
|
||||
var anna = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
||||
var docs = new FakeDocumentation();
|
||||
docs.Add(new Documentation { StudentId = anna.Id, GroupId = group.Id, Title = "Weg", Date = new DateOnly(2025, 9, 1) });
|
||||
var vm = BuildVm([anna], [group], docs);
|
||||
vm.Initialize(group.Id);
|
||||
vm.OnConfirmDeleteDocumentation = _ => Task.FromResult(true);
|
||||
|
||||
await vm.DeleteDocumentationCommand.ExecuteAsync(vm.Entries[0]);
|
||||
|
||||
Assert.Empty(vm.Entries);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user