using System.Collections.ObjectModel;
using LehrerApp.Core.Models;
namespace LehrerApp.Core.Importing;
public sealed record ImportedStudentContact
{
public string? Email { get; init; }
public string? MobilePhone { get; init; }
public string? Phone { get; init; }
public string? Street { get; init; }
public string? PostalCode { get; init; }
public string? City { get; init; }
public bool HasData => new[] { Email, MobilePhone, Phone, Street, PostalCode, City }
.Any(value => !string.IsNullOrWhiteSpace(value));
}
/// Formatunabhängige Schülerdaten, die ein konkreter Handler erzeugt.
public sealed record ImportedStudent
{
public required string FirstName { get; init; }
public required string LastName { get; init; }
public DateOnly? DateOfBirth { get; init; }
public Gender? Gender { get; init; }
public string? ExternalId { get; init; }
public string? GroupName { get; init; }
public ImportedStudentContact? Contact { get; init; }
public string? SourceReference { get; init; }
}
public static class StudentImportFormats
{
public static readonly ImportFormatId MasterDataCsv = new("student-master-data.csv");
}
public enum StudentImportResolutionKind { CreateNew, UseExisting, Skip }
public sealed record StudentImportResolution(
StudentImportResolutionKind Kind,
Guid? ExistingStudentId = null);
public sealed record StudentImportEntry(
string Id,
ImportedStudent Student,
StudentImportResolution? AutomaticResolution,
string? ConflictId,
IReadOnlyList FieldsToSupplement);
public sealed record StudentImportGroupAssignment(
string SourceGroupName,
Guid? AutomaticGroupId,
string? ConflictId);
public sealed class StudentImportPreview
{
public ImportFormatId FormatId { get; }
public string FormatName { get; }
public IReadOnlyList Entries { get; }
public IReadOnlyList Messages { get; }
public IReadOnlyList Conflicts { get; }
public IReadOnlyList GroupAssignments { get; }
internal string ExistingStudentsFingerprint { get; }
internal string GroupStateFingerprint { get; }
public bool CanApply =>
Entries.Count > 0 && Messages.All(message => message.Severity != ImportMessageSeverity.Error);
internal StudentImportPreview(
ImportFormatId formatId,
string formatName,
IEnumerable entries,
IEnumerable messages,
IEnumerable conflicts,
IEnumerable groupAssignments,
string existingStudentsFingerprint,
string groupStateFingerprint)
{
FormatId = formatId;
FormatName = formatName;
Entries = ReadOnly(entries);
Messages = ReadOnly(messages);
Conflicts = ReadOnly(conflicts);
GroupAssignments = ReadOnly(groupAssignments);
ExistingStudentsFingerprint = existingStudentsFingerprint;
GroupStateFingerprint = groupStateFingerprint;
}
private static IReadOnlyList ReadOnly(IEnumerable values) =>
new ReadOnlyCollection(values.ToList());
}
public sealed record StudentImportApplyResult(
int CreatedStudents,
int UpdatedStudents,
int MatchedExistingStudents,
int SkippedStudents,
int CreatedMemberships,
IReadOnlyList CreatedStudentIds);