d023534a03
Deploy App / deploy (push) Successful in 1m48s
Version A.B: B automatisch je Bearbeitungssitzung (10-Minuten-Fenster, unveraenderte Staende erzeugen keine), A manuell mit Pflichtkommentar. Eine Version haelt den vollstaendigen Zustand als PlanInput-JSON -- dadurch ist die Versionsauswahl in allen vier Analysewerkzeugen fast kostenlos, bei Monte-Carlo je Szenario einzeln. Wiederherstellen erhaelt die IDs (sonst verlieren Kind-Szenarien ihre Diff-Basis) und legt den Stand selbst als neue Version an. Wo ein Bezug trotzdem bricht, warnt der Dialog vorher namentlich. Statischer Waechter-Test: jeder schreibende Endpunkt loest eine Version aus. Migration gegen echtes Postgres verifiziert. Spezifikation 0.19 (3.8 und 9.28 neu), 25 Tests (139 -> 164). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
74 lines
2.8 KiB
TypeScript
74 lines
2.8 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { z } from "zod";
|
|
import { prisma } from "@/lib/db";
|
|
import { getCurrentUserId } from "@/lib/session";
|
|
import { createMajorVersion } from "@/lib/versioning-db";
|
|
import { isValidMajorComment } from "@/lib/versioning";
|
|
|
|
async function ownedScenario(scenarioId: string, userId: string) {
|
|
return prisma.scenario.findFirst({ where: { id: scenarioId, plan: { userId } } });
|
|
}
|
|
|
|
// Änderungshistorie eines Szenarios, neueste zuerst. Ohne die Snapshots -- die sind je
|
|
// Version zig Kilobyte gross und werden erst beim Anzeigen einzeln geladen.
|
|
export async function GET(_request: NextRequest, { params }: { params: Promise<{ scenarioId: string }> }) {
|
|
const userId = await getCurrentUserId();
|
|
if (!userId) return NextResponse.json({ error: "Nicht authentifiziert." }, { status: 401 });
|
|
const { scenarioId } = await params;
|
|
|
|
const scenario = await ownedScenario(scenarioId, userId);
|
|
if (!scenario) return NextResponse.json({ error: "Szenario nicht gefunden." }, { status: 404 });
|
|
|
|
const rows = await prisma.scenarioVersion.findMany({
|
|
where: { scenarioId },
|
|
orderBy: [{ major: "desc" }, { minor: "desc" }],
|
|
select: {
|
|
id: true,
|
|
major: true,
|
|
minor: true,
|
|
comment: true,
|
|
isMajor: true,
|
|
createdAt: true,
|
|
updatedAt: true,
|
|
createdBy: { select: { username: true } },
|
|
},
|
|
});
|
|
|
|
return NextResponse.json({
|
|
currentMajor: scenario.currentMajor,
|
|
versions: rows.map((r) => ({
|
|
id: r.id,
|
|
major: r.major,
|
|
minor: r.minor,
|
|
comment: r.comment,
|
|
isMajor: r.isMajor,
|
|
createdAt: r.createdAt,
|
|
updatedAt: r.updatedAt,
|
|
author: r.createdBy.username,
|
|
})),
|
|
});
|
|
}
|
|
|
|
const majorSchema = z.object({ comment: z.string().min(3).max(500) });
|
|
|
|
// Legt den aktuellen Stand als HAUPTVERSION fest. Der Kommentar ist Pflicht -- eine
|
|
// Hauptversion ohne Begründung wäre nur eine Zahl.
|
|
export async function POST(request: NextRequest, { params }: { params: Promise<{ scenarioId: string }> }) {
|
|
const userId = await getCurrentUserId();
|
|
if (!userId) return NextResponse.json({ error: "Nicht authentifiziert." }, { status: 401 });
|
|
const { scenarioId } = await params;
|
|
|
|
const scenario = await ownedScenario(scenarioId, userId);
|
|
if (!scenario) return NextResponse.json({ error: "Szenario nicht gefunden." }, { status: 404 });
|
|
|
|
const parsed = majorSchema.safeParse(await request.json());
|
|
if (!parsed.success || !isValidMajorComment(parsed.data.comment)) {
|
|
return NextResponse.json({ error: "Bitte einen Kommentar zur Hauptversion angeben." }, { status: 400 });
|
|
}
|
|
|
|
const ref = await createMajorVersion(scenarioId, userId, parsed.data.comment);
|
|
if (!ref) return NextResponse.json({ error: "Hauptversion konnte nicht angelegt werden." }, { status: 500 });
|
|
|
|
return NextResponse.json({ version: ref }, { status: 201 });
|
|
}
|