feat: add student master data import

This commit is contained in:
2026-08-17 13:12:03 +02:00
parent 9286bfa3b5
commit 37f4fee574
18 changed files with 2359 additions and 13 deletions
@@ -1,3 +1,71 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using LehrerApp.Core.Importing;
using LehrerApp.Core.Services;
using LehrerApp.Desktop.Services;
using LehrerApp.Desktop.ViewModels.Students;
using Microsoft.Extensions.DependencyInjection;
namespace LehrerApp.Desktop.Views.Students;
public partial class StudentListView : UserControl { public StudentListView() => InitializeComponent(); }
public partial class StudentListView : UserControl
{
private const int MaximumImportFileSize = 20 * 1024 * 1024;
public StudentListView() => InitializeComponent();
private async void OnImportClick(object? sender, RoutedEventArgs e)
{
var owner = TopLevel.GetTopLevel(this) as Window;
if (owner is null || DataContext is not StudentListViewModel list) return;
var service = App.Services.GetRequiredService<StudentImportService>();
var patterns = service.SupportedExtensions.Select(extension => $"*{extension}").ToArray();
var files = await owner.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = "Schüler-Stammdaten importieren",
AllowMultiple = false,
FileTypeFilter =
[
new FilePickerFileType("Unterstützte Schülerlisten")
{
Patterns = patterns.Length > 0 ? patterns : ["*.csv"],
},
],
});
if (files.Count == 0) return;
try
{
await using var source = await files[0].OpenReadAsync();
if (source.CanSeek && source.Length > MaximumImportFileSize)
throw new InvalidDataException("Die Importdatei ist größer als 20 MB.");
using var buffer = new MemoryStream();
await source.CopyToAsync(buffer);
if (buffer.Length > MaximumImportFileSize)
throw new InvalidDataException("Die Importdatei ist größer als 20 MB.");
var importFile = new ImportFile(files[0].Name, buffer.ToArray());
var preview = await Task.Run(async () =>
await service.AnalyzeAsync(importFile).ConfigureAwait(false));
var dialogVm = new StudentImportDialogViewModel(service, preview, files[0].Name);
var dialog = new StudentImportDialog { DataContext = dialogVm };
if (!await dialog.ShowDialog<bool>(owner)) return;
list.LoadStudents();
var result = dialogVm.Result!;
App.Services.GetRequiredService<NotificationService>().ShowSuccess(
$"Import abgeschlossen: {result.CreatedStudents} neu, {result.UpdatedStudents} ergänzt, "
+ $"{result.CreatedMemberships} Gruppenzuordnungen.");
}
catch (Exception ex) when (ex is ImportFormatException
or InvalidDataException
or IOException
or UnauthorizedAccessException)
{
App.Services.GetRequiredService<NotificationService>().ShowError(ex.Message);
}
}
}