Pensionierungs-Bildschirm, Ampel mit drei Zustaenden, Planungshorizont
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,6 @@ import { CATEGORY_LABELS, num, type InheritableKey } from "@/lib/elements";
|
||||
import {
|
||||
AHV_REFERENCE_AGE,
|
||||
DEFAULT_CAPITAL_TAX_RATE,
|
||||
DEFAULT_PK_CONVERSION_RATE,
|
||||
DEFAULT_PROPERTY_GAINS_TAX_RATE,
|
||||
PILLAR_3A_MAX_ANNUAL,
|
||||
PILLAR_3A_MAX_SELF_EMPLOYED,
|
||||
@@ -881,11 +880,15 @@ export function ElementTransitionFields({
|
||||
context,
|
||||
td,
|
||||
setT,
|
||||
retirement,
|
||||
}: {
|
||||
element: { category: ElementCategory };
|
||||
context: CellContext;
|
||||
td: TransitionData;
|
||||
setT: (patch: Partial<TransitionData>) => void;
|
||||
// Der fertig gerenderte Pensionierungs-Baustein (AHV/PK/3a). Wird vom Aufrufer geliefert,
|
||||
// damit dieses Modul nichts über den Pensionierungs-Bildschirm wissen muss.
|
||||
retirement?: React.ReactNode;
|
||||
}) {
|
||||
switch (element.category) {
|
||||
case "INCOME":
|
||||
@@ -897,8 +900,10 @@ export function ElementTransitionFields({
|
||||
</p>
|
||||
);
|
||||
case "AHV":
|
||||
if (context.isRetirementTransition && context.ahvCareer) {
|
||||
return <AhvReviewFields career={context.ahvCareer} td={td} setT={setT} />;
|
||||
// Der Bezugs-Entscheid liegt seit 0.34 am Element und wird hier nur ANDERS ANGESCHAUT --
|
||||
// es ist dieselbe Komponente wie im Pensionierungs-Bildschirm, kein Duplikat.
|
||||
if (context.isRetirementTransition && retirement) {
|
||||
return <div className="col-span-2">{retirement}</div>;
|
||||
}
|
||||
return (
|
||||
<p className="col-span-2 text-sm text-muted">
|
||||
@@ -906,103 +911,14 @@ export function ElementTransitionFields({
|
||||
</p>
|
||||
);
|
||||
case "PENSION_FUND": {
|
||||
if (context.isRetirementTransition) {
|
||||
const mode = td.payoutMode ?? "PENSION";
|
||||
const taxRate = num(td.capitalTaxRate, DEFAULT_CAPITAL_TAX_RATE);
|
||||
// Brutto = ganzes Guthaben (Kapitalbezug) bzw. der gewählte Teil (Kombination).
|
||||
const brutto =
|
||||
mode === "COMBI"
|
||||
? Math.min(context.carriedEndValue, Math.round(num(td.capitalAmount)))
|
||||
: context.carriedEndValue;
|
||||
const netto = Math.round(brutto * (1 - taxRate / 100));
|
||||
return (
|
||||
<>
|
||||
<SelectField
|
||||
label="Bezugsart bei Pensionierung"
|
||||
value={mode}
|
||||
onChange={(v: "CAPITAL" | "PENSION" | "COMBI") => setT({ payoutMode: v })}
|
||||
options={[
|
||||
{ value: "PENSION", label: "Rente" },
|
||||
{ value: "CAPITAL", label: "Kapitalbezug" },
|
||||
{ value: "COMBI", label: "Kombination" },
|
||||
]}
|
||||
/>
|
||||
{(mode === "PENSION" || mode === "COMBI") && (
|
||||
<NumberField
|
||||
label="Umwandlungssatz (%)"
|
||||
help="Jährliche Rente = verrentetes Kapital x Umwandlungssatz."
|
||||
step={0.1}
|
||||
value={num(td.conversionRate, DEFAULT_PK_CONVERSION_RATE)}
|
||||
onChange={(v) => setT({ conversionRate: v })}
|
||||
/>
|
||||
)}
|
||||
{mode === "COMBI" && (
|
||||
<MoneyField
|
||||
label="Davon Kapitalbezug (CHF)"
|
||||
help={`Der Rest wird verrentet. Maximal ${formatChf(context.carriedEndValue)}.`}
|
||||
value={num(td.capitalAmount)}
|
||||
max={context.carriedEndValue}
|
||||
onChange={(v) => setT({ capitalAmount: v })}
|
||||
/>
|
||||
)}
|
||||
{/* Erst der Betrag, dann die Steuer, dann die Verwendung -- in der Reihenfolge,
|
||||
in der man die Entscheidung tatsächlich trifft. */}
|
||||
{(mode === "CAPITAL" || mode === "COMBI") && (
|
||||
<>
|
||||
<DerivedField
|
||||
label="Kapitalbezug brutto"
|
||||
value={brutto}
|
||||
help="Das Guthaben am Ende der Vorphase (bei einer Kombination der oben gewählte Anteil)."
|
||||
/>
|
||||
<NumberField
|
||||
label="Kapitalbezugssteuer (%)"
|
||||
help="Pauschalsatz – die tatsächliche Steuer ist kantonal und progressiv."
|
||||
step={0.5}
|
||||
value={taxRate}
|
||||
onChange={(v) => setT({ capitalTaxRate: v })}
|
||||
/>
|
||||
<DerivedField
|
||||
label="Auszahlung netto"
|
||||
value={netto}
|
||||
help="Brutto abzüglich Kapitalbezugssteuer. Dieser Betrag wird unten verteilt."
|
||||
/>
|
||||
<CapitalUseFields td={td} setT={setT} netAmount={netto} targets={context.investTargets} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
if (context.isRetirementTransition && retirement) {
|
||||
return <div className="col-span-2">{retirement}</div>;
|
||||
}
|
||||
return <WithdrawalDecision td={td} setT={setT} max={context.carriedEndValue} label="PK-Bezug (CHF)" />;
|
||||
}
|
||||
case "PILLAR_3A": {
|
||||
if (context.isRetirementTransition) {
|
||||
// Die Säule 3a wird bei der Pensionierung IMMER vollständig bezogen -- entschieden
|
||||
// wird hier der Steuersatz und die Verwendung des Geldes.
|
||||
const taxRate = num(td.capitalTaxRate, DEFAULT_CAPITAL_TAX_RATE);
|
||||
const brutto = context.carriedEndValue;
|
||||
const netto = Math.round(brutto * (1 - taxRate / 100));
|
||||
return (
|
||||
<>
|
||||
<p className="col-span-2 rounded-lg bg-surface-2 px-3 py-2 text-xs text-muted">
|
||||
Die Säule 3a wird bei der Pensionierung <strong className="text-fg">vollständig bezogen</strong>. Zu
|
||||
entscheiden sind der Steuersatz und die Verwendung des Geldes.
|
||||
</p>
|
||||
<DerivedField label="Bezug brutto" value={brutto} help="Das Guthaben am Ende der Vorphase." />
|
||||
<NumberField
|
||||
label="Kapitalbezugssteuer (%)"
|
||||
help="Pauschalsatz – die tatsächliche Steuer ist kantonal und progressiv. Gestaffelte Bezüge (PK und 3a in verschiedenen Jahren) senken sie; das bildet das Tool noch nicht ab."
|
||||
step={0.5}
|
||||
value={taxRate}
|
||||
onChange={(v) => setT({ capitalTaxRate: v })}
|
||||
/>
|
||||
<DerivedField
|
||||
label="Auszahlung netto"
|
||||
value={netto}
|
||||
help="Brutto abzüglich Kapitalbezugssteuer. Dieser Betrag wird unten verteilt."
|
||||
/>
|
||||
<CapitalUseFields td={td} setT={setT} netAmount={netto} targets={context.investTargets} />
|
||||
</>
|
||||
);
|
||||
if (context.isRetirementTransition && retirement) {
|
||||
return <div className="col-span-2">{retirement}</div>;
|
||||
}
|
||||
return <WithdrawalDecision td={td} setT={setT} max={context.carriedEndValue} label="3a-Bezug (CHF)" />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user