Neue Funktion Schüler austragen statt aus Kurs löschen.

This commit is contained in:
2026-08-15 23:38:42 +02:00
parent 52bb9c2c2f
commit da8d2bb1da
19 changed files with 473 additions and 114 deletions
@@ -25,6 +25,7 @@ public partial class ReportGradeDialogViewModel : ObservableObject
private readonly GroupType _groupType;
private readonly GradingSystem _gradingSystem;
private readonly string _groupLabel;
private readonly string _schoolYear;
[ObservableProperty] private ParticipationPeriodOption _selectedPeriod;
[ObservableProperty] private RoundingRule _roundingRule = RoundingRule.Commercial;
@@ -51,11 +52,12 @@ public partial class ReportGradeDialogViewModel : ObservableObject
public ReportGradeDialogViewModel(IGradeRepository grades, IExamRepository exams,
IExamResultRepository results, IStudentRepository students, IGroupMembershipRepository memberships,
IGradingSchemeRepository schemes, IReportGradeRepository reportGrades, GradingService grading,
Guid groupId, GroupType groupType, GradingSystem gradingSystem, string groupLabel)
Guid groupId, GroupType groupType, GradingSystem gradingSystem, string groupLabel, string schoolYear)
{
_grades = grades; _exams = exams; _results = results; _students = students;
_memberships = memberships; _schemes = schemes; _reportGrades = reportGrades; _grading = grading;
_groupId = groupId; _groupType = groupType; _gradingSystem = gradingSystem; _groupLabel = groupLabel;
_schoolYear = schoolYear;
_selectedPeriod = PeriodOptions[0];
Recompute();
@@ -77,18 +79,24 @@ public partial class ReportGradeDialogViewModel : ObservableObject
var period = SelectedPeriod.Period;
var periodTag = SelectedPeriod.Label;
var (periodFrom, periodTo) = GroupMembershipService.SchoolYearPeriod(_schoolYear, period switch
{
ParticipationPeriod.H1 => SchoolYearPeriodKind.H1,
ParticipationPeriod.H2 => SchoolYearPeriodKind.H2,
_ => SchoolYearPeriodKind.FullYear,
});
var students = _students.GetByGroup(_groupId);
var membershipsByStudent = _memberships.GetByGroup(_groupId).ToDictionary(m => m.StudentId);
var exams = _exams.GetByGroup(_groupId).Where(e => InPeriod(e.Date, period)).ToList();
var exams = _exams.GetByGroup(_groupId).Where(e => e.Date >= periodFrom && e.Date <= periodTo).ToList();
var resultsByExam = exams.ToDictionary(e => e.Id, e => _results.GetByExam(e.Id).ToDictionary(r => r.StudentId));
var allGrades = _grades.GetByGroup(_groupId).Where(g => InPeriod(g.Date, period)).ToList();
var allGrades = _grades.GetByGroup(_groupId).Where(g => g.Date >= periodFrom && g.Date <= periodTo).ToList();
Rows.Clear();
foreach (var student in students.OrderBy(s => s.LastName).ThenBy(s => s.FirstName))
{
membershipsByStudent.TryGetValue(student.Id, out var membership);
if (!StudentActiveInPeriod(membership, period)) continue;
if (membership is not null && !GroupMembershipService.Overlaps(membership, periodFrom, periodTo)) continue;
var existing = _reportGrades.GetByStudentGroupPeriod(student.Id, _groupId, periodTag);
@@ -101,6 +109,7 @@ public partial class ReportGradeDialogViewModel : ObservableObject
var examGrades = new List<(string Grade, double Weight)>();
foreach (var exam in exams)
{
if (membership is not null && !GroupMembershipService.IsActiveOn(membership, exam.Date)) continue;
if (exam.Niveau.HasValue && membership?.Niveau != exam.Niveau) continue;
if (!resultsByExam[exam.Id].TryGetValue(student.Id, out var result)) continue;
if (result.Absent || result.Grade is null) continue;
@@ -108,10 +117,12 @@ public partial class ReportGradeDialogViewModel : ObservableObject
}
var participationGrades = allGrades
.Where(g => g.StudentId == student.Id && g.Category == GradeCategory.Participation)
.Where(g => g.StudentId == student.Id && g.Category == GradeCategory.Participation
&& (membership is null || GroupMembershipService.IsActiveOn(membership, g.Date)))
.Select(g => (g.Value, g.Weight)).ToList();
var otherGrades = allGrades
.Where(g => g.StudentId == student.Id && g.Category != GradeCategory.Participation)
.Where(g => g.StudentId == student.Id && g.Category != GradeCategory.Participation
&& (membership is null || GroupMembershipService.IsActiveOn(membership, g.Date)))
.Select(g => (g.Value, g.Weight)).ToList();
var calculated = _grading.CalculateReportGrade(examGrades, participationGrades, otherGrades,
@@ -168,23 +179,6 @@ public partial class ReportGradeDialogViewModel : ObservableObject
return sb.ToString();
}
private static bool InPeriod(DateOnly date, ParticipationPeriod period) => period switch
{
ParticipationPeriod.H1 => date.Month >= 8 || date.Month <= 1,
ParticipationPeriod.H2 => date.Month >= 2 && date.Month <= 7,
_ => true,
};
private static bool StudentActiveInPeriod(GroupMembership? m, ParticipationPeriod period)
{
if (period == ParticipationPeriod.FullYear || m is null) return true;
return m.Period switch
{
MembershipPeriod.H1Only => period == ParticipationPeriod.H1,
MembershipPeriod.H2Only => period == ParticipationPeriod.H2,
_ => true,
};
}
}
// ── Rundungsregel-Anzeige ─────────────────────────────────────────────────────