Klassenbuch-Tab zum Dokumentations-Hub ausgebaut
CI / build-and-test (push) Canceled after 0s

Umschalter zwischen WebUntis-Klassenbuch und eigener Dokumentation statt
Merge beider strukturell unterschiedlicher Datensätze, mit Zahlen-Badges
je Quelle (kritisch/Nacharbeit hervorgehoben) im Tab und an der
"Klassenbuch öffnen"-Aktion der Übersicht.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 17:05:13 +02:00
co-authored by Claude Sonnet 5
parent de6d4236a2
commit d297f9f109
7 changed files with 453 additions and 12 deletions
@@ -584,4 +584,68 @@ public sealed class ClassTeacherViewModelsTests
private static UntisStudentRosterCacheEntry Student(int? externKey, string displayName) =>
new() { ClassName = "6a", ExternKey = externKey, DisplayName = displayName };
// ── Klassenbuch-Tab als Dokumentations-Hub: eigene Dokumentation neben WebUntis ─────────────
[Fact]
public void FilterOwnDocumentation_ZeigtNurEintraegeZugeordneterSchuelerImZeitraum()
{
var ada = Guid.NewGuid();
var fremd = Guid.NewGuid();
var rosterMatches = new List<(Guid StudentId, string DisplayName)> { (ada, "Ada Müller") };
var docs = new List<Documentation>
{
new() { StudentId = ada, Date = new DateOnly(2026, 8, 20), Title = "Im Zeitraum" },
new() { StudentId = ada, Date = new DateOnly(2026, 7, 1), Title = "Vor dem Zeitraum" },
new() { StudentId = fremd, Date = new DateOnly(2026, 8, 20), Title = "Anderer Schüler" },
new() { StudentId = ada, Date = new DateOnly(2026, 8, 21), Title = "Gelöscht", IsDeleted = true },
};
var result = ClassTeacherDetailsViewModel.FilterOwnDocumentation(docs, rosterMatches,
new DateOnly(2026, 8, 1), new DateOnly(2026, 8, 31), "");
Assert.Equal(["Im Zeitraum"], result.Select(d => d.Title));
}
[Fact]
public void FilterOwnDocumentation_SortiertEntwuerfeVorNeuestenZuerst()
{
var id = Guid.NewGuid();
var rosterMatches = new List<(Guid StudentId, string DisplayName)> { (id, "Ada Müller") };
var docs = new List<Documentation>
{
new() { StudentId = id, Date = new DateOnly(2026, 8, 25), Title = "Neu, fertig" },
new() { StudentId = id, Date = new DateOnly(2026, 8, 10), Title = "Alt, Entwurf", IsDraft = true },
new() { StudentId = id, Date = new DateOnly(2026, 8, 20), Title = "Mittel, fertig" },
};
var result = ClassTeacherDetailsViewModel.FilterOwnDocumentation(docs, rosterMatches,
new DateOnly(2026, 8, 1), new DateOnly(2026, 8, 31), "");
Assert.Equal(["Alt, Entwurf", "Neu, fertig", "Mittel, fertig"], result.Select(d => d.Title));
}
[Fact]
public void FilterOwnDocumentation_SchuelerfilterErkenntVertauschteReihenfolge()
{
// Derselbe Namensabgleich wie bei den WebUntis-Klassenbuchzeilen (siehe
// RosterBuild_ErkenntNamenAuchInVertauschterReihenfolge) - der Filter kommt aus der
// Übersicht als "Nachname Vorname" oder "Vorname Nachname" je nach Bericht.
var ada = Guid.NewGuid();
var ben = Guid.NewGuid();
var rosterMatches = new List<(Guid StudentId, string DisplayName)>
{
(ada, "Ada Müller"), (ben, "Ben Schmidt"),
};
var docs = new List<Documentation>
{
new() { StudentId = ada, Date = new DateOnly(2026, 8, 20), Title = "Ada" },
new() { StudentId = ben, Date = new DateOnly(2026, 8, 20), Title = "Ben" },
};
var result = ClassTeacherDetailsViewModel.FilterOwnDocumentation(docs, rosterMatches,
new DateOnly(2026, 8, 1), new DateOnly(2026, 8, 31), "Müller Ada");
Assert.Equal(["Ada"], result.Select(d => d.Title));
}
}