Versionierung:
- startet neu bei 0.1; erst eine gesetzte Hauptversion macht daraus 1.0
- Szenario-Liste zeigt die echte Version (z.B. 0.17) statt "1.x", plus
neue Spalte "Phasen"
- Migration 20260724120000_version_zero_start (nur der Default)
Plan-Dashboard:
- Kacheln anklickbar (fuehren in ihren Bereich), neue Kachel "Berichte"
- Plan umbenennen ueber Stift-Symbol
- Ist-Abweichung nennt das Jahr des juengsten Ist-Datensatzes und ist bei
positiver Abweichung gruen statt rot
Szenario-Liste:
- Klick auf die Zeile oeffnet die Matrix (Matrix-Knopf entfaellt)
- je Zeile Kopie (Vorlage frei waehlbar) und Loeschen
- laedt nach einer Loeschung neu (zeigte vorher den alten Stand)
Seitenleiste:
- Szenarien wieder verschachtelt nach Herkunft
- Effektive Werte / Analysen / Berichte buendig zum Knoten "Szenarien"
CSV-Export (neues Modul lib/csv.ts):
- vier Bloecke: Kopf, Lebensphasen, ganze Matrix (Elemente x Phasen inkl.
Uebergangs-Entscheide im Klartext), Jahreswerte
- mit BOM (Excel-Umlaute), Dateiname transliteriert Umlaute
- vorher enthielt die Datei kein einziges finanzielles Element
Grafiken:
- Szenario-Waehler gilt fuer alle drei Grafiken
- BUGFIX Szenario-Vergleich: WealthChart nutzte den Namen als Datenschluessel
-> gleichnamige Szenarien ueberschrieben sich (Legende zeigte beide, Chart
nur eine). Neu die ID; stille Deckelung auf 4 Serien entfaellt
- eigene Legende mit freier Farbwahl je Serie + Erklaerung des Linienstils
- Vermoegensaufteilung neu: gestapelte Flaeche ueber die Planjahre + Ring
fuer die relative Aufteilung zu einem waehlbaren Zeitpunkt
- alle Diagrammfarben aus neuen Theme-Tokens (--chart-1..6, --chart-grid)
Doku-Drift bereinigt: Kapitel 2.1, 3.2.2-3.2.7 und 3.10 beschrieben noch den
Stand vor V7 (Grundprofil am Szenario, parentPlanId, Scenario.startYear,
window.confirm, drei Sidebar-Unterpunkte).
Nebenbei: verstuemmelte Hex-Farbe --danger-soft (warm) repariert, deutsche
Plural-/Umlautfehler in den Uebersichts-Kacheln.
SPEZIFIKATION 0.31. 267 -> 275 Tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der gemeldete 500 kam OHNE JSON-Koerper -- der Client konnte deshalb nur
"Fehler 500" zeigen. Ursache: Der Absturz lag ausserhalb der bisherigen
try/catch-Bloecke. Jetzt liegt der GESAMTE Handler in einem try/catch,
jede Ursache wird protokolliert und im Klartext zurueckgegeben.
Zusaetzlich zwei Risiken entfernt:
- Die verschachtelte Abfrage (Plan -> Szenarien -> Plan -> Personen) war
ein Ringbezug; Szenarien werden jetzt einzeln nachgeladen.
- pdfkit wird ueber einen Resolver geholt, der statischen Import,
.default und createRequire durchprobiert -- unabhaengig davon, wie der
Bundler CJS-Interop aufloest.
Neuer Test mit realistischem Plan (Immobilie, Schuld, AHV, PK, 3a,
Kopie-Szenario) -- laeuft lokal durch, schliesst die Datenform als
Ursache aus. 223 Tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) pdfkit wird als externes CJS-Modul geladen. Je nach Interop kommt der
Konstruktor direkt oder unter .default an -- trifft man die falsche Form,
gelingt der Import, aber `new PDFDocument()` scheitert erst zur Laufzeit
(passt zum gemeldeten 500: unauth. Aufruf gab 401, die Erzeugung 500).
Beide Formen werden jetzt akzeptiert.
2) Die Fusszeile stand unterhalb des Satzspiegels -- pdfkit haengt dafuer
automatisch Seiten an. Ein Bericht mit 6 Inhaltsseiten wurde so auf 18
aufgeblaeht. Unterer Rand wird fuers Schreiben auf 0 gesetzt; ein Test
prueft jetzt die Seitenzahl im FERTIGEN PDF, nicht davor.
3) Rendern und Speichern melden ihre Ursache statt eines nackten 500.
Spezifikation unveraendert, 1 Test ergaenzt (221 -> 222).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer Unterpunkt "Berichte" je Plan: Liste plus Assistent (Titel, Notiz,
nominal ODER real, Plan-/Ist-Daten, bis zu drei Szenarien, gespeicherte
Analysen). Layout immer gleich, Auswahl bestimmt nur die Bausteine.
Die PDF-Datei wird ALS DATEI abgelegt (BYTEA in Postgres, nicht im
Container-Dateisystem): Ein Bericht muss in drei Jahren byte-identisch
wieder herunterladbar sein -- eine Neuerzeugung koennte das nach
Aenderungen an Plan, Rechenkern oder Layout nicht garantieren.
Kennzahlen je Szenario inkl. offener Entscheide. Deren Zaehlung liegt neu
als reine Funktion in decisions.ts, die Matrix UND Bericht benutzen --
sonst nennen beide verschiedene Zahlen.
Zu jeder Kennzahl ihre Grundlage als Verweis; die vollstaendigen Annahmen
einmal je Szenario. Haftungsausschluss ist verpflichtend (per Test).
Technik: pdfkit in der Node-Runtime statt Headless-Browser;
@react-pdf/renderer bricht mit React 19. Als externes Paket deklariert,
weil pdfkit Font-Metriken ueber Dateipfade laedt.
Spezifikation 0.25 (3.11 neu), 9 Tests (212 -> 221).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sidebar zweistufig: pro Plan die Unterpunkte Szenarien / Effektive Werte /
Analysen; Klick auf Plan-Name oeffnet ein Plan-Dashboard.
Plan-Dashboard: Kennzahlen, gerechnete Werte ausdruecklich "laut
Basisszenario", Ist-Abweichung falls erfasst.
Szenario-Liste: Version, Elementzahl, Endvermoegen, Ruinalter + Aktionen
Historie und Matrix. Baum in der Sidebar bleibt.
Analysen: vier umklappende Kacheln (auch per Antippen). Grafiken oeffnen
neu mit Auswahl EINER Grafik. Szenario-Vergleich zu den Grafiken,
CSV-Export auf die Matrix.
Gespeicherte Analysen: Grafik/MC/Einflussfaktoren als ZAHLEN einfrieren
(read-only, nichts wird neu gerechnet) -- druckfaehig fuer den spaeteren
PDF-Bericht, ohne finalWealthSorted. Einheitliche generische Ergebnisform.
Neue Tabelle SavedAnalysis, Endpunkte /analyses und /dashboard, Module
analyses.ts, Komponenten PlanViews/SavedAnalysisView/SaveAnalysisButton.
Kein Eingriff in den Rechenkern. Spezifikation 0.24 (3.10 und 9.30 neu).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Neuer Knopf auf Plan-Ebene: Liste plus Wizard in zwei Schritten. Ein
Ist-Satz haengt am PLAN, nicht am Szenario -- die Zuordnung laeuft ueber
die Herkunfts-Kette sourceElementId.
computePlan nimmt neu { actuals }: Die Werte schnappen in jedem erfassten
Jahr auf die Realitaet und laufen von dort planmaessig weiter. Luecken
fallen auf die Plandaten zurueck. Ohne die Option unveraendert -- die 43
Golden Tests laufen durch.
Der Sprung ist keine Rendite: eigene Brueckenposition actualsCorrection
in Vermoegens- und Cash-Bruecke, sonst ginge die Zerlegung nicht auf.
Matrix: Umschalter Plan/Effektiv, im Ist-Modus mit farbiger Abweichung
statt acht Zahlen je Zelle. Zeitachse: Marker je Jahr, juengster farbig.
Vier Analysewerkzeuge mit einheitlicher Leiste (nominal/real als
Einfachauswahl, Plan/Effektiv). MC: Zielbetrag dreht mit, Startjahr
abgeleitet statt eingebbar.
Neue Tabelle ActualsSet (gegen echtes Postgres verifiziert), Module
actuals.ts und dataview.ts. Spezifikation 0.21, 27 Tests (181 -> 208).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Rein an der Oberflaeche -- Berechnung, Datenmodell und API-Semantik unveraendert
(103 Tests unveraendert gruen).
Paket A (Fundament):
- durchgehend Du-Form und echte Umlaute in allen sichtbaren Texten,
inkl. API-Fehlermeldungen (vorher Mix aus Sie/Du und ae/oe/ue)
- neue UI-Primitiven (ui.tsx): Button, Modal mit ESC/Fokus-Falle/Animation,
Bestaetigungs-Dialog statt window.confirm, Toasts statt alert,
Skeleton-Loader, EmptyState
- eigene Attention-Farbe (Amber) fuer offene Entscheide, getrennt vom Akzent
- Micro-Interactions mit prefers-reduced-motion-Fallback
Paket B (Onboarding, Roadmap Nr. 10):
- gefuehrter Plan-Assistent in 5 Schritten; Einkommen bewusst pro Person
(raeumt die 9.9-AHV-Falle aus); reine Orchestrierung bestehender Endpunkte
- Beispielplan mit einem Klick; Uebergaenge absichtlich offen
- interaktive Tour ueber die Planansicht (localStorage, jederzeit neu startbar)
- abgeleitete "Naechste Schritte"-Karte (offene Entscheide, fehlende Elemente,
fehlende Pensionsphase, Ruin -> Einflussfaktoren)
Paket C (Struktur):
- Inspector-Panel rechts statt Modals fuer alle Einzel-Bearbeitungen;
Matrix bleibt sichtbar, Zellklick wechselt den Inhalt
- Phasenkopf auf vier Kern-Infos entschlackt (Rest in der 0.11-Detailansicht)
- Matrix mit eigenem Scrollbereich, Koepfe beidachsig fixiert
- Sidebar-Gruppen "Meine Plaene" / "Wissen"; "So rechnet FPT" statt
SPEZIFIKATION; "Szenario-Profil" statt "Plan-Einstellungen"
- Aktions-Icons ohne Hover sichtbar (Touch)
Paket D (Extras):
- Sparklines je Element-Zeile aus den 0.11-Verlaufswerten
- Befehls-Palette (Ctrl/Cmd+K)
- Ruin-Banner verlinkt auf die Einflussfaktoren
Nebenbei: der ProfileMenu-Lint-Fehler und der Selection-Rest (9.17) sind
behoben -- npm run lint laeuft erstmals fehlerfrei.
SPEZIFIKATION auf 0.13: neue Kapitel 3.2.8, 3.7.6-3.7.9, 9.23, 9.24;
3.6.3 und 3.7.1 ueberarbeitet, 9.17 bereinigt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sieben Anpassungen aus dem Feedback:
- Grafiken liegen neu im eigenen Bereich "Grafiken" (Dialog, Button oben) statt
unter der Matrix. Die Matrix bleibt die ruhige Hauptansicht.
- Kennzahl "Geschaetzter Nachlass" entfernt -- sie war rechnerisch identisch mit
dem nominalen Endvermoegen und suggerierte eine Zusatzinformation, die es nicht gab.
- Monte-Carlo-Button nach oben zu den Szenario-Aktionen verschoben.
- Neues Profilfeld "Planstart (Jahr)" (Scenario.startYear + Migration). Rein fuer
die Darstellung -- die Berechnung rechnet unveraendert in relativen Jahren.
Bestehende Szenarien werden auf das laufende Jahr gesetzt.
- Zeitachse zeigt die Lebensphasen als Segmente (Breite = Dauer, Einfaerbung nach
Phasentyp) inkl. Jahresspanne, plus Jahres-Beschriftung an den Enden.
- Lebensphase bearbeiten neu als Popup statt Panel unter der Tabelle -- konsistent
zu allen anderen Eingaben; Speichern schliesst.
- Vermoegensverlauf ueber ALLE Jahre statt nur ueber die Phasengrenzen. Dafuer
fuehrt computePlan das Vermoegen neu pro Jahr mit (YearPoint.wealthNominal/
wealthReal) -- dieselbe Groesse, die schon die Ruin-Erkennung berechnet. Damit
werden Verlaeufe INNERHALB einer Phase sichtbar (z. B. Kapitalverzehr).
Zwei Tests fuer das Jahres-Vermoegen (58 -> 60). Spezifikation auf v0.9.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Groesste Umstrukturierung bisher. Der PLAN ist neu ein schlanker Behaelter ohne
Finanzdaten; die berechenbare Einheit ist das SZENARIO.
Modell:
- Jeder Plan bekommt beim Anlegen automatisch ein Basisszenario (isBase).
- Das Grundprofil liegt am Szenario, nicht am Plan -- nur so sind Szenarien mit
abweichendem PENSIONSALTER moeglich (Fruehpensionierung), das in Person steckt.
- Neue Szenarien sind vollstaendige Kopien eines BELIEBIGEN Szenarios und haengen
als Baum darunter (parentScenarioId); die Seitenleiste rueckt sie ein.
- Kopierte Phasen/Elemente tragen Herkunfts-Verweise (sourcePhaseId,
sourceElementId). Ueber den Namen zu matchen waere fragil gewesen.
Abweichungs-Markierung (Diff gegen das Eltern-Szenario, live):
- geaendert = gelb, neu = gruen + Badge, entfernt = graue Geisterzeile.
- Markiert: Phasen-/Uebergangszellen, Element-Zeilen, Phasenkoepfe, Cash-Anfangswert,
Cash-Uebergaenge, Grundprofil. Zaehler ueber der Matrix.
- Eigene Theme-Tokens fuer Hell/Dunkel/Warm -- ein fester Gelbwert waere im
Dunkelschema unbrauchbar.
Charts vergleichen neu die Geschwister-Szenarien statt fremder Plaene.
Datenmodell/Migration:
- Neue Tabelle Plan; bisheriger Plan -> Scenario (IDs erhalten, damit alle
Kind-Fremdschluessel gueltig bleiben); planId -> scenarioId in Person/Phase/
FinancialElement. Bestehende Szenarien werden per rekursivem CTE demselben
Behaelter zugeordnet, auch mehrfach verschachtelte.
- Migration VOR dem Deploy gegen echtes PostgreSQL verifiziert (PGlite, in-process),
inkl. verschachtelter Szenarien und Cascade. Der Test ist als
migrations.test.ts committet und sichert kuenftige Migrationen ab.
API neu unter /api/scenarios/*. 10 neue Tests (48 -> 58). Spezifikation auf v0.8.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Roadmap Nr. 9 (reduziert): Einkommen ist neu explizit als NETTOLOHN definiert
(Label + Hilfetext). Bisher stand nirgends, ob netto oder brutto gemeint ist -- fuer
den Cash-Fluss egal (beide Konventionen heben sich auf), aber seit der
einkommensabhaengigen AHV haengt eine Rente daran. Die AHV bemisst sich am
Bruttolohn, deshalb rechnet das Tool intern mit AHV_GROSS_FROM_NET_FACTOR = 1.12
hoch. Ohne das war die Rente um bis zu ~1'900/Jahr zu tief (Details: SPEZ 9.13).
Der Faktor ist hergeleitet und dokumentiert (AHV/IV/EO 5.3% + ALV 1.1% + NBU ~1% +
PK ~2-5% auf den koordinierten Lohn) -- fix vertretbar, weil das mdJE selbst ein
Karriere-Durchschnitt ist. Keine Aufschluesselung, kein sichtbares Feld (kommt mit
Roadmap Nr. 41 als erklaerte Konstante).
Roadmap Nr. 8: Immobilie neu mit Hypothekarzins (% der Restschuld, Zinsbetrag sinkt
mit der Amortisation, read-only "Beginn -> Ende") und Wertsteigerung.
WICHTIG: Die Wertsteigerung wirkt auf die LIEGENSCHAFT, nicht auf das Eigenkapital.
1% von 1 Mio sind 10'000/Jahr, also 10% eines Eigenkapitals von 100'000 -- das ist
der Hebel. Auf dem EK gerechnet waeren es 1'000 (Beispiel: 304'622 statt 210'462).
Kaufpreis und Verkehrswert laufen deshalb getrennt; die Grundstueckgewinnsteuer
bemisst sich weiterhin am urspruenglichen Kaufpreis.
Doppelzaehlung: Schalter interestHandling auf der Immobilie, Default INCLUDED --
bestehende Plaene haben die Zinsen in den Ausgaben und aendern sich nicht.
Keine Steuerschaetzung (Begruendung: SPEZ 9.14). Sechs Regressionstests (30 -> 36).
Spezifikation auf v0.5.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Cash-Uebergang zwischen zwei Phasen ist neu ein eigener Entscheid:
1:1 uebernehmen / einmaliger Zufluss / einmalige Kosten / beides. Die Betraege
gehen direkt aufs Cash-Konto und bleiben aus der Spar-/Verzehrquote heraus.
- Zufluss NOMINAL erfasst, real angezeigt (wie Einkommen), optionaler Steuersatz
(Default 0 %). Kosten REAL erfasst, nominal angezeigt (wie Ausgaben).
Umrechnung ueber den Bestands-Deflator an der Phasengrenze.
- Entscheid startet unbeantwortet und zaehlt im "offen"-Badge mit; eine neue Phase
erzeugt damit automatisch einen offenen Cash-Entscheid am neuen Uebergang.
- Eigene Kopf-Kennzahlen statt Vermischung mit Kapitalzufluss/-investitionen:
eine Erbschaft ist kein Verkaufserloes, ein Poolbau keine Investition.
- Cash ist kein FinancialElement -> der Entscheid haengt als JSON an der Von-Phase
(neue Spalte Phase.cashTransition + Migration). Szenario-Kopie nimmt ihn mit.
Fuenf Regressionstests ergaenzt (13 -> 18). Spezifikation auf v0.3.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Phase.inflationRate ersatzlos entfernt (inkl. Migration). Die Inflation liegt
seit V5 plan-weit; das Feld wurde von computePlan nie gelesen und war wirkungslos.
- Amortisation und Tilgung stoppen, sobald Hypothek bzw. Schuld abbezahlt sind:
Hypothek/Restschuld sind neu laufende Salden, die Rate ist pro Jahr am Restsaldo
gekappt. Belastet danach weder Cash noch Sparquote.
- Kapitalbezugssteuer greift neu auch bei PK-/3a-Vorbezuegen vor der Pensionierung.
Der Bezug wird brutto dem Kapital entnommen, netto ins Cash gebucht.
plannedSaveRate ist neu die Rate des ersten Phasenjahres. Drei Regressionstests
ergaenzt (10 -> 13).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neues Feld Plan.initialCash (additiv, Default 0). computePlan startet die erste Phase
mit diesem Cash-Bestand statt 0. In der Matrix ist die Cash-Zelle der ersten Phase
klickbar und oeffnet ein Popup zum Setzen des Anfangswerts (PATCH /api/plans/{id}).
Szenario-Kopie uebernimmt den Wert. Golden-Test ergaenzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behebt die Nominal/Real-Inkonsistenz (Bug #1): Einkommen/Ausgaben werden neu Jahr fuer
Jahr indexiert (eigenes Feld teuerungsausgleich je Element, Default = Phaseninflation;
Renten nominal fix = 0%). Vermoegen verzinst weiterhin nominal.
Cash: neues systemseitiges, immer sichtbares Element (0% Verzinsung, kein DB-Row -
synthetisch in computePlan). Ist der Ausgleichstopf = "verfuegbares Kapital fuer
Investments": cash_delta(t) = quote(t) - geplante flache Jahresraten (3a/Vermoegen/Amort./
Tilgung); Cash laeuft ueber Phasen fort, darf negativ werden (rot). Der Verteilzwang und
die harten Sparraten-Caps entfallen.
Ruin: Gesamtvermoegen (inkl. Cash) je Jahr; erstes Unterschreiten von 0 -> Ruin-Alter
(Person A), Anzeige als Banner + Zeitachsen-Marker.
Phasenkopf neu: Einkommen/Ausgaben Start->Ende, Quote Beginn/Ende, Cash Start->Ende,
Vermoegen inkl. Cash, Realwert. Inflation-Deflator neu pro Jahr (Math.pow ^Dauer).
Golden Tests (vitest) 1-4 + Renten-0% + Fortschreibung gruen (Test1 761'654/565'928,
Test2 Ruin Alter 94).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Person A/B erhalten ein optionales Namensfeld (Migration: Person.name nullable).
Fallback im UI bleibt "Person A"/"Person B". Angezeigt in Grundprofil-Box, Zeitachse,
Matrix-Elementzuordnung und Element-Erstelldialog; Szenario-Kopie uebernimmt den Namen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>