feat: Planungsideen-Feld je Stunde + persistierter Materialerstellungs-Prompt
CI / build-and-test (push) Canceled after 0s

Lesson bekommt ein neues Freitextfeld PlanningIdeas fuer grobe Ideen vor der
Feinplanung, sichtbar im LessonDialog und als Kontext an die KI-Planung
(Backend + MCP) durchgereicht. LessonPhaseStep.MaterialPrompt speichert den
beim Uebernehmen einer KI-Stunde erzeugten Materialerstellungs-Prompt dauerhaft,
statt ihn nur einmalig im AiAssistDialog anzuzeigen - im Verlaufsplan-Editor
ueber einen neuen Kopieren-Button je Phase erneut nutzbar, auch ueber MCP
lesbar/schreibbar.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 00:41:13 +02:00
co-authored by Claude Sonnet 5
parent 3675b70004
commit 7b660c7152
12 changed files with 141 additions and 15 deletions
@@ -188,11 +188,12 @@ public class LessonPlanTools(
return new WriteResultDto(true, lesson.Id, "Einzelstunde gespeichert.");
}
[Description("Ändert Metadaten einer bestehenden Einzelstunde (Thema, Hausaufgabe, Status, Beginn, Stundennummer) — der Verlaufsplan (Phasen) bleibt unverändert. Nur angegebene Felder werden geändert.")]
[Description("Ändert Metadaten einer bestehenden Einzelstunde (Thema, Hausaufgabe, Planungsideen, Status, Beginn, Stundennummer) — der Verlaufsplan (Phasen) bleibt unverändert. Nur angegebene Felder werden geändert.")]
public async Task<WriteResultDto> UpdateLesson(
[Description("ID der Einzelstunde.")] Guid lessonId,
[Description("Neues Thema. Unverändert lassen: weglassen.")] string? topic = null,
[Description("Neue Hausaufgabe. Unverändert lassen: weglassen.")] string? homework = null,
[Description("Neue Planungsideen (grober Entwurf vor der Feinplanung). Unverändert lassen: weglassen.")] string? planningIdeas = null,
[Description("Neuer Status: Planned, Conducted, Draft, Ready oder Cancelled (ausgefallen, z.B. Exkursion/Feiertag - Alternative zu delete_lesson, wenn die Stunde als Ereignis dokumentiert bleiben soll). Unverändert lassen: weglassen.")] LessonStatus? status = null,
[Description("Neuer Stundenbeginn, Format HH:mm. Unverändert lassen: weglassen.")] TimeOnly? startTime = null,
[Description("Neue Stundennummer. Unverändert lassen: weglassen.")] int? lessonNumber = null,
@@ -204,6 +205,7 @@ public class LessonPlanTools(
var changes = new StringBuilder();
if (topic is not null && topic != lesson.Topic) { changes.AppendLine($"Thema: „{lesson.Topic}“ → „{topic}“"); lesson.Topic = topic; }
if (homework is not null && homework != lesson.Homework) { changes.AppendLine($"Hausaufgabe: „{lesson.Homework}“ → „{homework}“"); lesson.Homework = homework; }
if (planningIdeas is not null && planningIdeas != lesson.PlanningIdeas) { changes.AppendLine($"Planungsideen: „{lesson.PlanningIdeas}“ → „{planningIdeas}“"); lesson.PlanningIdeas = planningIdeas; }
if (status is not null && status != lesson.Status) { changes.AppendLine($"Status: {lesson.Status} → {status}"); lesson.Status = status.Value; }
if (startTime is not null && startTime != lesson.StartTime) { changes.AppendLine($"Beginn: {lesson.StartTime:HH\\:mm} → {startTime:HH\\:mm}"); lesson.StartTime = startTime; }
if (lessonNumber is not null && lessonNumber != lesson.LessonNumber) { changes.AppendLine($"Nr.: {lesson.LessonNumber} → {lessonNumber}"); lesson.LessonNumber = lessonNumber; }
@@ -228,6 +230,7 @@ public class LessonPlanTools(
[Description("Tätigkeit/Sozialform.")] string activity = "",
[Description("Material.")] string material = "",
[Description("Kurzsymbol, z.B. \"AB001->S\".")] string shorthand = "",
[Description("Optionaler, vollständiger Prompt zur Materialerstellung für diese Phase (siehe get_lesson_plans, LessonPhaseDto.MaterialPrompt) - z.B. wenn eine externe KI-Sitzung ihn selbst formuliert hat und er zur Wiederverwendung gespeichert werden soll.")] string? materialPrompt = null,
CancellationToken ct = default)
{
var lesson = lessons.GetById(lessonId);
@@ -240,7 +243,7 @@ public class LessonPlanTools(
var phase = new LessonPhaseStep
{
Name = name, DurationMinutes = durationMinutes, Activity = activity,
Material = material, Shorthand = shorthand,
Material = material, Shorthand = shorthand, MaterialPrompt = materialPrompt,
};
lesson.Phases.Add(phase);
lessons.Save(lesson);
@@ -256,6 +259,7 @@ public class LessonPlanTools(
[Description("Neue Tätigkeit. Unverändert lassen: weglassen.")] string? activity = null,
[Description("Neues Material. Unverändert lassen: weglassen.")] string? material = null,
[Description("Neues Kurzsymbol. Unverändert lassen: weglassen.")] string? shorthand = null,
[Description("Neuer Prompt zur Materialerstellung (siehe get_lesson_plans, LessonPhaseDto.MaterialPrompt). Unverändert lassen: weglassen.")] string? materialPrompt = null,
CancellationToken ct = default)
{
var lesson = lessons.GetById(lessonId);
@@ -269,6 +273,7 @@ public class LessonPlanTools(
if (activity is not null && activity != phase.Activity) { changes.AppendLine($"Tätigkeit: „{phase.Activity}“ → „{activity}“"); phase.Activity = activity; }
if (material is not null && material != phase.Material) { changes.AppendLine($"Material: „{phase.Material}“ → „{material}“"); phase.Material = material; }
if (shorthand is not null && shorthand != phase.Shorthand) { changes.AppendLine($"Kürzel: „{phase.Shorthand}“ → „{shorthand}“"); phase.Shorthand = shorthand; }
if (materialPrompt is not null && materialPrompt != phase.MaterialPrompt) { changes.AppendLine("Materialerstellungs-Prompt geändert."); phase.MaterialPrompt = materialPrompt; }
if (changes.Length == 0)
return new WriteResultDto(true, phase.Id, "Keine Änderung nötig.");
@@ -409,7 +414,7 @@ public class LessonPlanTools(
}
private static LessonDto ToDto(Lesson l) => new(
l.Id, l.UnitId, l.GroupId, l.Date, l.LessonNumber, l.Topic, l.Homework, l.Status, l.Competencies,
l.Phases.Select(p => new LessonPhaseDto(p.Id, p.Name, p.DurationMinutes, p.Activity, p.Material, p.Shorthand)).ToList(),
l.Id, l.UnitId, l.GroupId, l.Date, l.LessonNumber, l.Topic, l.Homework, l.PlanningIdeas, l.Status, l.Competencies,
l.Phases.Select(p => new LessonPhaseDto(p.Id, p.Name, p.DurationMinutes, p.Activity, p.Material, p.Shorthand, p.MaterialPrompt)).ToList(),
l.Attachments.Select(a => new LessonAttachmentDto(a.StorageId, a.FileName, a.SizeBytes)).ToList());
}