Modul-Review 4: Matrix -- Kapitalverwendung, Phasendauer, Bedienung
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:
2026-07-25 23:09:03 +02:00
parent 0761f6b3e2
commit 0953880a80
17 changed files with 1040 additions and 267 deletions
+17 -11
View File
@@ -122,6 +122,20 @@ export interface TransitionData {
extraAmortization?: number;
// OTHER_DEBT
immediateRepayment?: number;
// Verwendung des BEZOGENEN KAPITALS (Roadmap Nr. 44, Punkt C).
//
// Gilt für PENSION_FUND (nur bei Kapitalbezug) und PILLAR_3A am Pensions-Übergang: Wohin
// fliesst das ausbezahlte Alterskapital? Bewusst in PROZENT und nicht in Franken -- wird
// das Pensionsalter verschoben, ändert sich der Betrag, und eine Quote skaliert mit,
// während eine Frankenzahl still falsch würde. Der nicht zugeteilte Rest bleibt Cash.
//
// Bis 0.32 lagen diese Felder am CASH-Übergang. Das war der falsche Ort: Die Frage gehört
// zum Bezugs-Entscheid des jeweiligen Vorsorgeguthabens, nicht zum Cash-Konto -- und mit
// zwei Guthaben (PK und 3a) liess sie sich dort gar nicht getrennt beantworten.
capitalUseAmortizationPct?: number;
capitalUseInvestPct?: number;
// Ziel der Anlage-Quote; ohne Angabe das erste aktive «Sonstiges Vermögen».
capitalUseTargetElementId?: string;
}
// --- Cash-Übergang: einmalige Sonderein-/ausgaben ---
@@ -140,14 +154,6 @@ export interface CashTransitionData {
// Einmalige Kosten (z. B. Poolbau): REAL erfasst (heutige Kaufkraft).
outflowLabel?: string;
outflowAmount?: number;
// Verwendung des Kapitalzuflusses am Pensions-Übergang (Roadmap Nr. 44, Punkt C).
// Bewusst in PROZENT und nicht in Franken: Verschiebt man das Pensionsalter, ändert sich
// das bezogene Kapital -- eine Franken-Angabe müsste man dann von Hand nachziehen, eine
// Quote skaliert mit. Der nicht zugeteilte Rest bleibt Cash.
capitalUseAmortizationPct?: number;
capitalUseInvestPct?: number;
// Ziel der Anlage-Quote; ohne Angabe das erste aktive «Sonstiges Vermögen».
capitalUseTargetElementId?: string;
}
// --- Zod-Schemas (nachsichtig: unbekannte Felder werden verworfen) ---
@@ -162,9 +168,6 @@ export const cashTransitionSchema = z
inflowTaxRate: z.number().min(0).max(100).optional(),
outflowLabel: z.string().max(120).optional(),
outflowAmount: nonNeg.optional(),
capitalUseAmortizationPct: z.number().min(0).max(100).optional(),
capitalUseInvestPct: z.number().min(0).max(100).optional(),
capitalUseTargetElementId: z.string().max(60).optional(),
})
.strip();
@@ -210,6 +213,9 @@ export const transitionDataSchema = z
partialSaleAmount: nonNeg.optional(),
extraAmortization: nonNeg.optional(),
immediateRepayment: nonNeg.optional(),
capitalUseAmortizationPct: z.number().min(0).max(100).optional(),
capitalUseInvestPct: z.number().min(0).max(100).optional(),
capitalUseTargetElementId: z.string().max(60).optional(),
})
.strip();