V5-Modell: Einkommen nominal, Ausgaben real->nominal, Inflation plan-weit, Sparquoten-Grafik
Deploy App / deploy (push) Successful in 57s
Deploy App / deploy (push) Successful in 57s
- Einkommen: nominale Basis + nominale Lohnerhoehung (Default 0). Real read-only als Info. - Ausgaben: REALE Basis (heutige Kaufkraft) + reale Mehrausgaben (Default 0); nominal = real x plan-weite Inflation, read-only. Loest die "nominale Ausgaben verwirren"-Problematik. - Inflation nur noch plan-weit (Phasen-Override entfernt). - Engine liefert flowDeflatorEnd (Flow-Realwerte) + yearly-Serie (Jahr/Alter/Einkommen/ Ausgabe nominal/real). Nominal/Real-Umschalter nutzt Flow- vs. Bestands-Deflatoren. - Neue Grafik (Dashboard): Einkommen vs. nominale Ausgabe mit eingefaerbter Sparquoten- Flaeche (gruen/rot) + reale Ausgabe als Referenzlinie (Inflationskeil). - In-Tool-Erklaerungen in den Einkommen/Ausgaben-Popups. - Golden Tests aufs neue Modell hergeleitet (8 gruen, u.a. Ausgaben real->nominal, Ruin 94). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -176,6 +176,7 @@ export function PlanView({
|
||||
carried: ce?.carried ?? false,
|
||||
derivedStart: ce?.baseValue ?? 0,
|
||||
phaseInflation: phaseInflationFor(phase.id),
|
||||
deflatorStart: phase.cumulativeInflationStart,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -192,6 +193,7 @@ export function PlanView({
|
||||
carried: ce?.carried ?? false,
|
||||
derivedStart: 0,
|
||||
phaseInflation: phaseInflationFor(fromPhase.id),
|
||||
deflatorStart: fromPhase.cumulativeInflationStart,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -617,7 +619,6 @@ export function PlanView({
|
||||
phase={phaseInput}
|
||||
maxDurationYears={phase.maxDurationYears}
|
||||
isLast={isLast}
|
||||
inflationDefault={plan.inflationRateDefault}
|
||||
onSaved={onChanged}
|
||||
onDeleted={() => {
|
||||
setSelected(null);
|
||||
@@ -681,8 +682,9 @@ function phaseCellContent(
|
||||
): React.ReactNode {
|
||||
if (!ce) return "–";
|
||||
if (ce.note) return ce.note;
|
||||
const isFlow = ce.category === "INCOME" || ce.category === "EXPENSE";
|
||||
const dS = phase.cumulativeInflationStart;
|
||||
const dE = phase.cumulativeInflationEnd;
|
||||
const dE = isFlow ? phase.flowDeflatorEnd : phase.cumulativeInflationEnd;
|
||||
if (START_END_CATEGORIES.includes(ce.category) && (ce.startValue !== 0 || ce.endValue !== 0)) {
|
||||
return (
|
||||
<span className="whitespace-nowrap">
|
||||
@@ -711,7 +713,8 @@ function PhaseHeader({
|
||||
}) {
|
||||
const quotaLabel = phase.isConsumption ? "Verzehr" : "Quote";
|
||||
const dS = phase.cumulativeInflationStart;
|
||||
const dE = phase.cumulativeInflationEnd;
|
||||
const dE = phase.cumulativeInflationEnd; // Bestandswerte (Cash, Vermoegen)
|
||||
const dF = phase.flowDeflatorEnd; // Flow-Werte (Einkommen, Ausgaben, Quote)
|
||||
return (
|
||||
<th
|
||||
onClick={onClick}
|
||||
@@ -739,10 +742,10 @@ function PhaseHeader({
|
||||
{personLabel(p.role)} {p.startAge} → {p.endAge}
|
||||
</div>
|
||||
))}
|
||||
<div>Einkommen {valStr(phase.incomeStart, dS, mode)} → {valStr(phase.incomeEnd, dE, mode)}</div>
|
||||
<div>Ausgaben {valStr(phase.expenseStart, dS, mode)} → {valStr(phase.expenseEnd, dE, mode)}</div>
|
||||
<div>Einkommen {valStr(phase.incomeStart, dS, mode)} → {valStr(phase.incomeEnd, dF, mode)}</div>
|
||||
<div>Ausgaben {valStr(phase.expenseStart, dS, mode)} → {valStr(phase.expenseEnd, dF, mode)}</div>
|
||||
<div>
|
||||
{quotaLabel} {valStr(phase.quotaStart, dS, mode)} → {valStr(phase.quotaEnd, dE, mode)}
|
||||
{quotaLabel} {valStr(phase.quotaStart, dS, mode)} → {valStr(phase.quotaEnd, dF, mode)}
|
||||
</div>
|
||||
<div className={phase.cashNegative ? "text-danger font-medium" : ""}>
|
||||
Cash {valStr(phase.cashStart, dS, mode)} → {valStr(phase.cashEnd, dE, mode)}
|
||||
@@ -842,7 +845,8 @@ function AddElementDialog({
|
||||
carriedEndValue: 0,
|
||||
carried: false,
|
||||
derivedStart: 0,
|
||||
phaseInflation: plan.phases.find((p) => p.id === firstPhase.id)?.inflationRate ?? plan.inflationRateDefault,
|
||||
phaseInflation: plan.inflationRateDefault,
|
||||
deflatorStart: firstPhase.cumulativeInflationStart,
|
||||
};
|
||||
|
||||
async function create() {
|
||||
|
||||
Reference in New Issue
Block a user