Files
adminandClaude Opus 5.5 d9eac0d1d2
CI / build-and-test (push) Canceled after 0s
Zwischenstand: vorläufige Noten zu Stichtag und Anlass
Ein Zwischenstand ist ein Durchgang aus Stichtag, Anlass und
Schülerauswahl (ganze Gruppe, Teilgruppe oder Einzelfall, mit
Schnellfilter für gefährdete Schüler). Der Zeugnisnoten-Assistent geht
die gewählten Schüler im Zwischenstand-Modus durch und notiert
vorläufige schriftliche, mündliche und Gesamtnote samt Notiz.

Gespeichert wird das als eigenes Modell InterimGrade, getrennt von der
Zeugnisnote. Die Berechnung endet am Stichtag und rechnet den laufenden
Mitarbeits-Abschnitt mit ein. Zwischenstände erscheinen im Assistenten
als Liste und Marker im Verlauf sowie als graue Spalte in der
Notenübersicht (nicht in "Gesamt", nicht im PDF).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:01:34 +02:00

37 lines
1.8 KiB
C#

using LehrerApp.Core.Models;
using LehrerApp.Core.Services;
namespace LehrerApp.Desktop.ViewModels.Groups;
/// <param name="RunningParticipation">Notenvorschlag des am Stichtag laufenden
/// Mitarbeits-Abschnitts, der in <paramref name="Result"/> bereits eingerechnet ist.</param>
public sealed record InterimResult(ParticipationPeriod Period, ReportGradeResult Result, string? RunningParticipation);
/// <summary>
/// Vorläufige Halbjahresnote zu einem Stichtag (Zwischenstand, 2.7.5). Anders als die
/// Zeugnisnote zählt hier der laufende Mitarbeits-Abschnitt mit seinem Vorschlag mit — sonst
/// bestünde ein Zwischenstand früh im Halbjahr nur aus dem Schriftlichen.
/// </summary>
public sealed class InterimGradeCalculator(ReportGradeCalculator calculator, ParticipationTimelineBuilder timeline,
IReadOnlyList<ParticipationSection> sections)
{
/// Das Halbjahr, zu dem ein Stichtag gehört.
public ParticipationPeriod HalfOf(DateOnly date) =>
date <= calculator.Range(ParticipationPeriod.H1).To ? ParticipationPeriod.H1 : ParticipationPeriod.H2;
public InterimResult Calculate(Guid studentId, DateOnly asOf, RoundingRule rounding)
{
var period = HalfOf(asOf);
var from = calculator.Range(period).From;
// "Laufend" aus Sicht des Stichtags: alles nach dem letzten bis dahin beendeten Abschnitt.
var closed = sections.Where(s => s.EndDate <= asOf).ToList();
var openStart = timeline.OpenStart(closed, asOf);
if (openStart < from) openStart = from;
var running = openStart <= asOf ? timeline.ComputeSuggestion(studentId, openStart, asOf) : null;
var result = calculator.Calculate(studentId, period, rounding, asOf: asOf, runningParticipation: running);
return new InterimResult(period, result, running);
}
}