Add shared export infrastructure

This commit is contained in:
2026-08-18 21:21:56 +02:00
parent 41bf2c0756
commit 26461bd2f2
13 changed files with 336 additions and 63 deletions
@@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.Input;
using LehrerApp.Core.Interfaces;
using LehrerApp.Core.Models;
using LehrerApp.Core.Services;
using LehrerApp.Desktop.Services;
using System.Collections.ObjectModel;
using System.Globalization;
@@ -519,6 +520,7 @@ public class TimeEntryListItem(TimeEntry model, string? taskTitle)
public class CategoryTimeSummary(string category, int minutes, double barFraction)
{
public string Category { get; } = category;
public int Minutes { get; } = minutes;
public string MinutesDisplay { get; } = $"{minutes} min";
public double BarFraction { get; } = barFraction;
}
@@ -619,6 +621,20 @@ public partial class WorkloadEvaluationViewModel : ObservableObject
public ObservableCollection<GroupTimeSummary> GroupSummaries { get; } = [];
public string TotalMinutesDisplay { get; private set; } = "0 min";
public string RequiredVsActualDisplay { get; private set; } = "";
public string ExportSuggestedFileName
{
get
{
if (PeriodMode == SchoolYearMode)
return $"Arbeitszeitauswertung_Schuljahr_{SelectedYear}-{SelectedYear + 1}.csv";
var month = MonthOptions.IndexOf(SelectedMonth) + 1;
return $"Arbeitszeitauswertung_{SelectedYear}-{month:00}.csv";
}
}
private DateOnly _periodFrom;
private DateOnly _periodTo;
private int _totalMinutes;
public WorkloadEvaluationViewModel(ITimeEntryRepository entries, IGroupRepository groups,
WorkloadSettingsService workloadSettings, SchoolYearService schoolYear)
@@ -671,6 +687,8 @@ public partial class WorkloadEvaluationViewModel : ObservableObject
private void Refresh()
{
var (from, to) = CurrentPeriod();
_periodFrom = from;
_periodTo = to;
var periodEntries = _entries.GetByDateRange(from, to);
var groupNames = _groups.GetAll(includeInactive: true).ToDictionary(g => g.Id, g => g.Name);
@@ -698,6 +716,7 @@ public partial class WorkloadEvaluationViewModel : ObservableObject
}
var totalMinutes = periodEntries.Sum(e => e.DurationMinutes);
_totalMinutes = totalMinutes;
TotalMinutesDisplay = $"{totalMinutes} min ({(totalMinutes / 60.0).ToString("0.#", CultureInfo.InvariantCulture)} h)";
// Pflichtstunden-Abgleich (6.3.2): auf die Anzahl Wochen im Zeitraum hochgerechnet.
@@ -721,12 +740,52 @@ public partial class WorkloadEvaluationViewModel : ObservableObject
OnPropertyChanged(nameof(TotalMinutesDisplay));
OnPropertyChanged(nameof(RequiredVsActualDisplay));
OnPropertyChanged(nameof(ExportSuggestedFileName));
}
public string ExportCsv()
{
var germanCulture = CultureInfo.GetCultureInfo("de-DE");
var csv = new CsvBuilder()
.AddRow("Arbeitszeitauswertung")
.AddRow("Zeitraum", _periodFrom.ToString("dd.MM.yyyy", germanCulture),
_periodTo.ToString("dd.MM.yyyy", germanCulture))
.AddRow("Gesamtzeit (Minuten)", _totalMinutes)
.AddRow("Gesamtzeit (Stunden)", (_totalMinutes / 60.0).ToString("0.##", germanCulture));
if (_workloadSettings.RequiredWeeklyHours > 0)
{
var weeks = (_periodTo.DayNumber - _periodFrom.DayNumber + 1) / 7.0;
var requiredHours = _workloadSettings.RequiredWeeklyHours * weeks;
var actualHours = _totalMinutes / 60.0;
csv.AddRow("Pflichtstunden pro Woche",
_workloadSettings.RequiredWeeklyHours.ToString("0.##", germanCulture))
.AddRow("Sollzeit (Stunden)", requiredHours.ToString("0.##", germanCulture))
.AddRow("Abweichung (Stunden)", (actualHours - requiredHours).ToString("0.##", germanCulture));
}
csv.AddBlankRow()
.AddRow("Nach Kategorie")
.AddRow("Kategorie", "Minuten", "Stunden");
foreach (var summary in CategorySummaries)
csv.AddRow(summary.Category, summary.Minutes,
(summary.Minutes / 60.0).ToString("0.##", germanCulture));
csv.AddBlankRow()
.AddRow("Nach Gruppe")
.AddRow("Gruppe", "Minuten", "Stunden");
foreach (var summary in GroupSummaries)
csv.AddRow(summary.GroupName, summary.Minutes,
(summary.Minutes / 60.0).ToString("0.##", germanCulture));
return csv.ToString();
}
}
public class GroupTimeSummary(string groupName, int minutes, double barFraction)
{
public string GroupName { get; } = groupName;
public int Minutes { get; } = minutes;
public string MinutesDisplay { get; } = $"{minutes} min";
public double BarFraction { get; } = barFraction;
}