feat: Teilnehmerlisten in Lerngruppen importieren

This commit is contained in:
2026-08-18 00:44:07 +02:00
parent cdac335ad1
commit 99efa3a0fe
11 changed files with 489 additions and 79 deletions
@@ -305,6 +305,67 @@ public sealed class StudentImportServiceTests
Assert.Equal(ownClass.Id, Assert.Single(preview.GroupAssignments).AutomaticGroupId);
}
[Fact]
public async Task Apply_ExpliziteZielgruppeIgnoriertHeimatklasseUndVervollstaendigtTeilnehmerliste()
{
var repository = new InMemoryStudentRepository();
var target = new LearningGroup { Name = "Mathematik 10", IsActive = true };
var groups = new InMemoryGroupRepository([target]);
var memberships = new InMemoryGroupMembershipRepository();
var service = Service(repository,
[
new ImportedStudent
{
FirstName = "Max", LastName = "Beispiel", GroupName = "10c",
},
], groups, memberships);
var preview = await service.AnalyzeAsync(File(), target.Id);
var result = await service.ApplyAsync(preview);
Assert.True(preview.CanApply);
Assert.Equal(target.Id, preview.TargetGroupId);
Assert.Equal(target.Id, Assert.Single(preview.GroupAssignments).AutomaticGroupId);
Assert.Equal(1, result.CreatedStudents);
Assert.Equal(1, result.CreatedMemberships);
Assert.Equal(target.Id, Assert.Single(memberships.Memberships).GroupId);
}
[Fact]
public async Task Analyze_ExpliziteZielgruppeErkenntBereitsZugeordnetenNamensgleichenSchueler()
{
var existing = new Student { FirstName = "Max", LastName = "Beispiel" };
var repository = new InMemoryStudentRepository([existing]);
var target = new LearningGroup { Name = "Mathematik 10", IsActive = true };
var groups = new InMemoryGroupRepository([target]);
var memberships = new InMemoryGroupMembershipRepository();
memberships.Save(new GroupMembership { StudentId = existing.Id, GroupId = target.Id });
var service = Service(repository,
[new ImportedStudent { FirstName = "Max", LastName = "Beispiel" }],
groups, memberships);
var preview = await service.AnalyzeAsync(File(), target.Id);
Assert.Empty(preview.Conflicts);
var resolution = Assert.Single(preview.Entries).AutomaticResolution;
Assert.Equal(StudentImportResolutionKind.UseExisting, resolution?.Kind);
Assert.Equal(existing.Id, resolution?.ExistingStudentId);
}
[Fact]
public async Task Analyze_ArchivierteZielgruppeVerhindertImport()
{
var target = new LearningGroup { Name = "Alter Kurs", IsActive = false };
var service = Service(new InMemoryStudentRepository(),
[new ImportedStudent { FirstName = "Max", LastName = "Beispiel" }],
new InMemoryGroupRepository([target]));
var preview = await service.AnalyzeAsync(File(), target.Id);
Assert.False(preview.CanApply);
Assert.Contains(preview.Messages, message => message.Code == "student.target-group.unavailable");
}
private static StudentImportService Service(
InMemoryStudentRepository repository,
IReadOnlyList<ImportedStudent> imported,