Modul-Review 4: Matrix -- Kapitalverwendung, Phasendauer, Bedienung
Deploy App / deploy (push) Successful in 1m10s
Deploy App / deploy (push) Successful in 1m10s
Kapitalverwendung (Punkt C) am richtigen Ort: - Prozent-Aufteilung des bezogenen Alterskapitals wandert vom Cash-Uebergang zum Bezugs-Entscheid der PK (nur bei Kapitalbezug) bzw. der Saeule 3a -- mit zwei Guthaben liess sie sich vorher gar nicht getrennt beantworten - Dialoge fuehren neu brutto -> Steuersatz -> netto -> Verteilung - BUGFIX: Der zugeteilte Betrag erhoehte still den internen Bestand, deshalb zeigten Ziel-Element und "Kapital verteilen" eine 0. Er laeuft jetzt ueber Carry.capitalIn als Zusatzeinlage der Folgephase und ist ueberall sichtbar - Saeule 3a ist am Pensions-Uebergang neu ein offener Entscheid Phasendauer (gemeldeter Fehler): - Die Folgephase gleicht eine geaenderte Dauer aus; Gesamtdauer bleibt gleich - Vorher kappte das Tool nur die bearbeitete Phase -> Phase 2 ueberspannte danach die Pensionierung und die Invariante aus Punkt 44 kippte - Rueckfrage vorher, Blockade wenn die Folgephase unter 1 Jahr fiele - neue reine Funktion planDurationChange Bedienung: - Element-Zeile und Phasenkopf: Stift (umbenennen, beim Element inkl. Zuordnung), Papierkorb, Expand -- alle immer sichtbar - PATCH /api/elements/<id> nimmt neu auch ownerRole - Hilfetexte via Portal (wurden in scrollenden Dialogen abgeschnitten) - Verteil-Dialoge: Zuordnung je Zeile, nach vom/ins Cash gruppiert, Vorbelegung mit dem EFFEKTIVEN Wert inkl. Vererbung (zeigte vorher 0) - Matrix: gleiche Spaltenbreiten + horizontales Scrollen, "Alle auf-/ zuklappen", Kategorie-Summe in der zugeklappten Zeile - Phasen-Detailansicht nutzt die neue Aufteilungs-Grafik - Uebersicht: "Leer starten" auch im leeren Zustand Nebenbei: dritte verstuemmelte Hex-Farbe (#7c3aed) repariert, Phasen-Panel nutzt den eigenen Bestaetigungs-Dialog statt window.confirm; mehrere veraltete Referenzen und die buildCarryData-Tabelle in der Spez nachgezogen. SPEZIFIKATION 0.33. 278 -> 288 Tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+87
-44
@@ -4,10 +4,10 @@
|
||||
| | |
|
||||
|---|---|
|
||||
| **Dokument** | Funktionale und Technische Spezifikation FPT |
|
||||
| **Version** | 0.32 |
|
||||
| **Version** | 0.33 |
|
||||
| **Datum** | 2026-07-25 |
|
||||
| **Status** | Lebendes Dokument |
|
||||
| **Codestand** | Arbeitsstand nach `b42f9b3` inkl. Modul-Review 3 (Nachbesserungen) (Branch `main`) |
|
||||
| **Codestand** | Arbeitsstand nach `0761f6b` inkl. Modul-Review 4 (Matrix) (Branch `main`) |
|
||||
| **Ersetzt** | `FDD_TDD_FPT.docx` (v1–v5) im Ordner `Info Dateien` – diese sind ab Version 0.1 dieses Dokuments obsolet |
|
||||
| **Geltungsbereich** | Gesamter Code im Verzeichnis `FPT` |
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
| Version | Datum | Autor | Änderung |
|
||||
|---|---|---|---|
|
||||
| 0.33 | 2026-07-25 | Claude (Opus 5) | **Modul-Review 4 (Matrix: Phasen und Elemente).** (1) **Kapitalverwendung neu am Vorsorge-Element** (Punkt C aus Roadmap Nr. 44): Die Prozent-Aufteilung des bezogenen Alterskapitals hing am **Cash-Übergang** – dem falschen Ort, denn mit zwei Guthaben (PK und 3a) liess sie sich dort gar nicht getrennt beantworten. Sie steht jetzt beim **Bezugs-Entscheid** der Pensionskasse (nur bei Kapitalbezug) bzw. der **Säule 3a**. Beide Dialoge führen neu **brutto → Steuersatz → netto** und darunter die Verteilung. Der zugeteilte Betrag fliesst über den regulären Weg (`Carry.capitalIn` → Zusatzeinlage der Folgephase) und ist damit **überall sichtbar**: am Ziel-Element, in der Cash-Brücke als Investition und im «Kapital verteilen»-Dialog. Vorher erhöhte er still den Bestand, weshalb Element und Dialog eine **0** zeigten. Die **Säule 3a** ist am Pensions-Übergang neu ein **offener Entscheid** (Steuersatz und Verwendung); vorher galt sie als automatisch beantwortet. (2) **Phasendauer: die Folgephase gleicht aus** (Kap. 3.3.2). Bis 0.32 prüfte die Kappung nur die **bearbeitete** Phase – wurde Phase 1 von 10 auf 12 Jahre verlängert, überspannte danach Phase 2 die Pensionierung, und die tragende Invariante aus Roadmap Nr. 44 kippte. Neu trägt die Folgephase die Differenz (Gesamtdauer bleibt gleich, wie beim Verschieben des Pensionsalters); passt sie nicht, wird blockiert; vorher erscheint eine Rückfrage. Neue reine Funktion `planDurationChange`. (3) **Element und Phase direkt bedienbar:** In der Matrix tragen Element-Zeile und Phasenkopf neu **Stift** (umbenennen, beim Element inkl. **Zuordnung**) und **Papierkorb**; das Expand-Symbol ist **immer** sichtbar statt nur bei Mouseover. `PATCH /api/elements/<id>` nimmt dafür neu auch `ownerRole` (bleibt für AHV/PK/3a personengebunden). (4) **Hilfetexte** werden über ein **Portal** gezeichnet – in scrollenden Dialogen schnitt der Container sie vorher ab; sie klappen nach oben, wenn unten kein Platz ist. (5) **Verteil-Dialoge:** Zeilen zeigen die **Zuordnung** (Person A/B/Gemeinsam) und sind nach **«vom Cash»/«ins Cash»** gruppiert; die Vorbelegung nutzt neu den **effektiven** Wert inklusive Vererbung aus der Vorphase – ein geerbter 3a-Beitrag erschien vorher als 0. (6) **Matrix:** alle Phasenspalten **gleich breit**, bei vielen Phasen wird horizontal gescrollt; **«Alle auf-/zuklappen»**; eine zugeklappte Kategorie zeigt je Phase die **Summe** ihrer Elemente. (7) **Phasen-Detailansicht** nutzt die neue Aufteilungs-Grafik (Fläche + Ring) statt der alten Balken. (8) **Übersicht:** «Leer starten» steht neu auch im leeren Zustand zur Wahl. (9) Nebenbei: dritte vom Umlaut-Sweep verstümmelte Hex-Farbe (`#7c3äd`) repariert, das Phasen-Panel nutzt den eigenen Bestätigungs-Dialog statt `window.confirm`. 10 Tests ergänzt (278 → 288). |
|
||||
| 0.32 | 2026-07-25 | Claude (Opus 5) | **Modul-Review 3, Nachbesserungen – darunter ein gravierender Rechenfehler bei den effektiven Werten.** (1) **Immobilien-Bugfix (Kap. 3.9):** Der Ist-Wizard belegte den Immobilienwert mit dem **Eigenkapital** vor (`ElementYearPoint.value`), während Erfassung und Rechenkern den **Verkehrswert** erwarten. Der Rechenkern setzte den vorbelegten Wert als Verkehrswert ein, liess die Hypothek aber stehen – das Eigenkapital brach im Ist-Jahr schlagartig ein, typischerweise ins Negative. Sichtbar wurde das als **negative Gesamt-Abweichung, obwohl nur ein Lohn erhöht** wurde, und als «wegbrechendes» Wohneigentum in der Vermögensaufteilung. Neu wird `propertyValue` vorbelegt; das Feld ist als «Verkehrswert + Restschuld» beschriftet. Drei Regressionstests. (2) **Ist-Datensätze bearbeitbar:** Ein Klick auf die Zeile (oder «Bearbeiten») öffnet den erfassten Satz erneut; neuer Endpunkt `PUT /api/plans/<id>/actuals/<setId>`. Beim Bearbeiten überschreiben die Planwerte die erfassten Zahlen nicht mehr. (3) **Ring-Klick in der Vermögensaufteilung repariert:** Recharts 3 reicht im Klick-Parameter **kein `activePayload`** mehr durch (nur noch `activeIndex`) – der Handler feuerte nie, der Ring zeigte immer das Planende. (4) **Seitenleiste sauber dreistufig:** Ebene 1 Pläne, Ebene 2 die vier Bereiche (Szenarien, Effektive Werte, Analysen, Berichte) mit **bündigen Symbolen**, Ebene 3 nur die Szenarien – verschachtelt nach Herkunft. (5) Die **Szenario-Liste** zeigt neben der Version deren **Kommentar**. |
|
||||
| 0.31 | 2026-07-25 | Claude (Opus 5) | **Modul-Review 3 (Plan-/Szenario-Struktur, Dashboard, Grafiken).** (1) **Versionierung startet bei 0.1** statt 1.0 (Kap. 3.8): Ein Szenario läuft in der 0er-Reihe (0.1, 0.2, … 0.137), bis eine **Hauptversion** gesetzt wird – erst dann entsteht 1.0. Vorher begann jedes Szenario bereits bei 1.0, wodurch die Hauptversion ihre Bedeutung verlor. Die Szenario-Liste zeigt neu die **echte** Version statt «1.x», dazu eine Spalte **Phasen**. (2) **Plan-Dashboard:** Kacheln sind **anklickbar** und führen in ihren Bereich, neu inkl. **Berichte**; der Plan lässt sich über ein Stift-Symbol **umbenennen**; die Ist-Abweichung nennt das **Jahr** des jüngsten Ist-Datensatzes und ist bei einer positiven Abweichung **grün** statt rot. (3) **Szenario-Liste:** Ein Klick auf die **Zeile** öffnet die Matrix (der «Matrix»-Knopf entfällt), dazu je Zeile **Kopie** und **Löschen**; die Kopiervorlage ist damit frei wählbar und nicht mehr auf das Basisszenario festgelegt. Nach einer Löschung lädt die Liste neu (zeigte vorher den alten Stand). (4) **Seitenleiste:** Szenarien werden wieder **verschachtelt** dargestellt (Tiefe = Herkunftskette); «Effektive Werte», «Analysen» und «Berichte» stehen neu **bündig zum Knoten «Szenarien»** statt auf Höhe der einzelnen Szenarien. (5) **CSV-Export vollständig neu** (Kap. 3.6.5, neues Modul `csv.ts`): vier Blöcke – Kopf, Lebensphasen, **die ganze Matrix** (Elemente × Phasen mit Beginn/Ende und den Übergangs-Entscheiden im Klartext) und **Jahreswerte**; mit BOM, damit Excel die Umlaute erkennt. Vorher enthielt die Datei kein einziges finanzielles Element. (6) **Grafiken:** Ein **Szenario-Wähler** gilt neu für **alle drei** Grafiken (vorher nur der Vermögensverlauf, und der nur additiv). Der **Vergleichs-Fehler** ist behoben: `WealthChart` benutzte den Szenario-**Namen** als Datenschlüssel, wodurch sich gleichnamige Szenarien gegenseitig überschrieben (Legende zeigte beide, der Chart nur eine) – neu die **ID**; die stille Deckelung auf vier Serien entfällt. Die **Legende** ist eigenständig, erlaubt eine **freie Farbwahl je Serie** und erklärt den Linienstil (gestrichelt = Plan, durchgezogen = effektiv). Die **Vermögensaufteilung** ist neu eine **gestapelte Fläche über alle Planjahre** plus ein **Ring** für die relative Aufteilung zu einem wählbaren Zeitpunkt (vorher gestapelte Balken je Phase mit schräger Beschriftung). **Alle Diagrammfarben** kommen aus neuen Theme-Tokens (`--chart-1` … `--chart-6`, `--chart-grid`) statt fester Hex-Werte. (7) **Dokumentation nachgezogen:** Die 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). (8) Nebenbei: verstümmelte Hex-Farbe `--danger-soft` im Warm-Schema repariert, deutsche Plural-/Umlautfehler in den Übersichts-Kacheln, Dateiname des CSV-Exports transliteriert Umlaute statt sie zu `_` zu machen. 8 Tests ergänzt (267 → 275). |
|
||||
| 0.30 | 2026-07-24 | Claude (Opus 4.8) | **Tour-Korrekturen und 3a-Verschiebung.** (1) Der Tour-**Spotlight** wird neu aus **vier fixed-Flächen** um die Bounding-Box des Ziels gezeichnet (Kap. 9.24) statt aus einem `box-shadow`-Trick. Grund: Der Schatten liess sticky Matrix-Köpfe (hoher z-index) hell durchscheinen und wurde im Matrix-Scrollbereich abgeschnitten (dann blieb fast alles hell). Die vier Flächen funktionieren unabhängig von z-index und overflow und folgen dem Ziel per `requestAnimationFrame`. (2) **Tour-Schritte** überarbeitet: neu erklärt sind **Zeitachse** und **Endvermögen**; der vormals «Analysen»-Schritt beschreibt jetzt korrekt die **obere Funktions-Leiste** (die Analyse-Werkzeuge sind dort nicht mehr), und ein neuer Schritt zeigt das **linke Menü** (Analysen, Berichte, Effektive Werte). Unsichtbare Ziele (z. B. das Menü auf schmalen Screens) werden übersprungen. (3) Der Schalter **«Selbstständig – grosse Säule 3a»** wandert im Assistenten von Schritt 4 zu **Schritt 5**, weil er die 3a-Einzahlung (also die Sparraten-Verteilung) betrifft. Kein Eingriff in den Rechenkern; 267 Tests unverändert grün. |
|
||||
@@ -528,32 +529,47 @@ und die AHV-/PK-Renten am Phasenbeginn ausgewertet werden.
|
||||
mindestens eine Person pensioniert ist, sonst „Erwerbsphase".
|
||||
|
||||
**Vorbelegung der Elemente:** Beim Anlegen einer Phase wird für jedes noch aktive Element
|
||||
(nicht `SOLD`, nicht `SETTLED`) ein `ElementPhaseValue` mit den **editierbaren** Feldern der
|
||||
Vorphase erzeugt (`buildCarryData`):
|
||||
(nicht `SOLD`, nicht `SETTLED`) ein `ElementPhaseValue` erzeugt – seit 0.28 aber fast **leer**
|
||||
(`buildCarryData`):
|
||||
|
||||
| Kategorie | Übernommene Felder |
|
||||
| Kategorie | Kopierte Felder |
|
||||
|---|---|
|
||||
| `INCOME`, `EXPENSE` | nur `teuerungsausgleich` (Basis wird live fortgeschrieben) |
|
||||
| `AHV` | `gapYears: 0` |
|
||||
| `PENSION_FUND`, `PILLAR_3A`, `OTHER_ASSET` | `annualContribution`, `expectedReturn` |
|
||||
| `REAL_ESTATE` | `purchasePrice`, `amortization` (Resthypothek wird live fortgeschrieben) |
|
||||
| `OTHER_DEBT` | `annualRepayment` |
|
||||
| `AHV` | `gapYears: 0` – Ausfalljahre gelten für genau eine Phase, ein geerbter Wert würde eine Lücke erfinden |
|
||||
| `REAL_ESTATE` | `purchasePrice` (eine Tatsache, Basis der Grundstückgewinnsteuer) und `interestHandling` (ein Schalter ohne Zahlenwert) |
|
||||
| alle übrigen | **nichts** |
|
||||
|
||||
Bestände (PK-/3a-/Vermögenswert, Resthypothek, Restschuld) werden **bewusst nicht als Snapshot
|
||||
gespeichert**, sondern in jeder Berechnung live aus der Vorphase fortgeschrieben. Damit wirken
|
||||
sich nachträgliche Änderungen an frühen Phasen automatisch auf alle Folgephasen aus.
|
||||
Alles andere wird **nicht kopiert, sondern live vererbt**: Beträge und Bestände werden aus der
|
||||
Vorphase fortgeschrieben, die **Wiederkehr-Parameter** (Raten, Beiträge, Amortisation,
|
||||
Wertsteigerung, Zinssatz) gelten weiter, solange das Feld leer bleibt
|
||||
([3.12.4](#3124-punkt-a-aus-vorphase-übernehmen)). Der Unterschied zeigt sich, sobald man eine
|
||||
frühe Phase nachträglich ändert: Eine Kopie bliebe stehen, die Vererbung zieht mit.
|
||||
|
||||
Referenz: `src/app/api/plans/[planId]/phases/route.ts`.
|
||||
Referenz: `src/app/api/scenarios/[scenarioId]/phases/route.ts`.
|
||||
|
||||
### 3.3.2 Phase bearbeiten
|
||||
|
||||
Klick auf einen Phasenkopf öffnet ein **Popup** („Lebensphase: <Name>") mit Bezeichnung und
|
||||
Dauer – konsistent zu allen anderen Eingaben (Element-Zellen, Übergänge). Speichern schliesst
|
||||
das Popup. Die Dauer wird auch hier gekappt. Eine phasenspezifische Inflationsrate gibt es nicht;
|
||||
das Panel weist darauf hin: „Die Inflationsrate gilt plan-weit und wird in den Plan-Einstellungen
|
||||
gesetzt."
|
||||
Klick auf einen Phasenkopf (oder auf dessen **Stift-Symbol**) öffnet das Panel „Lebensphase:
|
||||
<Name>" mit Bezeichnung und Dauer. Eine phasenspezifische Inflationsrate gibt es nicht; das
|
||||
Panel weist darauf hin.
|
||||
|
||||
Referenz: `src/components/PhaseDetail.tsx`.
|
||||
**Die Folgephase gleicht eine geänderte Dauer aus.** Wird eine Phase um N Jahre verlängert, wird
|
||||
die **nächste** um N Jahre kürzer – die Gesamtdauer des Plans bleibt gleich. Das Panel zeigt die
|
||||
Auswirkung live und fragt vor dem Speichern nach.
|
||||
|
||||
Warum das nötig ist: Bis 0.32 kappte das Tool nur die **bearbeitete** Phase am nächsten
|
||||
Pensionsereignis. Das ist richtig, aber nicht ausreichend. Beispiel: Phase 1 (10 J.) + Phase 2
|
||||
(10 J.), Pensionierung im Jahr 20. Eine Verlängerung von Phase 1 auf 12 Jahre ist für Phase 1
|
||||
zulässig – danach lief Phase 2 aber von Jahr 12 bis 22 und **überspannte die Pensionierung**.
|
||||
Da `computePlan` die Dauer nicht nachkappt und den Phasentyp am Phasen*beginn* ableitet, wurde
|
||||
die Pensionierung faktisch übersprungen; die tragende Invariante aus
|
||||
[4.16.1](#4161-die-tragende-invariante) war verletzt.
|
||||
|
||||
Passt der Ausgleich nicht (die Folgephase fiele unter ein Jahr), wird die Änderung **blockiert**
|
||||
mit dem Hinweis, um wie viel sie höchstens möglich wäre. Die **letzte** Phase hat keine
|
||||
Nachfolgerin – sie verlängert oder verkürzt den Plan tatsächlich.
|
||||
|
||||
Referenz: `planDurationChange` in `src/lib/phaseplan.ts`, `src/components/PhaseDetail.tsx`,
|
||||
`src/app/api/phases/[phaseId]/route.ts` (setzt beide Dauern in einer Transaktion).
|
||||
|
||||
### 3.3.3 Phase löschen
|
||||
|
||||
@@ -561,7 +577,7 @@ Referenz: `src/components/PhaseDetail.tsx`.
|
||||
Phase kann gelöscht werden."). Damit bleibt die Kette der `sequenceNumber` lückenlos. Der
|
||||
Löschen-Button erscheint im Detail-Panel nur bei der letzten Phase.
|
||||
|
||||
Referenz: `src/app/api/phases/[phaseId]/route.ts` Zeilen 55–77.
|
||||
Referenz: `src/app/api/phases/[phaseId]/route.ts`.
|
||||
|
||||
## 3.4 Finanzielle Elemente
|
||||
|
||||
@@ -584,7 +600,7 @@ Kategorien kein `PERSON_A`/`PERSON_B` übergeben → HTTP 400.
|
||||
|
||||
Für die übrigen Kategorien gilt: fehlt die Zuordnung, wird serverseitig `HOUSEHOLD` gesetzt.
|
||||
|
||||
Referenz: `src/lib/elements.ts` Zeilen 19–23, `src/app/api/plans/[planId]/elements/route.ts` Zeilen 43–54.
|
||||
Referenz: `src/lib/elements.ts` (`PERSON_ONLY_CATEGORIES`), `src/app/api/scenarios/[scenarioId]/elements/route.ts`.
|
||||
|
||||
### 3.4.2 Element anlegen
|
||||
|
||||
@@ -595,17 +611,28 @@ Bezeichnungs-Default ist das Kategorie-Label.
|
||||
|
||||
`orderIndex` = bisheriges Maximum + 1; bestimmt die Reihenfolge innerhalb der Kategoriegruppe.
|
||||
|
||||
Referenz: `src/components/PlanView.tsx` Zeilen 799–947.
|
||||
Referenz: `AddElementDialog` in `src/components/PlanView.tsx`.
|
||||
|
||||
### 3.4.3 Element bearbeiten und löschen
|
||||
|
||||
Ein Klick auf eine **Phasenzelle** öffnet den Dialog „Lebensphase: <Name>" mit den
|
||||
kategorie- und kontextabhängigen Feldern (siehe [3.4.4](#344-feldkatalog-je-kategorie)) sowie
|
||||
dem Button „Element löschen". Löschen entfernt das Element **aus allen Phasen**
|
||||
(Browser-`confirm()`, dann Cascade auf `ElementPhaseValue` und `ElementTransitionValue`).
|
||||
Ein Klick auf eine **Phasenzelle** öffnet das Panel mit den kategorie- und kontextabhängigen
|
||||
Feldern (siehe [3.4.4](#344-feldkatalog-je-kategorie)) – dort stehen die Werte **dieser Phase**.
|
||||
|
||||
Umbenennen ist per API möglich (`PATCH /api/elements/<id>`), im aktuellen UI aber nicht
|
||||
angebunden.
|
||||
Die Eigenschaften des **Elements selbst** (Bezeichnung, Zuordnung) sind phasenunabhängig und
|
||||
haben deshalb ihren eigenen Ort: In der Element-Zeile ganz links stehen drei Symbole –
|
||||
**Stift** (umbenennen und Zuordnung ändern), **Papierkorb** (löschen) und **Expand**
|
||||
(Detailansicht). Alle drei sind **immer** sichtbar, nicht erst bei Mouseover; auf einem
|
||||
Touch-Gerät gäbe es sonst keinen Weg dorthin. Denselben Aufbau trägt der **Phasenkopf**.
|
||||
|
||||
Die Zuordnung läuft über `ownerRole`, nicht über eine Person-ID – deshalb übersteht sie auch
|
||||
das Neuanlegen der Personen im Profil-Dialog. Für AHV, Pensionskasse und Säule 3a bleibt sie
|
||||
zwingend personengebunden (HTTP 400 bei „Gemeinsam").
|
||||
|
||||
Löschen entfernt das Element **aus allen Phasen** (eigener Bestätigungs-Dialog, dann Cascade auf
|
||||
`ElementPhaseValue` und `ElementTransitionValue`).
|
||||
|
||||
Referenz: `PATCH /api/elements/<id>` (Felder `name`, `ownerRole`), `ElementMetaPanel` in
|
||||
`src/components/PlanView.tsx`.
|
||||
|
||||
### 3.4.4 Feldkatalog je Kategorie
|
||||
|
||||
@@ -614,7 +641,7 @@ Die angezeigten Felder hängen von drei Kontextgrössen ab:
|
||||
- **`ownerWorking`** – ob der zugeordnete Besitzer in dieser Phase erwerbstätig ist
|
||||
- **`durationYears`** – Phasendauer (begrenzt z. B. die Ausfalljahre)
|
||||
|
||||
Referenz: `src/components/ElementDetail.tsx` Zeilen 124–340.
|
||||
Referenz: `ElementPhaseFields` in `src/components/ElementDetail.tsx`.
|
||||
|
||||
#### INCOME (Einkommen)
|
||||
|
||||
@@ -669,7 +696,7 @@ Ausgaben beruecksichtigt)" – Lohnabzüge sind im Nettoeinkommen bereits weg.
|
||||
|
||||
Wie PK, aber:
|
||||
- Die Einzahlung **zählt** zur Sparquote (verlässt das Cash).
|
||||
- Das Feld ist auf `PILLAR_3A_MAX_ANNUAL` = **7'258 CHF** (2026, mit PK) hart geklammert.
|
||||
- Das Feld ist auf `PILLAR_3A_MAX_ANNUAL` = **7'258 CHF** (2026, mit PK) hart geklammert – mit dem Schalter «Selbstständig ohne PK» auf `PILLAR_3A_MAX_SELF_EMPLOYED` (Feld `selfEmployed3a`, siehe 4.11).
|
||||
- Bei Pensionierung: „Die Saeule 3a wird beim Pensions-Uebergang vollstaendig bezogen."
|
||||
|
||||
#### REAL_ESTATE (Immobilie)
|
||||
@@ -947,7 +974,7 @@ in den Modi «Nominal» und «Real» bleibt alles einzeilig.
|
||||
|
||||
Es werden zwei verschiedene Deflatoren verwendet – siehe [4.5.3](#453-die-drei-deflatoren).
|
||||
|
||||
Referenz: `src/components/PlanView.tsx` Zeilen 665–699.
|
||||
Referenz: `src/components/PlanView.tsx` (Anzeige-Umschalter über der Matrix).
|
||||
|
||||
### 3.6.2 Zeitachse
|
||||
|
||||
@@ -1922,12 +1949,18 @@ Annahme) und die **Zins-Behandlung** (ein Schalter ohne Zahlenwert).
|
||||
Bestehende Pläne verhalten sich unverändert: Dort sind die Werte gespeichert und gewinnen daher
|
||||
gegen die Vererbung, bis man das Häkchen aktiv setzt.
|
||||
|
||||
### 3.12.5 Punkt C: Verwendung des Kapitalzuflusses
|
||||
### 3.12.5 Punkt C: Verwendung des bezogenen Alterskapitals
|
||||
|
||||
Am Pensions-Übergang kommt oft ein grosser Betrag auf einmal herein (PK-Kapital, Säule 3a,
|
||||
Verkaufserlös). Ihn vollständig als Cash liegen zu lassen ist selten die Absicht. Im
|
||||
Cash-Übergang lässt sich deshalb erfassen, wie viel **in Prozent** in die Amortisation der
|
||||
Hypothek und in eine Anlage fliesst; der Rest bleibt Cash.
|
||||
Am Pensions-Übergang kommt oft ein grosser Betrag auf einmal herein (PK-Kapital, Säule 3a).
|
||||
Ihn vollständig als Cash liegen zu lassen ist selten die Absicht. Beim **Bezugs-Entscheid des
|
||||
jeweiligen Guthabens** lässt sich deshalb erfassen, wie viel **in Prozent** in die Amortisation
|
||||
der Hypothek und in eine Anlage fliesst; der Rest bleibt Cash.
|
||||
|
||||
Die Frage steht seit 0.33 dort, wo der Bezug entschieden wird – bei der **Pensionskasse** (nur
|
||||
wenn Kapital bezogen wird) und bei der **Säule 3a**. Bis 0.32 hing sie am **Cash-Übergang**:
|
||||
Das war der falsche Ort, weil sich mit zwei Guthaben nicht getrennt festlegen liess, welches
|
||||
wohin fliesst. Beide Dialoge führen deshalb neu in der Reihenfolge, in der man tatsächlich
|
||||
entscheidet: **Bezugsart → Betrag brutto → Steuersatz → Betrag netto → Verteilung**.
|
||||
|
||||
**Warum Prozent und nicht Franken:** Verschiebt man das Pensionsalter, ändert sich das bezogene
|
||||
Kapital. Ein Frankenbetrag müsste von Hand nachgezogen werden – und würde bis dahin still eine
|
||||
@@ -1936,7 +1969,17 @@ falsche Aufteilung rechnen. Eine Quote skaliert mit.
|
||||
Die Amortisations-Quote ist am Restsaldo der Hypothek gekappt; ist sie grösser, bleibt der Rest
|
||||
Cash. Die Anlage-Quote fliesst in ein wählbares Vermögens-Element (Vorgabe: das erste aktive).
|
||||
Beide sind mechanisch nichts Neues – die eine wirkt wie eine Sonderamortisation, die andere wie
|
||||
eine Zusatzinvestition, und beide laufen dadurch korrekt durch die zwei Wasserfall-Brücken.
|
||||
eine Zusatzeinlage, und beide laufen dadurch korrekt durch die zwei Wasserfall-Brücken.
|
||||
|
||||
**Der zugeteilte Betrag ist überall sichtbar.** Er wandert über `Carry.capitalIn` in die
|
||||
**Zusatzeinlage der Folgephase** und erscheint dadurch am Ziel-Element (als eigene, read-only
|
||||
Zeile «Davon aus Kapitalbezug»), in der Cash-Brücke als **Investition** und im Dialog «Kapital
|
||||
verteilen». Bis 0.32 erhöhte die Verteilung direkt den internen Bestand – Element und Dialog
|
||||
zeigten deshalb eine **0**, obwohl das Geld geflossen war.
|
||||
|
||||
**Die Säule 3a ist am Pensions-Übergang ein offener Entscheid.** Der Bezug selbst steht fest
|
||||
(sie wird immer ausbezahlt), zu entscheiden sind Steuersatz und Verwendung. Vorher galt der
|
||||
Übergang als automatisch beantwortet, wodurch die Verwendungsfrage nie gestellt wurde.
|
||||
|
||||
Referenz: `src/lib/retirement.ts`, `src/components/RetirementAdjuster.tsx`,
|
||||
`src/components/FormField.tsx` (`InheritableField`).
|
||||
@@ -3529,6 +3572,9 @@ den Wert der Vorphase. Alle übrigen Felder bedeuten «nicht gesetzt = 0» wie b
|
||||
| `extraAmortization` | REAL_ESTATE (Sonderamortisation) | ≥ 0 |
|
||||
| `saleTaxRate` | REAL_ESTATE | 0–100 |
|
||||
| `immediateRepayment` | OTHER_DEBT | ≥ 0 |
|
||||
| `capitalUseAmortizationPct` | PENSION_FUND (Kapitalbezug), PILLAR_3A – Anteil des bezogenen Kapitals in die Amortisation | 0–100 |
|
||||
| `capitalUseInvestPct` | dito – Anteil in eine Anlage | 0–100 |
|
||||
| `capitalUseTargetElementId` | Ziel der Anlage-Quote; ohne Angabe das erste aktive Sonstige Vermögen | ≤ 60 Zeichen |
|
||||
|
||||
### 5.4.5 JSON-Payload `CashTransitionData`
|
||||
|
||||
@@ -3542,9 +3588,6 @@ Liegt in `Phase.cashTransition`. Validierung über `cashTransitionSchema`.
|
||||
| `inflowTaxRate` | Steuer auf den Zufluss, Default 0 % | 0–100 |
|
||||
| `outflowLabel` | Bezeichnung der Kosten (z. B. „Poolbau") | ≤ 120 Zeichen |
|
||||
| `outflowAmount` | Betrag **real** (heutige Kaufkraft) | ≥ 0 |
|
||||
| `capitalUseAmortizationPct` | Anteil des Kapitalzuflusses in die Amortisation (Kap. 3.12.5) | 0–100 |
|
||||
| `capitalUseInvestPct` | Anteil des Kapitalzuflusses in eine Anlage | 0–100 |
|
||||
| `capitalUseTargetElementId` | Ziel der Anlage-Quote; ohne Angabe das erste aktive Sonstige Vermögen | ≤ 60 Zeichen |
|
||||
|
||||
Pro Übergang ist **genau ein** Zufluss und **eine** Kostenposition möglich – siehe
|
||||
[9.7](#97-nur-ein-zufluss-und-eine-kostenposition-pro-übergang).
|
||||
@@ -3950,15 +3993,15 @@ Include `src/**/*.test.ts`). Es gibt **keine** Komponenten-, API- oder E2E-Tests
|
||||
| `versioning-coverage.test.ts` | 3 | statischer Wächter: jeder schreibende Endpunkt löst eine Version aus |
|
||||
| `report.test.ts` | 9 | Zusammenfassung, Basis-Angabe zu JEDER Kennzahl, Szenario-Deckelung, Plan/Ist-Block, Haftungsausschluss, gültige PDF-Datei |
|
||||
| `livesim.test.ts` | 15 | Element-Regler bewegt genau ein Element; Aufschlüsselung deckt sich mit dem Sammelregler; neutrale Stellung verändert den Plan nicht; Ruinmeldung |
|
||||
| `phaseplan.test.ts` | 8 | Ableitung der Lebensabschnitte aus den Pensionierungszeitpunkten (Einzel/Paar/bereits pensioniert); letzter Teil immer offen |
|
||||
| `bridges.test.ts` | 13 | Vermögens- und Cash-Brücke gehen über acht Plankonstellationen ohne Restgrösse auf; Umbuchungen bleiben aus der Vermögensbrücke heraus; Kapitalverwendung nach Quote (Punkt C) |
|
||||
| `phaseplan.test.ts` | 14 | Ableitung der Lebensabschnitte aus den Pensionierungszeitpunkten (Einzel/Paar/bereits pensioniert); letzter Teil immer offen |
|
||||
| `bridges.test.ts` | 17 | Vermögens- und Cash-Brücke gehen über acht Plankonstellationen ohne Restgrösse auf; Umbuchungen bleiben aus der Vermögensbrücke heraus; Kapitalverwendung nach Quote (Punkt C) |
|
||||
| `retirement.test.ts` | 16 | Spielraum und Sperren je Person, Verschiebung ohne Änderung der Gesamtdauer, Wegfall einer Phase, Zusammenführung der Übergangs-Entscheide |
|
||||
| `server-boundary.test.ts` | 1 | statischer Wächter: kein Modul unter `src/lib` importiert aus `src/components` |
|
||||
| `diff.test.ts` | 9 | Abweichungs-Erkennung gegen das Eltern-Szenario |
|
||||
| `migrations.test.ts` | 3 | spielt alle Migrationen gegen echtes PostgreSQL (PGlite) ein; prüft zusätzlich die V7-**Datenübernahme** (Basisszenario gewinnt, Pensionsalter bleiben szenario-eigen) |
|
||||
| `rate-limit.test.ts` | 6 | Fixed-Window: erlaubt bis Limit, blockt danach, startet nach Fensterablauf neu, trennt je Schlüssel; Client-IP aus X-Forwarded-For / X-Real-IP |
|
||||
| `csv.test.ts` | 7 | BOM, alle vier Blöcke, jedes Element als Zeile, Beginn-/Ende-/Übergangsspalten, Entscheid im Klartext, ein Eintrag je Planjahr, Maskierung von `;` und `"` |
|
||||
| **Total** | **278** | |
|
||||
| **Total** | **288** | |
|
||||
|
||||
## 8.2 Testfälle
|
||||
|
||||
|
||||
Reference in New Issue
Block a user