From 651c9cddf866617f76f80df49ac0f6effe1e1093 Mon Sep 17 00:00:00 2001 From: Sebastian Hedtrich Date: Thu, 22 Oct 2026 20:55:27 +0200 Subject: [PATCH] =?UTF-8?q?F=C3=B6rderarbeit=20als=20dritte=20Folgearbeits?= =?UTF-8?q?-Art=20erg=C3=A4nzen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neben Wiederholung und Nachschreibarbeit gibt es im Arbeitsdialog die Art Förderarbeit (Exam.IsSupportWork). Sie darf am Tag der ersten Arbeit liegen, übernimmt dessen Datum als Vorschlag und ersetzt wie eine Nachschreibarbeit nur fehlende Noten. Co-Authored-By: Claude Sonnet 5.5 --- LehrerApp.Core/Models/Exam.cs | 11 +++ .../Services/ExamCoverSheetService.cs | 8 +- LehrerApp.Core/Services/ExamScoringService.cs | 8 +- .../ExamDialogViewModelTests.cs | 77 +++++++++++++++++++ .../Services/GradeReportDrawingBuilder.cs | 5 +- .../Groups/ExamEvaluationViewModels.cs | 6 +- .../ViewModels/Groups/ExamViewModels.cs | 69 +++++++++++++---- .../ViewModels/Groups/GroupViewModels.cs | 1 + .../Groups/ReportGradeAssistantViewModels.cs | 5 +- .../Views/Groups/ExamDialog.axaml | 6 +- LehrerApp.Tests/ExamCoverSheetServiceTests.cs | 20 +++++ LehrerApp.Tests/ExamScoringServiceTests.cs | 13 ++++ TODO.md | 12 +++ docs/Datenmodell.md | 5 +- 14 files changed, 214 insertions(+), 32 deletions(-) diff --git a/LehrerApp.Core/Models/Exam.cs b/LehrerApp.Core/Models/Exam.cs index 69e436b..0a65a14 100644 --- a/LehrerApp.Core/Models/Exam.cs +++ b/LehrerApp.Core/Models/Exam.cs @@ -32,6 +32,10 @@ public class Exam /// erste Arbeit () versäumt haben. Anders als eine Wiederholung /// wird sie nur von diesen Schülern geschrieben und ersetzt deren fehlende Note. public bool IsMakeUp { get; set; } + /// Förderarbeit: inhaltlich eigene Arbeit, die einzelne Schüler statt der verknüpften + /// ersten Arbeit schreiben — typischerweise am selben Tag, daher darf sie am Datum der ersten + /// Arbeit liegen. Zählt wie eine Nachschreibarbeit (ersetzt nur eine fehlende Note). + public bool IsSupportWork { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } @@ -78,6 +82,13 @@ public enum RepeatGradeRule { Better, Repeat, Original } /// Reihenfolge ist persistiert (LiteDB speichert den Enum-Wert) — nur hinten anhängen. public enum ExamKind { Klausur, Test, KontrollierteHausaufgabe, Sonstiges } +public static class ExamFollowUpExtensions +{ + /// Nachschreib- und Förderarbeiten sind inhaltlich eigene Arbeiten nur für einzelne + /// Schüler: ihre Note ersetzt eine fehlende Note der ersten Arbeit, verdrängt sie aber nie. + public static bool ReplacesMissingGrade(this Exam exam) => exam.IsMakeUp || exam.IsSupportWork; +} + public static class ExamKindExtensions { public static bool CountsAsWritten(this ExamKind kind) => kind == ExamKind.Klausur; diff --git a/LehrerApp.Core/Services/ExamCoverSheetService.cs b/LehrerApp.Core/Services/ExamCoverSheetService.cs index 936d9cf..43a0361 100644 --- a/LehrerApp.Core/Services/ExamCoverSheetService.cs +++ b/LehrerApp.Core/Services/ExamCoverSheetService.cs @@ -37,12 +37,12 @@ public static class ExamCoverSheetService /// Wer eine Arbeit mitschreibt — eine Regel für Punkteeingabe und Deckblätter. public static class ExamParticipantService { - /// Bei einer Nachschreibarbeit: Schüler, die die erste Arbeit bereits mit Note - /// geschrieben haben. Sonst leer. + /// Bei einer Nachschreib- oder Förderarbeit: Schüler, die die erste Arbeit bereits mit + /// Note geschrieben haben. Sonst leer. public static HashSet WroteOriginal(Exam exam, Func> resultsByExam) { var wroteOriginal = new HashSet(); - if (exam.IsMakeUp && exam.RepeatOfExamId is { } originalId) + if (exam.ReplacesMissingGrade() && exam.RepeatOfExamId is { } originalId) foreach (var r in resultsByExam(originalId).Where(r => !r.Absent && r.Grade is not null)) wroteOriginal.Add(r.StudentId); return wroteOriginal; @@ -54,7 +54,7 @@ public static class ExamParticipantService // Niveau-Klausur: nur Schüler mit passendem Niveau. Klausuren ohne Niveau-Zuordnung gelten // weiterhin für die ganze Gruppe. if (exam.Niveau.HasValue && membership?.Niveau != exam.Niveau) return false; - // Nachschreibarbeit: wer die erste Arbeit schon mit Note geschrieben hat, taucht nicht auf — + // Nachschreib-/Förderarbeit: wer die erste Arbeit schon mit Note geschrieben hat, taucht nicht auf — // außer es gibt hier bereits ein Ergebnis (nichts verstecken, was schon eingetragen wurde). return hasResult || !wroteOriginal; } diff --git a/LehrerApp.Core/Services/ExamScoringService.cs b/LehrerApp.Core/Services/ExamScoringService.cs index 9b673d1..6e32721 100644 --- a/LehrerApp.Core/Services/ExamScoringService.cs +++ b/LehrerApp.Core/Services/ExamScoringService.cs @@ -45,10 +45,10 @@ public static class ExamScoringService AppliesTo(task, variant) && index < points.Count ? points[index] : 0).Sum(); /// - /// Wählt pro Arbeit samt allen verknüpften Folgearbeiten (Wiederholung, Nachschreibarbeit) + /// Wählt pro Arbeit samt allen verknüpften Folgearbeiten (Wiederholung, Nachschreib-/Förderarbeit) /// genau eine Note. Andere Arbeiten bleiben erhalten. Fehlt die erste Arbeit (Schüler war - /// abwesend), zählt die Nachschreibarbeit allein; hat der Schüler beide geschrieben, zählt bei - /// einer Nachschreibarbeit immer die erste — sie ersetzt nur eine fehlende Note. + /// abwesend), zählt die Nachschreib-/Förderarbeit allein; hat der Schüler beide geschrieben, + /// zählt immer die erste — sie ersetzen nur eine fehlende Note. /// public static List EffectiveGrades(IEnumerable<(Exam Exam, string Grade)> entries, GradingSystem system) @@ -72,7 +72,7 @@ public static class ExamScoringService var current = ordered[0].Grade; foreach (var next in ordered.Skip(1)) current = Choose(current, next.Grade, - next.Exam.IsMakeUp ? RepeatGradeRule.Original : next.Exam.RepeatGradeRule, system); + next.Exam.ReplacesMissingGrade() ? RepeatGradeRule.Original : next.Exam.RepeatGradeRule, system); result.Add(current); } return result; diff --git a/LehrerApp.Desktop.Tests/ExamDialogViewModelTests.cs b/LehrerApp.Desktop.Tests/ExamDialogViewModelTests.cs index fc3796b..429c7ab 100644 --- a/LehrerApp.Desktop.Tests/ExamDialogViewModelTests.cs +++ b/LehrerApp.Desktop.Tests/ExamDialogViewModelTests.cs @@ -84,4 +84,81 @@ public sealed class ExamDialogViewModelTests Assert.Equal(10, result.TotalPoints); Assert.Equal("1", result.Grade); } + + // ── Förderarbeit ───────────────────────────────────────────────────────── + + private static (ExamDialogViewModel Vm, Exam Original) BuildFollowUpViewModel(DateOnly originalDate) + { + var original = new Exam { GroupId = Guid.NewGuid(), Title = "Atombau", Date = originalDate }; + var vm = new ExamDialogViewModel(new FakeExams([original]), new FakeCompetencyDomains(), + new FakeGradingKeyTemplates(), new GradingService(), original.GroupId, null, 9, + GradingSystem.Grades1To6, "Chemie", false, null, null); + vm.Title = "Atombau (Förder)"; + vm.Tasks.Add(new ExamTaskEditItem("A1", 10, 1, [], []) { OnChanged = () => { } }); + vm.Tasks[0].MaxPoints = 10; + vm.SelectedOriginalExam = original; + return (vm, original); + } + + [Fact] + public void Foerderarbeit_UebernimmtDatumDerErstenArbeitUndDarfAmSelbenTagLiegen() + { + var (vm, original) = BuildFollowUpViewModel(new DateOnly(2026, 10, 14)); + + vm.FollowUpKindName = "Förderarbeit"; + + Assert.Equal("14.10.2026", vm.DateText); + vm.SaveCommand.Execute(null); + Assert.Equal("", vm.RepeatError); + Assert.NotNull(vm.Result); + Assert.True(vm.Result!.IsSupportWork); + Assert.False(vm.Result.IsMakeUp); + Assert.Equal(original.Id, vm.Result.RepeatOfExamId); + Assert.Equal(original.Date, vm.Result.Date); + } + + [Fact] + public void Foerderarbeit_VorDerErstenArbeit_WirdAbgelehnt() + { + var (vm, _) = BuildFollowUpViewModel(new DateOnly(2026, 10, 14)); + vm.FollowUpKindName = "Förderarbeit"; + + vm.DateText = "13.10.2026"; + vm.SaveCommand.Execute(null); + + Assert.Contains("Förderarbeit", vm.RepeatError); + Assert.Null(vm.Result); + } + + [Fact] + public void Nachschreibarbeit_AmSelbenTag_BleibtAbgelehnt() + { + var (vm, _) = BuildFollowUpViewModel(new DateOnly(2026, 10, 14)); + vm.FollowUpKindName = "Nachschreibarbeit"; + + vm.DateText = "14.10.2026"; + vm.SaveCommand.Execute(null); + + Assert.Contains("Nachschreibarbeit", vm.RepeatError); + Assert.Null(vm.Result); + } + + [Fact] + public void Foerderarbeit_WirdBeimBearbeitenWiederhergestelltOhneDatumZuUeberschreiben() + { + var original = new Exam { GroupId = Guid.NewGuid(), Title = "Atombau", Date = new DateOnly(2026, 10, 14) }; + var support = new Exam + { + GroupId = original.GroupId, Title = "Förder", Date = new DateOnly(2026, 10, 16), + RepeatOfExamId = original.Id, IsSupportWork = true, + }; + + var vm = new ExamDialogViewModel(new FakeExams([original, support]), new FakeCompetencyDomains(), + new FakeGradingKeyTemplates(), new GradingService(), original.GroupId, null, 9, + GradingSystem.Grades1To6, "Chemie", false, support, null); + + Assert.True(vm.IsSupportWork); + Assert.Equal("16.10.2026", vm.DateText); + Assert.False(vm.ShowRepeatRule); + } } diff --git a/LehrerApp.Desktop/Services/GradeReportDrawingBuilder.cs b/LehrerApp.Desktop/Services/GradeReportDrawingBuilder.cs index 61cdbff..59103dc 100644 --- a/LehrerApp.Desktop/Services/GradeReportDrawingBuilder.cs +++ b/LehrerApp.Desktop/Services/GradeReportDrawingBuilder.cs @@ -22,7 +22,8 @@ public static class GradeReportDrawingBuilder if (exam.RepeatOfExamId is null) return new DrawingValue([], 0); if (original is null || original.Id != exam.RepeatOfExamId || original.GroupId != exam.GroupId) throw new InvalidDataException("Die verknüpfte erste Arbeit ist nicht verfügbar."); - var rule = exam.IsMakeUp ? "Die Nachschreibarbeit ersetzt die versäumte erste Arbeit. Liegen beide Noten vor, zählt die erste Arbeit." + var rule = exam.IsSupportWork ? "Die Förderarbeit ersetzt die erste Arbeit. Liegen beide Noten vor, zählt die erste Arbeit." + : exam.IsMakeUp ? "Die Nachschreibarbeit ersetzt die versäumte erste Arbeit. Liegen beide Noten vor, zählt die erste Arbeit." : exam.RepeatGradeRule switch { RepeatGradeRule.Repeat => "Für die Bewertung zählt die Note der Wiederholungsarbeit.", @@ -35,7 +36,7 @@ public static class GradeReportDrawingBuilder ExamScoringService.Maximum(original.Tasks, originalResult.Variant), original.GradingKey); var firstGrade = originalResult is { Absent: true } ? "abwesend" : Value(grade); return Text(template, ReportTextDrawing.RepeatInfo, - exam.IsMakeUp ? "Nachschreibarbeit" : "Wiederholungsarbeit", + exam.IsSupportWork ? "Förderarbeit" : exam.IsMakeUp ? "Nachschreibarbeit" : "Wiederholungsarbeit", [$"Erste Arbeit: {original.Title} vom {original.Date:dd.MM.yyyy}", $"Note der ersten Arbeit: {firstGrade}", rule]); } diff --git a/LehrerApp.Desktop/ViewModels/Groups/ExamEvaluationViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/ExamEvaluationViewModels.cs index a850c0e..bd44e3a 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/ExamEvaluationViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/ExamEvaluationViewModels.cs @@ -42,7 +42,7 @@ public partial class ExamEvaluationDialogViewModel : ObservableObject public ObservableCollection RepeatComparison { get; } = []; public bool HasRepeatComparison => RepeatComparison.Count > 0; public string RepeatComparisonTitle { get; private set; } = ""; - /// "Wiederholung" bzw. "Nachschreibarbeit" — Beschriftung der Folgearbeit im Vergleich. + /// "Wiederholung", "Nachschreibarbeit" bzw. "Förderarbeit" — Beschriftung der Folgearbeit im Vergleich. public string FollowUpLabel { get; private set; } = "Wiederholung"; public string FollowUpComparisonHeading => $"Vergleich mit der {FollowUpLabel}"; public ObservableCollection GradingKeyEntries { get; } = []; @@ -72,8 +72,8 @@ public partial class ExamEvaluationDialogViewModel : ObservableObject : _exams.GetByGroup(_exam.GroupId).Where(e => e.RepeatOfExamId == _exam.Id) .OrderBy(e => e.Date).FirstOrDefault(); if (repeat is null) return; - FollowUpLabel = repeat.IsMakeUp ? "Nachschreibarbeit" : "Wiederholung"; - var rule = repeat.IsMakeUp ? "ersetzt fehlende Note" : repeat.RepeatGradeRule switch + FollowUpLabel = repeat.IsSupportWork ? "Förderarbeit" : repeat.IsMakeUp ? "Nachschreibarbeit" : "Wiederholung"; + var rule = repeat.ReplacesMissingGrade() ? "ersetzt fehlende Note" : repeat.RepeatGradeRule switch { RepeatGradeRule.Repeat => "Wiederholung zählt", RepeatGradeRule.Original => "Erste Arbeit zählt", diff --git a/LehrerApp.Desktop/ViewModels/Groups/ExamViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/ExamViewModels.cs index e18694b..8ee5101 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/ExamViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/ExamViewModels.cs @@ -47,19 +47,33 @@ public partial class ExamDialogViewModel : ObservableObject [ObservableProperty] private string _repeatError = ""; [ObservableProperty] private string _taskPointsError = ""; [ObservableProperty] private string _kindName = ExamKind.Klausur.Label(); - [ObservableProperty] private bool _isMakeUp; + [ObservableProperty] private string _followUpKindName = WiederholungName; + + private const string WiederholungName = "Wiederholung"; + private const string NachschreibarbeitName = "Nachschreibarbeit"; + private const string FoerderarbeitName = "Förderarbeit"; + // Beim Befüllen aus einer vorhandenen Arbeit darf die Datums-Übernahme das gespeicherte Datum + // nicht überschreiben. + private bool _initializing = true; public bool IsDifferentiated { get; } public string[] NiveauOptions => NiveauDisplay.Options; public string[] KindOptions { get; } = Enum.GetValues().Select(k => k.Label()).ToArray(); public string[] RepeatRuleOptions => ["Bessere zählt", "Wiederholung zählt", "Erste Arbeit zählt"]; + public string[] FollowUpKindOptions { get; } = [WiederholungName, NachschreibarbeitName, FoerderarbeitName]; + public bool IsMakeUp => FollowUpKindName == NachschreibarbeitName; + public bool IsSupportWork => FollowUpKindName == FoerderarbeitName; public bool HasSelectedOriginalExam => SelectedOriginalExam is not null; /// Art und Zählweise sind bei einer verknüpften Folgearbeit festgelegt: sie erbt die Art der - /// ersten Arbeit, eine Nachschreibarbeit ersetzt nur fehlende Noten (keine Regelwahl nötig). + /// ersten Arbeit, Nachschreib- und Förderarbeiten ersetzen nur fehlende Noten (keine Regelwahl nötig). public bool CanChooseKind => !HasSelectedOriginalExam; - public bool ShowRepeatRule => HasSelectedOriginalExam && !IsMakeUp; - public string LinkedExamLabel => IsMakeUp - ? "Nachschreibarbeit zu (optional)" : "Wiederholung oder Nachschreibarbeit zu (optional)"; + public bool ShowRepeatRule => HasSelectedOriginalExam && FollowUpKindName == WiederholungName; + public string LinkedExamLabel => FollowUpKindName switch + { + NachschreibarbeitName => "Nachschreibarbeit zu (optional)", + FoerderarbeitName => "Förderarbeit zu (optional)", + _ => "Wiederholung, Nachschreib- oder Förderarbeit zu (optional)", + }; private ExamKind Kind => Enum.GetValues().FirstOrDefault(k => k.Label() == KindName); public ObservableCollection AvailableOriginalExams { get; } = []; @@ -128,7 +142,9 @@ public partial class ExamDialogViewModel : ObservableObject if (!isDuplicate) { SelectedOriginalExam = AvailableOriginalExams.FirstOrDefault(e => e.Id == source.RepeatOfExamId); - IsMakeUp = source.IsMakeUp && SelectedOriginalExam is not null; + if (SelectedOriginalExam is not null) + FollowUpKindName = source.IsSupportWork ? FoerderarbeitName + : source.IsMakeUp ? NachschreibarbeitName : WiederholungName; RepeatRuleName = source.RepeatGradeRule switch { RepeatGradeRule.Repeat => "Wiederholung zählt", @@ -152,6 +168,7 @@ public partial class ExamDialogViewModel : ObservableObject foreach (var t in Tasks) t.ShowWeight = UseWeighting; RecomputeTotals(); UpdateWeekLoadHint(); + _initializing = false; } partial void OnUseWeightingChanged(bool value) @@ -161,17 +178,29 @@ public partial class ExamDialogViewModel : ObservableObject partial void OnSelectedOriginalExamChanged(Exam? value) { if (value is not null) KindName = value.Kind.Label(); - else IsMakeUp = false; + else FollowUpKindName = WiederholungName; OnPropertyChanged(nameof(HasSelectedOriginalExam)); OnPropertyChanged(nameof(CanChooseKind)); OnPropertyChanged(nameof(ShowRepeatRule)); + TakeOverOriginalDateForSupportWork(); UpdateWeekLoadHint(); } - partial void OnIsMakeUpChanged(bool value) + partial void OnFollowUpKindNameChanged(string value) { + OnPropertyChanged(nameof(IsMakeUp)); + OnPropertyChanged(nameof(IsSupportWork)); OnPropertyChanged(nameof(ShowRepeatRule)); OnPropertyChanged(nameof(LinkedExamLabel)); + TakeOverOriginalDateForSupportWork(); + } + + /// Eine Förderarbeit wird meist parallel zur ersten Arbeit geschrieben: das Datum der + /// ersten Arbeit ist der Vorschlag, bleibt aber änderbar. + private void TakeOverOriginalDateForSupportWork() + { + if (_initializing || !IsSupportWork || SelectedOriginalExam is null) return; + DateText = SelectedOriginalExam.Date.ToString("dd.MM.yyyy"); } partial void OnKindNameChanged(string value) => UpdateWeekLoadHint(); @@ -382,12 +411,25 @@ public partial class ExamDialogViewModel : ObservableObject var gradingKey = BuildGradingKeyEntries(); var gradingKeyError = _grading.ValidateGradingKey(gradingKey); if (gradingKeyError is not null) { GradingKeyValidation = gradingKeyError; valid = false; } - if (SelectedOriginalExam is not null && SelectedOriginalExam.Date >= date) + // Datumsprüfung nur bei gültigem Datum — sonst meldet das Datumsfeld den Fehler bereits. + // Eine Förderarbeit entsteht parallel zur ersten Arbeit und darf am selben Tag liegen. + if (SelectedOriginalExam is not null && DateTextError == "") { - RepeatError = IsMakeUp - ? "Die erste Arbeit muss vor der Nachschreibarbeit liegen." - : "Die erste Arbeit muss vor der Wiederholung liegen."; - valid = false; + if (IsSupportWork) + { + if (SelectedOriginalExam.Date > date) + { + RepeatError = "Die Förderarbeit darf nicht vor der ersten Arbeit liegen."; + valid = false; + } + } + else if (SelectedOriginalExam.Date >= date) + { + RepeatError = IsMakeUp + ? "Die erste Arbeit muss vor der Nachschreibarbeit liegen." + : "Die erste Arbeit muss vor der Wiederholung liegen."; + valid = false; + } } if (Tasks.Any(t => t.VariantName != "Beide") && (TotalPoints <= 0 || Tasks.Where(t => !t.IsBonus && t.VariantName != "A").Sum(t => t.MaxPoints) <= 0)) @@ -410,6 +452,7 @@ public partial class ExamDialogViewModel : ObservableObject Result.RepeatOfExamId = SelectedOriginalExam?.Id; Result.Kind = SelectedOriginalExam?.Kind ?? Kind; Result.IsMakeUp = IsMakeUp && SelectedOriginalExam is not null; + Result.IsSupportWork = IsSupportWork && SelectedOriginalExam is not null; Result.RepeatGradeRule = RepeatRuleName switch { "Wiederholung zählt" => RepeatGradeRule.Repeat, diff --git a/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs index c3498b8..a8ccc99 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/GroupViewModels.cs @@ -656,6 +656,7 @@ public class ExamSummary NiveauLabel = e.Niveau.HasValue ? NiveauDisplay.ToName(e.Niveau) : "alle"; var hasVariants = e.Tasks.Any(t => t.Variant is not null); var followUp = e.RepeatOfExamId is null ? null + : e.IsSupportWork ? (hasVariants ? "Förder · A/B" : "Förderarbeit") : e.IsMakeUp ? (hasVariants ? "Nachschr. · A/B" : "Nachschreiben") : hasVariants ? "Wdh. · A/B" : "Wiederholung"; // Folgearbeiten behalten ihre Art im Hintergrund (sie erben sie), die Spalte nennt nur diff --git a/LehrerApp.Desktop/ViewModels/Groups/ReportGradeAssistantViewModels.cs b/LehrerApp.Desktop/ViewModels/Groups/ReportGradeAssistantViewModels.cs index 4063417..ef3b276 100644 --- a/LehrerApp.Desktop/ViewModels/Groups/ReportGradeAssistantViewModels.cs +++ b/LehrerApp.Desktop/ViewModels/Groups/ReportGradeAssistantViewModels.cs @@ -373,7 +373,7 @@ public partial class ReportGradeAssistantViewModel : ObservableObject if (!ReportGradeCalculator.ExamApplies(exam, membership)) continue; var results = _calculator.ResultsByExam[exam.Id]; results.TryGetValue(studentId, out var own); - // Nachschreib- und Wiederholungsarbeiten betreffen nur einzelne Schüler — ohne eigenes + // Nachschreib-, Förder- und Wiederholungsarbeiten betreffen nur einzelne Schüler — ohne eigenes // Ergebnis gehören sie nicht in diese Übersicht. if (own is null && exam.RepeatOfExamId.HasValue) continue; @@ -396,7 +396,8 @@ public partial class ReportGradeAssistantViewModel : ObservableObject var classAverage = classGrades.Count > 0 ? $"Ø Kurs {Format(_grading.WeightedAverage(classGrades))}" : ""; var kind = exam.Kind.Label(); - if (exam.IsMakeUp) kind += " · Nachschreibarbeit"; + if (exam.IsSupportWork) kind += " · Förderarbeit"; + else if (exam.IsMakeUp) kind += " · Nachschreibarbeit"; else if (exam.RepeatOfExamId.HasValue) kind += " · Wiederholung"; Works.Add(new AssistantWorkCard(exam.Title, exam.Date, kind, gradeDisplay, percentDisplay, diff --git a/LehrerApp.Desktop/Views/Groups/ExamDialog.axaml b/LehrerApp.Desktop/Views/Groups/ExamDialog.axaml index 01ceb31..0b8cb32 100644 --- a/LehrerApp.Desktop/Views/Groups/ExamDialog.axaml +++ b/LehrerApp.Desktop/Views/Groups/ExamDialog.axaml @@ -76,9 +76,9 @@