KI-gestützte Planungsunterstützung (4.5.9) + Kompetenzkatalog-Import (8.1.2)
KI-Unterstützung: neuer Einstellungen-Tab (Anmeldung, Guthaben) und Button im Planungs-Tab, der Einheiten+Stunden als JSON an ein neues PHP-Backend (ai-backend/) sendet und die Antwort als prüfbare Vorschlagsliste zurückbringt. Provider-Aufruf, Guthabenverwaltung und Abrechnung nach echten Token-Kosten laufen serverseitig, der Desktop-Client sieht nie einen LLM-API-Key. Zentral abgesichert: eine von der KI zurückgegebene Stunden-Id, die zu keiner echten Lesson der Einheit passt, wird nie als Update übernommen, sondern immer als neue Stunde behandelt. Kompetenzkatalog-Import (8.1.2): JSON-Export/Import für Kompetenzkataloge.
This commit is contained in:
@@ -1,11 +1,33 @@
|
||||
using LehrerApp.Core.Interfaces;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Desktop.Services;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
// Einfache In-Memory-Fakes der Repository-Schnittstellen, damit ViewModel-Tests ohne echte
|
||||
// LiteDB-Anbindung laufen. Bewusst schlank gehalten: nur was die getesteten ViewModels brauchen.
|
||||
|
||||
public static class TestSupport
|
||||
{
|
||||
/// Für Tests, die eine echte AiSettingsService-Instanz brauchen (dateibasiert wie
|
||||
/// PeriodScheduleService & Co.) — eigenes Temp-Verzeichnis je Aufruf, damit Tests sich nicht
|
||||
/// gegenseitig über dieselbe ai-settings.json/ai-token.key stören.
|
||||
public static AiSettingsService BuildAiSettingsService()
|
||||
{
|
||||
var tempPath = Path.Combine(Path.GetTempPath(), $"lehrerapp-aisettings-tests-{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return new AiSettingsService(tempPath);
|
||||
}
|
||||
|
||||
/// Für Tests, die nur einen validen AiPlanningService zum Durchreichen brauchen (z.B. weil
|
||||
/// SettingsViewModel/PlanningTabViewModel ihn im Konstruktor verlangen), nicht seine eigentliche
|
||||
/// Funktionalität testen — leere Fakes genügen, es wird kein echter HTTP-Aufruf ausgelöst,
|
||||
/// solange AiSettingsService.IsLoggedIn false ist.
|
||||
public static AiPlanningService BuildAiPlanningService() => new(
|
||||
new HttpClient(), new FakeLessons(), new FakeGroups([]), new FakeSubjects([]),
|
||||
new FakeCompetencyDomains(), new FakeAlternativeLessonPaths([]));
|
||||
}
|
||||
|
||||
public class FakeStudents(List<Student> all) : IStudentRepository
|
||||
{
|
||||
private readonly Dictionary<Guid, StudentReferenceSummary> _references = [];
|
||||
@@ -209,11 +231,20 @@ public class FakeSubjects(List<Subject> all) : ISubjectRepository
|
||||
|
||||
public class FakeCompetencyDomains : ICompetencyDomainRepository
|
||||
{
|
||||
public List<CompetencyDomain> GetBySubjectAndGrade(Guid subjectId, int gradeLevel) => [];
|
||||
public CompetencyDomain? GetById(Guid id) => null;
|
||||
public void Save(CompetencyDomain domain) { }
|
||||
public void Delete(Guid id) { }
|
||||
public void DeleteBySubjectAndGrade(Guid subjectId, int gradeLevel) { }
|
||||
private readonly List<CompetencyDomain> _all = [];
|
||||
public void Add(CompetencyDomain d) => _all.Add(d);
|
||||
public List<CompetencyDomain> GetBySubjectAndGrade(Guid subjectId, int gradeLevel) =>
|
||||
_all.Where(d => d.SubjectId == subjectId && d.GradeLevel == gradeLevel).ToList();
|
||||
public CompetencyDomain? GetById(Guid id) => _all.FirstOrDefault(d => d.Id == id);
|
||||
public void Save(CompetencyDomain domain) { _all.RemoveAll(d => d.Id == domain.Id); _all.Add(domain); }
|
||||
public void Delete(Guid id) => _all.RemoveAll(d => d.Id == id);
|
||||
public void DeleteBySubjectAndGrade(Guid subjectId, int gradeLevel) =>
|
||||
_all.RemoveAll(d => d.SubjectId == subjectId && d.GradeLevel == gradeLevel);
|
||||
public void ReplaceForSubjectAndGrade(Guid subjectId, int gradeLevel, List<CompetencyDomain> domains)
|
||||
{
|
||||
DeleteBySubjectAndGrade(subjectId, gradeLevel);
|
||||
_all.AddRange(domains);
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeShorthandCodes(List<ShorthandCode> all) : IShorthandCodeRepository
|
||||
|
||||
Reference in New Issue
Block a user