fix: Fehlzeitenkalender in Templates, Datenbezug und Layout
CI / build-and-test (push) Waiting to run
CI / build-and-test (push) Waiting to run
This commit is contained in:
@@ -18,4 +18,18 @@ public sealed class UntisNameMatchingTests
|
||||
[InlineData("Ben Schmidt", "")]
|
||||
public void NamesMatch_LehntUnterschiedlicheOderFehlendeNamenAb(string? a, string b) =>
|
||||
Assert.False(UntisNameMatching.NamesMatch(a, b));
|
||||
|
||||
// Regression: Student.FullName liefert "Nachname, Vorname" (mit Komma) für Anzeigezwecke.
|
||||
// Wird dieser String direkt an NamesMatch übergeben, bleibt das Komma am Wort kleben
|
||||
// ("gerste," != "gerste") und der Abgleich gegen WebUntis-Namen (immer ohne Komma) schlägt
|
||||
// fehl - genau das ließ den Anwesenheitskalender/die Fehlzeitenliste im Elternbrief leer
|
||||
// bleiben, obwohl echte Fehlzeiten vorlagen. Aufrufer müssen deshalb "Vorname Nachname" ohne
|
||||
// Komma bilden (siehe StudentAttendanceCalendarDrawingBuilder.StudentAttendanceCalendarService
|
||||
// und ClassTeacherOverviewViewModel.cs:1173), statt Student.FullName direkt zu verwenden.
|
||||
[Fact]
|
||||
public void NamesMatch_KommaGetrennterAnzeigename_PasstNichtOhneUmformung()
|
||||
{
|
||||
Assert.False(UntisNameMatching.NamesMatch("Gerste, Amelia", "Gerste Amelia"));
|
||||
Assert.True(UntisNameMatching.NamesMatch("Amelia Gerste", "Gerste Amelia"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,12 @@ public static class StudentAttendanceCalendarDrawingBuilder
|
||||
_ => .85f,
|
||||
};
|
||||
var contentWidth = width * scale;
|
||||
var cellWidth = contentWidth / 7;
|
||||
var cellHeight = 10 * scale;
|
||||
var monthGap = 6 * scale;
|
||||
var monthGapX = 6 * scale;
|
||||
var first = options.NormalizedStartMonth;
|
||||
var monthCount = options.NormalizedMonthCount;
|
||||
var monthWidth = (contentWidth - monthGapX * (monthCount - 1)) / monthCount;
|
||||
var cellWidth = monthWidth / 7;
|
||||
var commands = new List<DrawingCommand>();
|
||||
var y = 0f;
|
||||
commands.Add(new DrawStringEx(0, y, 14 * scale, contentWidth, "Anwesenheit",
|
||||
@@ -52,6 +53,8 @@ public static class StudentAttendanceCalendarDrawingBuilder
|
||||
DrawingTextAlignment.AlignLeft, 8 * scale, Color: "#6B7280"));
|
||||
y += 10 * scale + 2 * scale;
|
||||
var weekdays = new[] { "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So" };
|
||||
var gridStartY = y;
|
||||
var maxWeeks = 0;
|
||||
for (var monthIndex = 0; monthIndex < monthCount; monthIndex++)
|
||||
{
|
||||
var current = first.AddMonths(monthIndex);
|
||||
@@ -59,30 +62,33 @@ public static class StudentAttendanceCalendarDrawingBuilder
|
||||
DateOnly.FromDateTime(DateTime.Today), studentName);
|
||||
var offset = ((int)current.DayOfWeek + 6) % 7;
|
||||
var weeks = (int)Math.Ceiling((offset + days.Count) / 7d);
|
||||
commands.Add(new DrawStringEx(0, y, 11 * scale, contentWidth,
|
||||
maxWeeks = Math.Max(maxWeeks, weeks);
|
||||
var xOffset = monthIndex * (monthWidth + monthGapX);
|
||||
var monthY = gridStartY;
|
||||
commands.Add(new DrawStringEx(xOffset, monthY, 11 * scale, monthWidth,
|
||||
current.ToString("MMMM yyyy", CultureInfo.GetCultureInfo("de-DE")),
|
||||
DrawingTextAlignment.AlignLeft, 9 * scale, Color: "#374151", Bold: true));
|
||||
y += 11 * scale;
|
||||
monthY += 11 * scale;
|
||||
for (var column = 0; column < 7; column++)
|
||||
commands.Add(new DrawStringEx(column * cellWidth, y, 9 * scale, cellWidth, weekdays[column],
|
||||
DrawingTextAlignment.AlignCenter, 7 * scale, Color: "#6B7280", Bold: true));
|
||||
y += 9 * scale;
|
||||
commands.Add(new DrawStringEx(xOffset + column * cellWidth, monthY, 9 * scale, cellWidth,
|
||||
weekdays[column], DrawingTextAlignment.AlignCenter, 7 * scale, Color: "#6B7280", Bold: true));
|
||||
monthY += 9 * scale;
|
||||
|
||||
foreach (var day in days)
|
||||
{
|
||||
var index = offset + day.Date.Day - 1;
|
||||
var column = index % 7;
|
||||
var row = index / 7;
|
||||
var x = column * cellWidth;
|
||||
var cellY = y + row * cellHeight;
|
||||
var x = xOffset + column * cellWidth;
|
||||
var cellY = monthY + row * cellHeight;
|
||||
commands.Add(new DrawRectangle(x + scale, cellY, cellWidth - 2 * scale, cellHeight - scale,
|
||||
"#D1D5DB", .35f, day.HasSignal ? day.SignalColorHex : "#FFFFFF"));
|
||||
commands.Add(new DrawStringEx(x, cellY + scale, cellHeight - 2 * scale, cellWidth,
|
||||
day.HasSignal ? day.SignalCode : day.DayNumber, DrawingTextAlignment.AlignCenter, 7 * scale,
|
||||
Color: day.HasSignal ? "#FFFFFF" : "#374151", Bold: day.HasSignal));
|
||||
}
|
||||
y += weeks * cellHeight + monthGap;
|
||||
}
|
||||
y = gridStartY + 11 * scale + 9 * scale + maxWeeks * cellHeight + monthGapX;
|
||||
|
||||
commands.Add(new DrawStringEx(0, y, 8 * scale, contentWidth,
|
||||
"U unentschuldigt · A abwesend · V verspätet · E entschuldigt · ! Klassenbuch",
|
||||
@@ -190,9 +196,10 @@ public sealed class StudentAttendanceCalendarService(
|
||||
|
||||
var first = options.NormalizedStartMonth;
|
||||
var last = first.AddMonths(options.NormalizedMonthCount).AddDays(-1);
|
||||
var matchName = $"{student.FirstName} {student.LastName}";
|
||||
var rosterName = rosterCache.GetByClass(className)
|
||||
.FirstOrDefault(r => UntisNameMatching.NamesMatch(r.DisplayName, student.FullName))?.DisplayName
|
||||
?? student.FullName;
|
||||
.FirstOrDefault(r => UntisNameMatching.NamesMatch(r.DisplayName, matchName))?.DisplayName
|
||||
?? matchName;
|
||||
var start = first.Year * 10000 + first.Month * 100 + first.Day;
|
||||
var end = last.Year * 10000 + last.Month * 100 + last.Day;
|
||||
var absences = absenceCache.GetByClassAndRange(className, start, end)
|
||||
@@ -215,9 +222,10 @@ public sealed class StudentAttendanceCalendarService(
|
||||
|
||||
var first = options.NormalizedStartMonth;
|
||||
var last = first.AddMonths(options.NormalizedMonthCount).AddDays(-1);
|
||||
var matchName = $"{student.FirstName} {student.LastName}";
|
||||
var rosterName = rosterCache.GetByClass(className)
|
||||
.FirstOrDefault(r => UntisNameMatching.NamesMatch(r.DisplayName, student.FullName))?.DisplayName
|
||||
?? student.FullName;
|
||||
.FirstOrDefault(r => UntisNameMatching.NamesMatch(r.DisplayName, matchName))?.DisplayName
|
||||
?? matchName;
|
||||
var start = first.Year * 10000 + first.Month * 100 + first.Day;
|
||||
var end = last.Year * 10000 + last.Month * 100 + last.Day;
|
||||
var absences = absenceCache.GetByClassAndRange(className, start, end)
|
||||
|
||||
Reference in New Issue
Block a user