V7: Haushalt auf Plan-Ebene, Annahmen bleiben am Szenario
Deploy App / deploy (push) Successful in 1m52s

Haushaltsform, Personen (Name/Alter) und Startjahr wandern vom Szenario
auf den Plan. Das Pensionsalter bleibt szenario-eigen -- es ist der Kern
jedes Frueh-/Spaetpensionierungs-Szenarios.

Neue Tabelle PlanPerson; Person behaelt nur Rolle + Pensionsalter;
Plan bekommt householdType und startYear.

Der Rechenkern bleibt unberuehrt: toPlanInput fuegt beide Ebenen wieder
zu einem unveraenderten PlanInput zusammen. 43 Golden Tests unveraendert.

Nebeneffekt: Ein Ist-Satz trifft jetzt in ALLEN Szenarien dasselbe
Planjahr -- vorher war das nicht garantiert.

Wiederherstellen einer Version setzt nur noch Szenario-Eigenes zurueck.
Profil-Dialog kennzeichnet plan-weite vs. szenario-eigene Felder.

Zwei Tests spielen echte V6-Daten ein und pruefen die Uebernahme.
Spezifikation 0.23 (210 -> 212).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 21:53:12 +02:00
parent 44c6c81f5d
commit ce5f83823f
10 changed files with 290 additions and 51 deletions
+24 -6
View File
@@ -66,18 +66,31 @@ enum ElementCategory {
// Einzelperson eines Szenarios. retirementAge ist das (szenario-eigene) Pensionsalter --
// dadurch sind Frueh-/Spaetpensionierungs-Szenarien moeglich.
// Szenario-EIGENE Angabe zu einer Person. Seit V7 nur noch das Pensionsalter -- es ist der
// Kern jedes Frueh-/Spaetpensionierungs-Szenarios. Name und Alter beschreiben den Haushalt
// und liegen deshalb am Plan (PlanPerson).
model Person {
id String @id @default(cuid())
scenarioId String
scenario Scenario @relation(fields: [scenarioId], references: [id], onDelete: Cascade)
role PersonRole
name String?
age Int
retirementAge Int
@@unique([scenarioId, role])
}
// Eine Person des HAUSHALTS. Gilt fuer alle Szenarien des Plans.
model PlanPerson {
id String @id @default(cuid())
planId String
plan Plan @relation(fields: [planId], references: [id], onDelete: Cascade)
role PersonRole
name String?
age Int
@@unique([planId, role])
}
// Behaelter einer Planung. Traegt selbst KEINE Finanzdaten, nur den Namen und die Szenarien.
model Plan {
id String @id @default(cuid())
@@ -85,11 +98,19 @@ model Plan {
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
name String
// Seit V7 am Plan: Diese Angaben beschreiben den HAUSHALT, nicht eine Planungsvariante.
// Unterscheiden sie sich, ist es ein anderer Plan -- kein anderes Szenario.
householdType HouseholdType
// Kalenderjahr, in dem die Planung beginnt (Jahr 1). Rein fuer die Darstellung --
// die Berechnung rechnet weiterhin in relativen Jahren ab Planbeginn.
startYear Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
scenarios Scenario[]
actuals ActualsSet[]
persons PlanPerson[]
}
// Ein erfasster Stand der WIRKLICHKEIT zu einem Stichtag (Roadmap Nr. 5).
@@ -136,12 +157,9 @@ model Scenario {
parentScenario Scenario? @relation("ScenarioTree", fields: [parentScenarioId], references: [id], onDelete: SetNull)
children Scenario[] @relation("ScenarioTree")
householdType HouseholdType
// Szenario-eigene Annahmen. Haushaltsform, Personen und Startjahr liegen seit V7 am Plan.
inflationRateDefault Float
initialCash Float @default(0)
// Kalenderjahr, in dem die Planung beginnt (Jahr 1). Rein fuer die Darstellung --
// die Berechnung rechnet weiterhin in relativen Jahren ab Planbeginn.
startYear Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt