feat: add seating plans for learning groups

This commit is contained in:
2026-08-17 01:01:40 +02:00
parent fbf70df439
commit fe36f51886
19 changed files with 771 additions and 6 deletions
+14
View File
@@ -60,6 +60,20 @@ public class FakeMemberships(List<GroupMembership> all) : IGroupMembershipReposi
public void Delete(Guid id) => all.RemoveAll(m => m.Id == id);
}
public class FakeSeatingPlans(List<SeatingPlan>? initial = null) : ISeatingPlanRepository
{
private readonly List<SeatingPlan> _all = initial ?? [];
public SeatingPlan? GetById(Guid id) => _all.FirstOrDefault(p => p.Id == id);
public List<SeatingPlan> GetByGroup(Guid groupId) =>
_all.Where(p => p.GroupId == groupId).OrderBy(p => p.Name).ToList();
public void Save(SeatingPlan plan)
{
_all.RemoveAll(p => p.Id == plan.Id);
_all.Add(plan);
}
public void Delete(Guid id) => _all.RemoveAll(p => p.Id == id);
}
public class FakeSessions(List<ParticipationSession> all) : IParticipationSessionRepository
{
public List<ParticipationSession> GetByGroup(Guid groupId) => all.Where(s => s.GroupId == groupId).ToList();
@@ -24,7 +24,8 @@ public sealed class GroupDetailViewModelTests
new PlanningTabViewModel(new FakeUnits(), new FakeLessons(), groups, subjects,
new FakeCompetencyDomains(), TestSupport.BuildAiSettingsService()),
new CompetencyOverviewTabViewModel(new FakeUnits(), exams, new FakeResults(),
new FakeCompetencyDomains(), students, new CompetencyAnalysisService()));
new FakeCompetencyDomains(), students, new CompetencyAnalysisService()),
new SeatingPlanTabViewModel(new FakeSeatingPlans(), students, memberships));
vm.LoadGroup(group.Id);
vm.SelectedExam = vm.Exams.First(e => e.Id == exam.Id);
@@ -24,13 +24,23 @@ public sealed class PersonalDataExportServiceTests
var documentation = new FakeDocumentation();
documentation.Add(new Documentation { StudentId = studentId, Title = "Elterngespräch" });
var service = new PersonalDataExportService(students, groups, memberships, grades, results, entries, documentation);
var seatingPlans = new FakeSeatingPlans([
new SeatingPlan
{
GroupId = groupId, Name = "Standard", Room = "B204",
Assignments = [new SeatAssignment { Row = 1, Column = 2, StudentId = studentId }],
},
]);
var service = new PersonalDataExportService(students, groups, memberships, grades, results, entries,
documentation, seatingPlans);
var json = service.ExportAsJson(studentId);
Assert.Contains("Anna", json);
Assert.Contains("Elterngespräch", json);
Assert.Contains("\"Value\": \"2\"", json);
Assert.Contains("\"Sitzplan\": \"Standard\"", json);
Assert.Contains("\"Reihe\": 2", json);
}
[Fact]
@@ -38,7 +48,8 @@ public sealed class PersonalDataExportServiceTests
{
var service = new PersonalDataExportService(
new FakeStudents([]), new FakeGroups([]), new FakeMemberships([]),
new FakeGrades(), new FakeResults(), new FakeEntries(), new FakeDocumentation());
new FakeGrades(), new FakeResults(), new FakeEntries(), new FakeDocumentation(),
new FakeSeatingPlans());
Assert.Throws<InvalidOperationException>(() => service.ExportAsJson(Guid.NewGuid()));
}
@@ -0,0 +1,51 @@
using LehrerApp.Core.Models;
using LehrerApp.Desktop.ViewModels.Groups;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class SeatingPlanViewModelTests
{
[Fact]
public void AuswahlEinesBereitsZugeordnetenSchuelers_VerschiebtIhnAufDenNeuenPlatz()
{
var groupId = Guid.NewGuid();
var student = new Student { FirstName = "Anna", LastName = "Beispiel" };
var students = new FakeStudents([student]);
var memberships = new FakeMemberships([
new GroupMembership { GroupId = groupId, StudentId = student.Id },
]);
var plan = new SeatingPlan
{
GroupId = groupId,
Name = "Standard",
Rows = 1,
Columns = 2,
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
};
var plans = new FakeSeatingPlans([plan]);
var vm = new SeatingPlanTabViewModel(plans, students, memberships);
vm.Initialize(groupId, isReadOnly: false);
vm.Seats[1].SelectedOption = vm.StudentOptions.Single(o => o.StudentId == student.Id);
Assert.Null(vm.Seats[0].SelectedOption.StudentId);
var assignment = Assert.Single(plans.GetById(plan.Id)!.Assignments);
Assert.Equal((0, 1, student.Id), (assignment.Row, assignment.Column, assignment.StudentId));
}
[Fact]
public void ArchivierteGruppe_DeaktiviertSitzplatzbearbeitung()
{
var groupId = Guid.NewGuid();
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1 };
var vm = new SeatingPlanTabViewModel(
new FakeSeatingPlans([plan]), new FakeStudents([]), new FakeMemberships([]));
vm.Initialize(groupId, isReadOnly: true);
Assert.False(vm.IsEditable);
Assert.False(vm.Seats.Single().CanEdit);
Assert.False(vm.AddPlanCommand.CanExecute(null));
}
}