import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { prisma } from "@/lib/db"; import { getOwnedScenario } from "@/lib/queries"; import { getCurrentUserId } from "@/lib/session"; const copySchema = z.object({ name: z.string().min(1).max(120) }); // Erstellt ein neues Szenario als vollstaendige Kopie eines bestehenden. Das Original wird // zum Elternteil -- damit haengt der Baum in der Seitenleiste und der Diff hat seine Basis. // Jede kopierte Phase/jedes kopierte Element traegt einen Herkunfts-Verweis auf sein // Gegenstueck im Original; darauf beruht die Abweichungs-Markierung im UI. 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 parsed = copySchema.safeParse(await request.json()); if (!parsed.success) return NextResponse.json({ error: "Ungueltige Eingabe." }, { status: 400 }); const source = await getOwnedScenario(scenarioId, userId); if (!source) return NextResponse.json({ error: "Ursprungs-Szenario nicht gefunden." }, { status: 404 }); const newId = await prisma.$transaction(async (tx) => { const created = await tx.scenario.create({ data: { planId: source.planId, name: parsed.data.name, isBase: false, parentScenarioId: source.id, householdType: source.householdType, inflationRateDefault: source.inflationRateDefault, initialCash: source.initialCash, startYear: source.startYear, persons: { create: source.persons.map((p) => ({ role: p.role, name: p.name, age: p.age, retirementAge: p.retirementAge, })), }, }, }); // Phasen kopieren (alte -> neue Id merken, fuer die Werte-Zuordnung). const phaseIdMap = new Map(); for (const phase of source.phases) { const p = await tx.phase.create({ data: { scenarioId: created.id, sequenceNumber: phase.sequenceNumber, name: phase.name, durationYears: phase.durationYears, cashTransition: phase.cashTransition ?? undefined, sourcePhaseId: phase.id, }, }); phaseIdMap.set(phase.id, p.id); } // Elemente inkl. Phasen- und Uebergangswerten kopieren. for (const el of source.elements) { const newEl = await tx.financialElement.create({ data: { scenarioId: created.id, category: el.category, name: el.name, ownerRole: el.ownerRole, orderIndex: el.orderIndex, sourceElementId: el.id, }, }); for (const pv of el.phaseValues) { const phaseId = phaseIdMap.get(pv.phaseId); if (!phaseId) continue; await tx.elementPhaseValue.create({ data: { elementId: newEl.id, phaseId, data: pv.data as object }, }); } for (const tv of el.transitionValues) { const fromPhaseId = phaseIdMap.get(tv.fromPhaseId); if (!fromPhaseId) continue; await tx.elementTransitionValue.create({ data: { elementId: newEl.id, fromPhaseId, data: tv.data as object }, }); } } return created.id; }); return NextResponse.json({ scenarioId: newId }, { status: 201 }); }