Einmalige Sonderein-/ausgaben am Cash-Uebergang (Roadmap Nr. 1)
Deploy App / deploy (push) Successful in 1m51s
Deploy App / deploy (push) Successful in 1m51s
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>
This commit is contained in:
+148
-16
@@ -4,10 +4,10 @@
|
||||
| | |
|
||||
|---|---|
|
||||
| **Dokument** | Funktionale und Technische Spezifikation FPT |
|
||||
| **Version** | 0.2 |
|
||||
| **Version** | 0.3 |
|
||||
| **Datum** | 2026-07-16 |
|
||||
| **Status** | Lebendes Dokument |
|
||||
| **Codestand** | Arbeitsstand nach `f768e01` inkl. Fixes zu Phaseninflation, Tilgungsraten und Vorbezugssteuer (Branch `main`) |
|
||||
| **Codestand** | Arbeitsstand nach `87e6a5f` inkl. einmaliger Sonderein-/ausgaben am Cash-Übergang (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.3 | 2026-07-16 | Claude (Opus 4.8) | **Einmalige Sonderein-/ausgaben** umgesetzt (Roadmap Nr. 1). Der Cash-Übergang zwischen zwei Phasen ist neu ein eigener Entscheid: 1:1 übernehmen · einmaliger Zufluss · einmalige Kosten · beides. Beträge gehen direkt aufs Cash-Konto. Zufluss wird nominal erfasst (real angezeigt) mit optionalem Steuersatz (Default 0 %), Kosten werden real erfasst (nominal angezeigt); beide bleiben aus der Sparquote heraus. Der Entscheid startet unbeantwortet und zählt im „offen"-Badge mit. Neue Spalte `Phase.cashTransition` (JSON) + Migration, neue Route `PUT /api/phases/<id>/cash-transition`, eigene Kennzahlen im Phasenkopf. Fünf Regressionstests ergänzt (13 → 18). Neue Kapitel 3.5.5, 4.9.6; Abschnitt 9 um zwei Grenzen ergänzt. |
|
||||
| 0.2 | 2026-07-16 | Claude (Opus 4.8) | Drei Fixes umgesetzt und dokumentiert: **(1)** `Phase.inflationRate` ersatzlos entfernt (DB-Migration, API, Typen, UI) – die Inflation liegt seit V5 plan-weit; das Feld war wirkungslos. **(2)** Amortisation und Tilgung stoppen neu, sobald Hypothek bzw. Schuld abbezahlt sind – sie belasten danach weder Cash noch Sparquote (Kap. 4.6.5, 4.6.7, 4.7, 4.8). **(3)** Kapitalbezugssteuer greift neu auch bei PK-/3a-Vorbezügen vor der Pensionierung, inkl. Steuerfeld und Netto-Vorschau im UI (Kap. 3.5.2, 4.9.1, 4.9.2). Kennzahl `plannedSaveRate` ist neu die Rate des **ersten** Phasenjahres. Drei Regressionstests ergänzt (10 → 13). Abschnitt 9 neu nummeriert (erledigte Punkte entfernt, „Sparraten werden nicht indexiert" ergänzt). |
|
||||
| 0.1 | 2026-07-16 | Claude (Opus 4.8) | Erstfassung. Vollständige Neuerstellung aus dem Code (Stand `f768e01`). Ersetzt die bisherigen FDD/TDD-Dokumente v1–v5 vollständig. |
|
||||
|
||||
@@ -139,10 +140,16 @@ Cash ist kein vom Benutzer erfassbares Element, sondern das systemseitige Ausgle
|
||||
- Es empfängt die **Bezugsraten** aus Sonstigem Vermögen.
|
||||
- Es empfängt an Übergängen **Kapitalzuflüsse** (Verkäufe, PK-/3a-Bezüge) und finanziert
|
||||
**Sofort-Tilgungen** sowie **Zusatzinvestitionen** der Folgephase.
|
||||
- Es nimmt an Übergängen **einmalige Sonderein-/ausgaben** auf (Erbschaft, Poolbau, Autokauf) –
|
||||
siehe [3.5.5](#355-cash-übergang-einmalige-sonderein-ausgaben).
|
||||
- Es darf **negativ werden** – dies ist die Definition einer Liquiditätslücke und wird rot
|
||||
markiert, aber nicht automatisch korrigiert.
|
||||
|
||||
Referenz: `src/lib/calculations.ts` Zeilen 365–425, 599.
|
||||
Cash ist die einzige Zeile der Matrix ohne `FinancialElement`-Datensatz. Zwei Zellen sind
|
||||
dennoch bearbeitbar: die **erste** Phasenzelle (Cash-Anfangswert) und **jede Übergangszelle**
|
||||
(einmalige Sonderein-/ausgaben).
|
||||
|
||||
Referenz: `src/lib/calculations.ts` (Jahresschleife und Übergang).
|
||||
|
||||
---
|
||||
|
||||
@@ -456,8 +463,10 @@ Schulden gehen mit **negativem** Vorzeichen ins Vermögen ein.
|
||||
### 3.5.1 Konzept
|
||||
|
||||
Zwischen zwei Phasen liegt ein Übergang. Er ist der Ort, an dem einmalige Entscheide getroffen
|
||||
werden. Nur fünf Kategorien haben Übergangs-Entscheide (`TRANSITION_CATEGORIES`):
|
||||
`PENSION_FUND`, `PILLAR_3A`, `REAL_ESTATE`, `OTHER_ASSET`, `OTHER_DEBT`.
|
||||
werden. Fünf Kategorien haben Übergangs-Entscheide (`TRANSITION_CATEGORIES`):
|
||||
`PENSION_FUND`, `PILLAR_3A`, `REAL_ESTATE`, `OTHER_ASSET`, `OTHER_DEBT`. Dazu kommt der
|
||||
**Cash-Entscheid** (siehe [3.5.5](#355-cash-übergang-einmalige-sonderein-ausgaben)), der an
|
||||
jedem Übergang zu treffen ist.
|
||||
|
||||
Für `INCOME`, `EXPENSE` und `AHV` erscheint: „Fuer diese Kategorie gibt es im Uebergang keine
|
||||
Eingaben."
|
||||
@@ -499,6 +508,7 @@ Entscheidungsfeld gesetzt ist:
|
||||
| `REAL_ESTATE`, `OTHER_ASSET` | `decision` gesetzt |
|
||||
| `PENSION_FUND` | Pensions-Übergang: `payoutMode` gesetzt; sonst: `withdrawalMode` gesetzt |
|
||||
| `PILLAR_3A` | Pensions-Übergang: **immer** beantwortet; sonst: `withdrawalMode` gesetzt |
|
||||
| **Cash** | `mode` gesetzt (`isCashTransitionAnswered`) |
|
||||
| alle anderen | immer beantwortet |
|
||||
|
||||
Der Übergangs-Spaltenkopf zeigt entweder „N offen" (Akzentfarbe) oder „geprüft" (grün, Häkchen).
|
||||
@@ -513,8 +523,9 @@ Referenz: `src/components/PlanView.tsx` Zeilen 200–232, `src/components/Elemen
|
||||
### 3.5.4 Geführter Übergang (Review-Dialog)
|
||||
|
||||
Klick auf einen Übergangs-Spaltenkopf öffnet „Übergang prüfen: <Von> → <Nach>". Der Dialog
|
||||
listet **alle** noch aktiven Elemente der Übergangs-Kategorien untereinander mit ihren
|
||||
Entscheidfeldern und kontextabhängigen Hinweisen:
|
||||
listet zuoberst den **Cash-Entscheid** (einmalige Sonderein-/ausgaben, betrifft jeden Übergang)
|
||||
und darunter **alle** noch aktiven Elemente der Übergangs-Kategorien mit ihren Entscheidfeldern
|
||||
und kontextabhängigen Hinweisen:
|
||||
|
||||
- PK/3a, normaler Übergang: „Hier könnten Sie optional Kapital beziehen."
|
||||
- PK, Pensionierung: „Pensionierung: Bezugsart wählen (Rente / Kapital / Kombination)."
|
||||
@@ -524,7 +535,45 @@ Entscheidfeldern und kontextabhängigen Hinweisen:
|
||||
`withTransitionDefaults` vorbelegt (Halten / Kein Bezug / Rente), damit ein blosses Speichern den
|
||||
**sichtbaren** Default auch tatsächlich persistiert und die Ampel auf grün geht.
|
||||
|
||||
Referenz: `src/components/PlanView.tsx` Zeilen 1040–1127, `src/components/ElementDetail.tsx` Zeilen 89–105.
|
||||
Referenz: `src/components/PlanView.tsx` (`TransitionReviewDialog`), `src/components/ElementDetail.tsx`
|
||||
(`withTransitionDefaults`).
|
||||
|
||||
### 3.5.5 Cash-Übergang: einmalige Sonderein-/ausgaben
|
||||
|
||||
Einmalige Ereignisse (Erbschaft, Poolbau, Autokauf, grössere Anschaffung) werden **nicht** als
|
||||
finanzielles Element modelliert, sondern als Entscheid auf dem **Cash-Konto am Phasenübergang**.
|
||||
Sie belasten bzw. speisen das Cash direkt.
|
||||
|
||||
Der Entscheid hat vier Ausprägungen (`CashTransitionMode`):
|
||||
|
||||
| Modus | Bedeutung | Felder |
|
||||
|---|---|---|
|
||||
| `NONE` | **1:1 übernehmen** – Cash läuft unverändert weiter (Default) | – |
|
||||
| `INFLOW` | **Einmaliger Zufluss** | Bezeichnung, Betrag (nominal), Steuer (%) |
|
||||
| `OUTFLOW` | **Einmalige Kosten** | Bezeichnung, Betrag (real) |
|
||||
| `BOTH` | Zufluss **und** Kosten am selben Übergang | beide Feldgruppen |
|
||||
|
||||
**Erfassungs-Konventionen** – bewusst analog zu den laufenden Flows:
|
||||
|
||||
- **Zufluss: nominal erfasst, real angezeigt** (wie Einkommen). Man kennt den Betrag, der
|
||||
effektiv aufs Konto kommt. Der Realwert erscheint read-only als Info.
|
||||
- **Kosten: real erfasst, nominal angezeigt** (wie Ausgaben). Man denkt „ein Pool kostet heute
|
||||
20'000"; die Inflation rechnet daraus den Betrag zum Ereigniszeitpunkt. Der Nominalwert
|
||||
erscheint read-only als Info.
|
||||
- **Steuersatz nur beim Zufluss**, Default 0 % (Erbschaften an direkte Nachkommen sind in den
|
||||
meisten Kantonen steuerfrei). Ins Cash fliesst der Betrag nach Abzug der Steuer.
|
||||
|
||||
**Weder Zufluss noch Kosten gehen in die Spar-/Verzehrquote.** Sie sind keine laufenden Flows;
|
||||
eine Erbschaft von 250'000 würde die Quote zu einem sinnlosen Ausschlag treiben. Sie wirken
|
||||
ausschliesslich auf das Cash und damit auf Vermögensverlauf, Endvermögen und Ruinalter.
|
||||
|
||||
**Bedienung:** Klick auf eine Übergangszelle der Cash-Zeile öffnet den Dialog „Uebergang: Cash".
|
||||
Die Zelle zeigt `1:1`, `+100'000`, `−20'000` bzw. `+100'000 / −20'000`, solange offen ein `?`.
|
||||
Der Entscheid ist Teil des geführten Übergangs (3.5.4) und zählt im „offen"-Badge mit – eine
|
||||
neu angelegte Phase erzeugt damit automatisch einen offenen Cash-Entscheid am neuen Übergang.
|
||||
|
||||
Referenz: `src/components/ElementDetail.tsx` (`CashTransitionFields`), `src/components/PlanView.tsx`
|
||||
(`CashTransitionDialog`).
|
||||
|
||||
## 3.6 Auswertung und Visualisierung
|
||||
|
||||
@@ -571,8 +620,14 @@ Jeder Phasenkopf zeigt kompakt:
|
||||
| Geplante Verzehrrate | Summe der Bezugsraten |
|
||||
| Kapitalzufluss | nur wenn > 0: Verkäufe + PK-/3a-Bezüge aus dem Übergang **in** diese Phase |
|
||||
| Kapitalinvestitionen | nur wenn > 0: Zusatzinvestitionen + Sofort-Tilgungen |
|
||||
| **Einmaliger Zufluss** | nur wenn > 0: Bezeichnung + Betrag (grün), aus dem Übergang in diese Phase |
|
||||
| **Einmalige Kosten** | nur wenn > 0: Bezeichnung + Betrag (rot) |
|
||||
| Vermögen | Start → Ende (inkl. Cash) |
|
||||
|
||||
Die Einmalposten stehen bewusst **getrennt** von Kapitalzufluss/-investitionen: Eine Erbschaft
|
||||
ist kein Verkaufserlös und ein Poolbau keine Kapitalinvestition – eine Vermischung würde die
|
||||
Kennzahl falsch beschriften.
|
||||
|
||||
Referenz: `src/components/PlanView.tsx` Zeilen 701–769.
|
||||
|
||||
### 3.6.4 Dashboard
|
||||
@@ -974,6 +1029,8 @@ isConsumption = quotaStart < 0
|
||||
incomplete = cashNegative // „roter Status" = Liquiditätslücke
|
||||
capitalInflow = incomingInflow // aus dem Übergang IN diese Phase
|
||||
capitalInvest = investmentsFromCash + incomingImmediateRepay
|
||||
oneOffInflow = incomingOneOffInflow // einmaliger Zufluss (netto nach Steuer)
|
||||
oneOffOutflow = incomingOneOffOutflow // einmalige Kosten (nominal)
|
||||
```
|
||||
|
||||
## 4.9 Der Übergang
|
||||
@@ -1046,12 +1103,41 @@ falls immediate > 0:
|
||||
falls carry.owed === 0 → carry.status = "SETTLED"
|
||||
```
|
||||
|
||||
### 4.9.6 Abschluss des Übergangs
|
||||
### 4.9.6 Cash: einmalige Sonderein-/ausgaben
|
||||
|
||||
Gelesen wird `phase.cashTransition` – der Entscheid hängt an der **Von**-Phase. Er wird nur
|
||||
ausgewertet, **wenn eine Folgephase existiert**; nach der letzten Phase gibt es keinen Übergang,
|
||||
ein dort erfasster Betrag bleibt wirkungslos.
|
||||
|
||||
Der Umrechnungskurs zwischen real und nominal ist an dieser Grenze `cumulativeInflation`, also
|
||||
der **Bestands-Deflator am Phasenende** (vgl. [4.5.3](#453-die-drei-deflatoren)) – denn Cash ist
|
||||
ein Bestand, und das Ereignis fällt exakt auf die Grenze.
|
||||
|
||||
```
|
||||
cashCarryIn = cashEnd + txInflow − txImmediateRepay
|
||||
incomingInflow = txInflow // Kopf-Kennzahl der Folgephase
|
||||
mode = cashTransition.mode ?? "NONE"
|
||||
|
||||
falls mode ∈ {INFLOW, BOTH}: // nominal erfasst
|
||||
brutto = round(inflowAmount)
|
||||
txOneOffInflow = round(brutto × (1 − inflowTaxRate/100))
|
||||
|
||||
falls mode ∈ {OUTFLOW, BOTH}: // real erfasst
|
||||
txOneOffOutflow = round(outflowAmount × cumulativeInflation)
|
||||
```
|
||||
|
||||
Beide Grössen fliessen ausschliesslich ins Cash der Folgephase (4.9.7) und **nicht** in die
|
||||
Jahresschleife – damit bleiben sie per Konstruktion aus Einkommen, Ausgaben und Quote heraus.
|
||||
Ein Zufluss/eine Kostenposition, die das Cash unter 0 drückt, wird über den bestehenden
|
||||
Startwert-Check der Folgephase (`cashNegative = cash < 0`) automatisch als Liquiditätslücke
|
||||
erkannt.
|
||||
|
||||
### 4.9.7 Abschluss des Übergangs
|
||||
|
||||
```
|
||||
cashCarryIn = cashEnd + txInflow + txOneOffInflow − txImmediateRepay − txOneOffOutflow
|
||||
incomingInflow = txInflow // Kopf-Kennzahlen der Folgephase
|
||||
incomingImmediateRepay = txImmediateRepay
|
||||
incomingOneOffInflow = txOneOffInflow // inkl. Bezeichnung
|
||||
incomingOneOffOutflow = txOneOffOutflow // inkl. Bezeichnung
|
||||
yearsBefore += duration
|
||||
```
|
||||
|
||||
@@ -1212,9 +1298,14 @@ PlanComputed ← an den Client geliefert
|
||||
| `sequenceNumber` | Int | 1-basiert, lückenlos |
|
||||
| `name` | String | |
|
||||
| `durationYears` | Int | 1–80 |
|
||||
| `cashTransition` | Json? | Cash-Entscheid beim Übergang **nach** dieser Phase (siehe 5.4.5) |
|
||||
| `createdAt` / `updatedAt` | DateTime | |
|
||||
| | | `@@unique([planId, sequenceNumber])` |
|
||||
|
||||
`cashTransition` liegt an der Phase und nicht in `ElementTransitionValue`, weil Cash kein
|
||||
`FinancialElement` ist und damit keine `elementId` besitzt. Die Verschlüsselung folgt derselben
|
||||
Logik wie dort: Der Übergang gehört der **Von**-Phase.
|
||||
|
||||
**FinancialElement**
|
||||
|
||||
| Feld | Typ | Constraints |
|
||||
@@ -1293,12 +1384,28 @@ Referenz: `prisma/schema.prisma` Zeilen 4–6, `src/lib/elements.ts` Zeilen 48
|
||||
| `saleTaxRate` | REAL_ESTATE | 0–100 |
|
||||
| `immediateRepayment` | OTHER_DEBT | ≥ 0 |
|
||||
|
||||
Beide Schemas verwenden `.strip()` – **unbekannte Felder werden verworfen**, nicht abgelehnt.
|
||||
### 5.4.5 JSON-Payload `CashTransitionData`
|
||||
|
||||
Liegt in `Phase.cashTransition`. Validierung über `cashTransitionSchema`.
|
||||
|
||||
| Feld | Bedeutung | Zod-Regel |
|
||||
|---|---|---|
|
||||
| `mode` | Entscheid | `NONE` \| `INFLOW` \| `OUTFLOW` \| `BOTH` |
|
||||
| `inflowLabel` | Bezeichnung des Zuflusses (z. B. „Erbschaft") | ≤ 120 Zeichen |
|
||||
| `inflowAmount` | Betrag **nominal** | ≥ 0 |
|
||||
| `inflowTaxRate` | Steuer auf den Zufluss, Default 0 % | 0–100 |
|
||||
| `outflowLabel` | Bezeichnung der Kosten (z. B. „Poolbau") | ≤ 120 Zeichen |
|
||||
| `outflowAmount` | Betrag **real** (heutige Kaufkraft) | ≥ 0 |
|
||||
|
||||
Pro Übergang ist **genau ein** Zufluss und **eine** Kostenposition möglich – siehe
|
||||
[9.7](#97-nur-ein-zufluss-und-eine-kostenposition-pro-übergang).
|
||||
|
||||
Alle Schemas verwenden `.strip()` – **unbekannte Felder werden verworfen**, nicht abgelehnt.
|
||||
Beim Lesen aus der DB gilt zusätzlich: schlägt `safeParse` fehl, wird `{}` zurückgegeben
|
||||
(`parsePhaseData` / `parseTransitionData`) – korrupte Daten führen also nie zu einem Absturz,
|
||||
sondern zu leeren Werten.
|
||||
|
||||
### 5.4.5 Migrationshistorie
|
||||
### 5.4.6 Migrationshistorie
|
||||
|
||||
| Migration | Inhalt |
|
||||
|---|---|
|
||||
@@ -1311,6 +1418,7 @@ sondern zu leeren Werten.
|
||||
| `20260714120000_person_name` | `Person.name` |
|
||||
| `20260715120000_plan_initial_cash` | `Plan.initialCash` |
|
||||
| `20260716210000_drop_phase_inflation_rate` | `Phase.inflationRate` entfernt (Inflation ist plan-weit) |
|
||||
| `20260716230000_phase_cash_transition` | `Phase.cashTransition` (JSONB) für einmalige Sonderein-/ausgaben |
|
||||
|
||||
## 5.5 Frontend-Architektur
|
||||
|
||||
@@ -1469,6 +1577,11 @@ Hängt eine Phase am Ende an, kappt die Dauer, vergibt Default-Name, legt vorbel
|
||||
### `DELETE /api/phases/<phaseId>`
|
||||
Nur die letzte Phase. → 200 `{ ok }` · 400 „Nur die letzte Phase kann geloescht werden."
|
||||
|
||||
### `PUT /api/phases/<phaseId>/cash-transition`
|
||||
Body = `CashTransitionData` (siehe 5.4.5). Speichert den Cash-Entscheid für den Übergang **nach**
|
||||
dieser Phase (einmalige Sonderein-/ausgaben). Schreibt die Spalte `Phase.cashTransition`.
|
||||
→ 200 `{ ok }` · 404 wenn die Phase nicht dem Benutzer gehört.
|
||||
|
||||
## 6.4 Elemente
|
||||
|
||||
### `POST /api/plans/<planId>/elements`
|
||||
@@ -1548,7 +1661,7 @@ Zielumgebung: Hetzner CX23, Traefik als Reverse Proxy, Domain `fpt.aicds.ch`, Gi
|
||||
## 8.1 Teststrategie
|
||||
|
||||
Getestet wird ausschliesslich der Berechnungskern – bewusst, da dort die Fachlogik und das
|
||||
Regressionsrisiko liegen. `src/lib/calculations.test.ts` enthält 13 Tests („V5 Golden Tests"),
|
||||
Regressionsrisiko liegen. `src/lib/calculations.test.ts` enthält 18 Tests („V5 Golden Tests"),
|
||||
ausgeführt mit Vitest in der Node-Umgebung (`vitest.config.ts`, Include `src/**/*.test.ts`).
|
||||
Es gibt **keine** Komponenten-, API- oder E2E-Tests.
|
||||
|
||||
@@ -1568,6 +1681,11 @@ Es gibt **keine** Komponenten-, API- oder E2E-Tests.
|
||||
| **Tilgung stoppt** | Schuld 25'000, Tilgung 10'000/J., 5 Jahre: Gesamtabfluss 25'000 (nicht 50'000), `cashEnd === 75'000`, Restschuld 0 |
|
||||
| **Amortisation stoppt** | Hypothek 15'000, Amortisation 10'000/J., 4 Jahre: `cashEnd === 85'000` (nicht 60'000), Immobilie schuldenfrei |
|
||||
| **Vorbezugssteuer** | PK-Vorbezug 100'000 brutto @ 8 %: `capitalInflow === 92'000`, Restkapital 200'000 (brutto entnommen) |
|
||||
| **Einmaliger Zufluss** | 100'000 nominal @ 10 % Steuer → `oneOffInflow === 90'000`, Cash-Start Folgephase +90'000; Phase 1 hat keinen Zufluss |
|
||||
| **Einmalige Kosten** | 20'000 real, 2 % Inflation, Grenze nach 10 J. → `20'000 × 1.02^10`, entsprechend vom Cash abgezogen |
|
||||
| **Zufluss + Kosten / NONE** | `BOTH`: +50'000 −20'000 → Cash-Start 30'000. `NONE` mit erfassten Beträgen → keine Wirkung |
|
||||
| **Liquiditätslücke durch Kosten** | Kosten 25'000 bei Cash 10'000 → `cashStart === −15'000`, `cashNegative`, `incomplete` |
|
||||
| **Letzte Phase** | Cash-Entscheid der letzten Phase bleibt wirkungslos (kein Übergang mehr) |
|
||||
| Fortschreibung | Einkommens-Basiswert P1 → Startwert P2 = `100'000 × 1.02^5`; `cashStart(P2) === cashEnd(P1)` |
|
||||
|
||||
## 8.3 Ausführung
|
||||
@@ -1635,12 +1753,25 @@ Nominalbeträge, die über die Phasenjahre **konstant** bleiben. Eine Sparrate v
|
||||
20 Jahre lang 10'000 nominal und verliert dabei real an Gewicht. Wer eine mitwachsende Rate
|
||||
abbilden will, muss die Phase teilen und den Betrag in der Folgephase erhöhen.
|
||||
|
||||
## 9.7 `PILLAR_3A_MAX_ANNUAL` wird nur im UI erzwungen
|
||||
## 9.7 Nur ein Zufluss und eine Kostenposition pro Übergang
|
||||
|
||||
`CashTransitionData` hält genau ein Zufluss- und ein Kostenpaar (Bezeichnung + Betrag).
|
||||
„Erbschaft + Autoverkauf + Poolbau + Küche" am selben Übergang lässt sich nur durch
|
||||
Zusammenfassen abbilden („Diverses, 45'000") – die Aufschlüsselung geht dabei verloren.
|
||||
Bewusster Entscheid zugunsten eines einfachen UI; erweiterbar auf Listen.
|
||||
|
||||
## 9.8 Einmalige Ereignisse nur an Phasengrenzen
|
||||
|
||||
Ein Ereignis kann nur an einem Phasenübergang liegen. Ein Poolbau in Jahr 3 einer 10-jährigen
|
||||
Phase ist nur abbildbar, wenn dort eine Phasengrenze gezogen wird. Nach der letzten Phase gibt
|
||||
es keinen Übergang – ein dort erfasster Betrag bleibt wirkungslos (durch Test abgedeckt).
|
||||
|
||||
## 9.9 `PILLAR_3A_MAX_ANNUAL` wird nur im UI erzwungen
|
||||
|
||||
Das Feld ist per `max`-Prop hart geklammert. Das Zod-Schema kennt für `annualContribution` nur
|
||||
`≥ 0` – ein direkter API-Aufruf kann die Obergrenze überschreiten.
|
||||
|
||||
## 9.8 Kleinere Beobachtungen
|
||||
## 9.10 Kleinere Beobachtungen
|
||||
|
||||
- `planToCsv(plan, computed)` erhält den `plan`-Parameter, verwendet ihn aber nicht.
|
||||
- Der Typ `Selection` in `PlanView` hat nur eine Variante (`{ type: "phase" }`) – ein Rest der
|
||||
@@ -1666,6 +1797,7 @@ Das Feld ist per `max`-Prop hart geklammert. Das Zod-Schema kennt für `annualCo
|
||||
| **Phasentyp** | `ERWERB` / `PENSION` / `MIXED`; abgeleitet, nie gespeichert |
|
||||
| **Finanzielles Element** | Plan-weite Entität einer der 8 Kategorien, über alle Phasen identisch |
|
||||
| **Übergang** | Grenze zwischen zwei Phasen; Ort der einmaligen Entscheide |
|
||||
| **Einmalige Sonderein-/ausgabe** | Ereignis am Übergang (Erbschaft, Poolbau), das direkt aufs Cash wirkt und nicht in die Quote eingeht |
|
||||
| **Pensions-Übergang** | Übergang, bei dem der Besitzer des Elements pensioniert wird |
|
||||
| **Carry / Fortschreibung** | Live-Übertragung des Endwerts einer Phase in die nächste |
|
||||
| **Cash** | Systemseitiges Ausgleichskonto; darf negativ werden (Liquiditätslücke) |
|
||||
|
||||
Reference in New Issue
Block a user