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
@@ -23,6 +23,7 @@ public partial class GradeOverviewTabViewModel : ObservableObject
private GradingSystem _gradingSystem;
private GroupType _groupType;
private string _groupLabel = "";
private string _schoolYear = "";
private bool _sortByTotal;
private bool _sortDescending;
@@ -30,6 +31,7 @@ public partial class GradeOverviewTabViewModel : ObservableObject
public GradingSystem GradingSystem => _gradingSystem;
public GroupType GroupType => _groupType;
public string GroupLabel => _groupLabel;
public string SchoolYear => _schoolYear;
[ObservableProperty] private ParticipationPeriodOption _selectedPeriod;
[ObservableProperty] private bool _showAsPoints = true;
@@ -61,12 +63,14 @@ public partial class GradeOverviewTabViewModel : ObservableObject
_selectedPeriod = PeriodOptions[0];
}
public void Initialize(Guid groupId, GradingSystem gradingSystem, GroupType groupType, string groupLabel)
public void Initialize(Guid groupId, GradingSystem gradingSystem, GroupType groupType,
string groupLabel, string schoolYear)
{
_groupId = groupId;
_gradingSystem = gradingSystem;
_groupType = groupType;
_groupLabel = groupLabel;
_schoolYear = schoolYear;
ShowAsPoints = gradingSystem == GradingSystem.Points0To15;
OnPropertyChanged(nameof(CanTogglePointsView));
Recompute();
@@ -119,18 +123,24 @@ public partial class GradeOverviewTabViewModel : ObservableObject
private void Recompute()
{
var period = SelectedPeriod.Period;
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))
.Where(e => e.Date >= periodFrom && e.Date <= periodTo)
.OrderBy(e => e.Date)
.ToList();
var resultsByExam = exams.ToDictionary(e => e.Id, e => _results.GetByExam(e.Id).ToDictionary(r => r.StudentId));
var otherGrades = _grades.GetByGroup(_groupId)
.Where(g => InPeriod(g.Date, period))
.Where(g => g.Date >= periodFrom && g.Date <= periodTo)
.ToList();
var gradeColumnKeys = otherGrades
.Select(g => (g.Category, Note: g.Note ?? "", g.Date))
@@ -153,13 +163,15 @@ public partial class GradeOverviewTabViewModel : ObservableObject
foreach (var student in students)
{
membershipsByStudent.TryGetValue(student.Id, out var membership);
if (!StudentActiveInPeriod(membership, period)) continue;
if (membership is not null && !GroupMembershipService.Overlaps(membership, periodFrom, periodTo)) continue;
var cells = new List<string>();
var numeric = new List<(string Grade, double Weight)>();
foreach (var exam in exams)
{
if (membership is not null && !GroupMembershipService.IsActiveOn(membership, exam.Date))
{ cells.Add(""); continue; }
if (exam.Niveau.HasValue && membership?.Niveau != exam.Niveau) { cells.Add(""); continue; }
resultsByExam[exam.Id].TryGetValue(student.Id, out var result);
if (result is null) { cells.Add(""); continue; }
@@ -171,6 +183,8 @@ public partial class GradeOverviewTabViewModel : ObservableObject
foreach (var key in gradeColumnKeys)
{
if (membership is not null && !GroupMembershipService.IsActiveOn(membership, key.Date))
{ cells.Add(""); continue; }
var grade = otherGrades.FirstOrDefault(g =>
g.StudentId == student.Id && g.Category == key.Category &&
(g.Note ?? "") == key.Note && g.Date == key.Date);
@@ -206,23 +220,6 @@ public partial class GradeOverviewTabViewModel : ObservableObject
for (var i = 0; i < sorted.Count; i++) Rows.Move(Rows.IndexOf(sorted[i]), i);
}
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,
};
}
}
public class GradeOverviewColumnDef(string header)
@@ -404,6 +401,8 @@ public partial class GradeEditItem : ObservableObject
public partial class CollectiveGradeDialogViewModel : ObservableObject
{
private readonly IGradeRepository _grades;
private readonly IGroupMembershipRepository _memberships;
private readonly List<Student> _students;
private readonly Guid _groupId;
[ObservableProperty] private GradeCategory _category = GradeCategory.Other;
@@ -422,11 +421,36 @@ public partial class CollectiveGradeDialogViewModel : ObservableObject
public ObservableCollection<CollectiveGradeStudentRow> Rows { get; } = [];
public CollectiveGradeDialogViewModel(IGradeRepository grades, IStudentRepository students, Guid groupId)
public CollectiveGradeDialogViewModel(IGradeRepository grades, IStudentRepository students,
IGroupMembershipRepository memberships, Guid groupId)
{
_grades = grades; _groupId = groupId;
foreach (var s in students.GetByGroup(groupId).OrderBy(s => s.LastName).ThenBy(s => s.FirstName))
Rows.Add(new CollectiveGradeStudentRow(s.Id, s.FullName));
_grades = grades; _memberships = memberships; _groupId = groupId;
_students = students.GetByGroup(groupId).OrderBy(s => s.LastName).ThenBy(s => s.FirstName).ToList();
RebuildRows(DateOnly.FromDateTime(DateTime.Today));
}
partial void OnDateTextChanged(string value)
{
if (DateOnly.TryParseExact(value, "dd.MM.yyyy", null,
System.Globalization.DateTimeStyles.None, out var date))
RebuildRows(date);
}
private void RebuildRows(DateOnly date)
{
var previousValues = Rows.ToDictionary(r => r.StudentId, r => r.Value);
var membershipByStudent = _memberships.GetByGroup(_groupId).ToDictionary(m => m.StudentId);
Rows.Clear();
foreach (var student in _students)
{
if (membershipByStudent.TryGetValue(student.Id, out var membership)
&& !GroupMembershipService.IsActiveOn(membership, date))
continue;
Rows.Add(new CollectiveGradeStudentRow(student.Id, student.FullName)
{
Value = previousValues.GetValueOrDefault(student.Id, ""),
});
}
}
[RelayCommand]