Neue Bildungspläne wachsen je Fach klassenstufenweise hoch, sodass Kurse abhängig vom Einschulungsjahr entweder dem alten oder dem neuen Bildungsplan folgen. CompetencyCatalogVersion (Fach + Name + IsDefault) macht das abbildbar: CompetencyDomain bekommt eine VersionId, Kurse wählen über LearningGroup.CompetencyCatalogVersionId (null = Standardversion des Fachs) welche Version gilt. Migration legt für bestehende Kataloge automatisch eine Standardversion an, damit alte Datenbanken unverändert weiterlaufen. MCP: neue Tools für Versions-CRUD (get/create/update/delete_competency_plan_version, update_group_competency_version), get_competency_catalog/create_competency_domain um optionalen versionId-Parameter erweitert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
135 lines
4.8 KiB
C#
135 lines
4.8 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using LehrerApp.Core.Interfaces;
|
|
using LehrerApp.Core.Models;
|
|
using LehrerApp.Core.Services;
|
|
using LehrerApp.Data;
|
|
using LehrerApp.Desktop.Services;
|
|
using LehrerApp.Desktop.ViewModels.Planning;
|
|
using LehrerApp.Sync;
|
|
using LehrerApp.Sync.Crypto;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Security.Cryptography;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace LehrerApp.Desktop.ViewModels.Settings;
|
|
|
|
public partial class SettingsViewModel
|
|
{
|
|
// ── JSON Import / Export ──────────────────────────────────────────────────
|
|
|
|
public CompetencyCatalogImportPreview? PrepareCatalogImport(string json)
|
|
{
|
|
if (CatalogSubject is null)
|
|
{
|
|
CatalogValidation = "Bitte zuerst ein Fach auswählen.";
|
|
return null;
|
|
}
|
|
if (CatalogVersion is null)
|
|
{
|
|
CatalogValidation = "Bitte zuerst eine Version auswählen.";
|
|
return null;
|
|
}
|
|
try
|
|
{
|
|
CatalogValidation = "";
|
|
return _catalogImport.Analyze(
|
|
json, CatalogSubject.Id, CatalogSubject.Name, CatalogGradeLevel, CatalogVersion.Id);
|
|
}
|
|
catch (InvalidDataException ex)
|
|
{
|
|
CatalogValidation = ex.Message;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public void ApplyCatalogImport(CompetencyCatalogImportPreview preview,
|
|
CompetencyCatalogImportMode mode, IReadOnlySet<string> useImportedConflicts)
|
|
{
|
|
_catalogImport.Apply(preview, mode, useImportedConflicts);
|
|
LoadCatalog();
|
|
CatalogValidation = mode == CompetencyCatalogImportMode.Merge
|
|
? "Kompetenzkatalog wurde sicher zusammengeführt."
|
|
: "Kompetenzkatalog wurde vollständig ersetzt.";
|
|
}
|
|
|
|
public string ExportCatalog()
|
|
=> SerializeCatalog(CatalogGradeLevel);
|
|
|
|
public CompetencyCatalogImportPreview? PrepareCatalogCopy(int targetGradeLevel)
|
|
{
|
|
if (CatalogSubject is null)
|
|
{
|
|
CatalogValidation = "Bitte zuerst ein Fach auswählen.";
|
|
return null;
|
|
}
|
|
if (Domains.Count == 0)
|
|
{
|
|
CatalogValidation = "Der ausgewählte Katalog enthält keine Bereiche.";
|
|
return null;
|
|
}
|
|
if (targetGradeLevel is < 1 or > 13 || targetGradeLevel == CatalogGradeLevel)
|
|
{
|
|
CatalogValidation = "Bitte eine andere Zielklassenstufe zwischen 1 und 13 auswählen.";
|
|
return null;
|
|
}
|
|
|
|
if (CatalogVersion is null)
|
|
{
|
|
CatalogValidation = "Bitte zuerst eine Version auswählen.";
|
|
return null;
|
|
}
|
|
|
|
CatalogValidation = "";
|
|
return _catalogImport.Analyze(SerializeCatalog(targetGradeLevel), CatalogSubject.Id,
|
|
CatalogSubject.Name, targetGradeLevel, CatalogVersion.Id);
|
|
}
|
|
|
|
public void SetCatalogCopyStatus(int targetGradeLevel) =>
|
|
CatalogValidation = $"Kompetenzkatalog wurde in Klassenstufe {targetGradeLevel} kopiert.";
|
|
|
|
private string SerializeCatalog(int gradeLevel)
|
|
{
|
|
var dto = new CatalogDto
|
|
{
|
|
Subject = CatalogSubject?.Name ?? "",
|
|
GradeLevel = gradeLevel,
|
|
Domains = Domains.Select(d => new DomainDto
|
|
{
|
|
Name = d.Name,
|
|
Code = d.Code,
|
|
Competencies = d.Items.Select(i => new CompetencyDto
|
|
{
|
|
Code = i.Code,
|
|
Description = i.Description,
|
|
}).ToList(),
|
|
}).ToList(),
|
|
};
|
|
return JsonSerializer.Serialize(dto, new JsonSerializerOptions { WriteIndented = true });
|
|
}
|
|
}
|
|
|
|
// ── JSON DTOs ─────────────────────────────────────────────────────────────────
|
|
|
|
internal class CatalogDto
|
|
{
|
|
[JsonPropertyName("subject")] public string? Subject { get; set; }
|
|
[JsonPropertyName("gradeLevel")] public int GradeLevel { get; set; }
|
|
[JsonPropertyName("domains")] public List<DomainDto>? Domains { get; set; }
|
|
}
|
|
|
|
internal class DomainDto
|
|
{
|
|
[JsonPropertyName("name")] public string? Name { get; set; }
|
|
[JsonPropertyName("code")] public string? Code { get; set; }
|
|
[JsonPropertyName("competencies")] public List<CompetencyDto>? Competencies { get; set; }
|
|
}
|
|
|
|
internal class CompetencyDto
|
|
{
|
|
[JsonPropertyName("code")] public string? Code { get; set; }
|
|
[JsonPropertyName("description")] public string? Description { get; set; }
|
|
}
|