import { NextRequest, NextResponse } from "next/server"; import { z } from "zod"; import { prisma } from "@/lib/db"; import { phaseInclude } from "@/lib/queries"; const createPhaseSchema = z.object({ name: z.string().min(1).max(120), durationYears: z.number().int().min(1).max(80), inflationRate: z.number().min(-20).max(50).nullable().optional(), incomeMode: z.enum(["PER_PERSON", "HOUSEHOLD"]).default("HOUSEHOLD"), }); // Fuegt eine neue Lebensabschnittsphase am Ende der Phasenkette eines Plans an // (TDD Kapitel 3: Phasen werden chronologisch aneinandergereiht). export async function POST( request: NextRequest, { params }: { params: Promise<{ planId: string }> } ) { const { planId } = await params; const body = await request.json(); const parsed = createPhaseSchema.safeParse(body); if (!parsed.success) { return NextResponse.json({ error: parsed.error.flatten() }, { status: 400 }); } const plan = await prisma.plan.findUnique({ where: { id: planId } }); if (!plan) { return NextResponse.json({ error: "Plan nicht gefunden." }, { status: 404 }); } const lastPhase = await prisma.phase.findFirst({ where: { planId }, orderBy: { sequenceNumber: "desc" }, include: { incomeEntries: true, expenseEntries: true }, }); const nextSequence = (lastPhase?.sequenceNumber ?? 0) + 1; // Einkommen und Ausgaben werden 1:1 aus der letzten Phase uebernommen (manuell // anpassbar), damit man sie nicht bei jeder neuen Phase erneut eintippen muss. const phase = await prisma.phase.create({ data: { planId, sequenceNumber: nextSequence, name: parsed.data.name, durationYears: parsed.data.durationYears, inflationRate: parsed.data.inflationRate ?? null, incomeMode: lastPhase?.incomeMode ?? parsed.data.incomeMode, incomeEntries: lastPhase ? { create: lastPhase.incomeEntries.map((e) => ({ personId: e.personId, label: e.label, amount: e.amount, })), } : undefined, expenseEntries: lastPhase ? { create: lastPhase.expenseEntries.map((e) => ({ label: e.label, amount: e.amount })), } : undefined, }, include: phaseInclude, }); return NextResponse.json({ phase }, { status: 201 }); }