import { Prisma } from "@/generated/prisma/client"; import { prisma } from "@/lib/db"; import { cashTransitionSchema, phaseDataSchema, transitionDataSchema } from "@/lib/elements"; import type { CashTransitionData, PhaseData, TransitionData } from "@/lib/elements"; import type { PlanInput } from "@/lib/types"; export const planInclude = { persons: { orderBy: { role: "asc" } }, phases: { orderBy: { sequenceNumber: "asc" } }, elements: { orderBy: { orderIndex: "asc" }, include: { phaseValues: true, transitionValues: true }, }, } satisfies Prisma.ScenarioInclude; export type PlanWithRelations = Prisma.ScenarioGetPayload<{ include: typeof planInclude }>; function parsePhaseData(raw: unknown): PhaseData { const parsed = phaseDataSchema.safeParse(raw); return parsed.success ? parsed.data : {}; } function parseTransitionData(raw: unknown): TransitionData { const parsed = transitionDataSchema.safeParse(raw); return parsed.success ? parsed.data : {}; } function parseCashTransition(raw: unknown): CashTransitionData { const parsed = cashTransitionSchema.safeParse(raw); return parsed.success ? parsed.data : {}; } // Wandelt ein Szenario (DB) in die berechenbare Einheit (PlanInput) um. export function toPlanInput(plan: PlanWithRelations): PlanInput { return { id: plan.id, name: plan.name, householdType: plan.householdType, inflationRateDefault: plan.inflationRateDefault, initialCash: plan.initialCash, startYear: plan.startYear, persons: plan.persons.map((p) => ({ id: p.id, role: p.role, name: p.name, age: p.age, retirementAge: p.retirementAge, })), phases: plan.phases.map((phase) => ({ id: phase.id, sequenceNumber: phase.sequenceNumber, name: phase.name, durationYears: phase.durationYears, cashTransition: parseCashTransition(phase.cashTransition), sourcePhaseId: phase.sourcePhaseId, })), elements: plan.elements.map((e) => { const phaseValues: Record = {}; for (const pv of e.phaseValues) phaseValues[pv.phaseId] = parsePhaseData(pv.data); const transitionValues: Record = {}; for (const tv of e.transitionValues) transitionValues[tv.fromPhaseId] = parseTransitionData(tv.data); return { id: e.id, category: e.category, name: e.name, ownerRole: e.ownerRole, orderIndex: e.orderIndex, phaseValues, transitionValues, sourceElementId: e.sourceElementId, }; }), }; } // --- Ownership-Abfragen. Der Eigentümer hängt neu am PLAN; Szenario/Phase/Element // erben ihn über die Kette Scenario -> Plan -> User. --- // Lädt ein Szenario inkl. Profil + Phasen + Elemente, nur wenn es dem Benutzer gehört. export async function getOwnedScenario(scenarioId: string, userId: string) { return prisma.scenario.findFirst({ where: { id: scenarioId, plan: { userId } }, include: planInclude, }); } // Wie oben, zusätzlich mit den Kopfdaten (Plan, Basis-Flag, Elternteil). export async function getOwnedScenarioWithMeta(scenarioId: string, userId: string) { return prisma.scenario.findFirst({ where: { id: scenarioId, plan: { userId } }, include: { ...planInclude, plan: true }, }); } // Lädt einen Plan (Behälter) inkl. Szenario-Kopfdaten. export async function getOwnedPlan(planId: string, userId: string) { return prisma.plan.findFirst({ where: { id: planId, userId }, include: { scenarios: { orderBy: { createdAt: "asc" } } }, }); } // Lädt eine Phase (Basisdaten), aber nur wenn sie dem Benutzer gehört. export async function getOwnedPhase(phaseId: string, userId: string) { return prisma.phase.findFirst({ where: { id: phaseId, scenario: { plan: { userId } } }, }); } // Lädt ein Element (Basisdaten), aber nur wenn es dem Benutzer gehört. export async function getOwnedElement(elementId: string, userId: string) { return prisma.financialElement.findFirst({ where: { id: elementId, scenario: { plan: { userId } } }, }); }