Drei Berechnungs-Fixes: Phaseninflation, Tilgungsraten, Vorbezugssteuer

- 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>
This commit is contained in:
2026-07-16 22:22:34 +02:00
parent f768e01d61
commit dfebbeb397
12 changed files with 141 additions and 49 deletions
+26 -9
View File
@@ -24,7 +24,6 @@ export interface CellContext {
carriedEndValue: number; // Endwert des Elements in der (Vor-)Phase, fuer Bezugs-Maxima
carried: boolean; // Phase >= 2: Basiswert wird aus der Vorphase fortgeschrieben
derivedStart: number; // fortgeschriebener Basiswert (read-only Anzeige)
phaseInflation: number; // Plan-Inflationsrate (Info)
deflatorStart: number; // Kaufkraft-Deflator zu Phasenbeginn (real <-> nominal, erstes Jahr)
}
@@ -49,7 +48,9 @@ function DerivedField({ label, value, help }: { label: string; value: number; he
);
}
// PK/3a-Bezugs-Entscheid im normalen Uebergang: Kein Bezug / Bezug (+ Betrag).
// PK/3a-Bezugs-Entscheid im normalen Uebergang (Vorbezug): Kein Bezug / Bezug (+ Betrag +
// Kapitalbezugssteuer). Der Bezugsbetrag wird brutto dem Kapital entnommen; ins Cash fliesst
// der Betrag nach Abzug der Steuer.
function WithdrawalDecision({
td,
setT,
@@ -62,6 +63,8 @@ function WithdrawalDecision({
label: string;
}) {
const mode = td.withdrawalMode ?? "NONE";
const gross = num(td.withdrawal);
const taxRate = num(td.capitalTaxRate, DEFAULT_CAPITAL_TAX_RATE);
return (
<>
<SelectField
@@ -74,13 +77,27 @@ function WithdrawalDecision({
]}
/>
{mode === "AMOUNT" && (
<MoneyField
label={label}
help={`Maximal ${formatChf(max)} (Endwert der Vorphase).`}
value={num(td.withdrawal)}
max={max}
onChange={(v) => setT({ withdrawal: v })}
/>
<>
<MoneyField
label={label}
help={`Bruttobetrag, dem Kapital entnommen. Maximal ${formatChf(max)} (Endwert der Vorphase).`}
value={gross}
max={max}
onChange={(v) => setT({ withdrawal: v })}
/>
<NumberField
label="Kapitalbezugssteuer (%)"
help="Ein Vorbezug ist wie der Bezug bei Pensionierung kapitalbezugssteuerpflichtig."
step={0.5}
value={taxRate}
onChange={(v) => setT({ capitalTaxRate: v })}
/>
<DerivedField
label="Auszahlung netto (ins Cash)"
value={Math.round(gross * (1 - taxRate / 100))}
help="Bruttobezug abzueglich Kapitalbezugssteuer. Wird automatisch berechnet."
/>
</>
)}
</>
);