Stammdaten gewinnen in Phase 1, Bestaetigung je Zeile statt pauschal
Deploy App / deploy (push) Successful in 1m10s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 21:41:07 +02:00
parent ce987b9978
commit f9d7ca07fd
5 changed files with 223 additions and 37 deletions
+16 -4
View File
@@ -545,12 +545,15 @@ export function ElementPhaseFields({
// wird er in der Spalte «Start». Bis 0.39 stand hier ein Eingabefeld, das
// `phaseValues[phase1]` schrieb und die Stammdaten still überschattete (der Rechenkern
// legt sie als `{...baseData, ...phaseValues}` übereinander): dieselbe Zahl an zwei Orten.
// Dieselbe Vorrangregel wie im Rechenkern (`firstPhaseValues`): Wo die Stammdaten einen Wert
// tragen, gewinnen SIE -- ein Phasenwert darf sie nicht überschatten. Der Rückfall auf den
// Phasenwert bleibt nur, solange die Stammdaten leer sind.
const bd = context.baseData;
const start = (key: "amount" | "currentValue" | "startValue" | "purchasePrice" | "mortgage", label: string, help?: string) => (
<LinkedField
label={label}
help={help}
value={Math.round(num(pd[key], num(bd[key])))}
value={Math.round(typeof bd[key] === "number" ? (bd[key] as number) : num(pd[key]))}
actionLabel="Startwert bearbeiten"
onAction={context.onEditBase}
/>
@@ -589,8 +592,13 @@ export function ElementPhaseFields({
const isIncome = element.category === "INCOME";
// Basiswert (erstes Jahr). Ab Phase 2 mit dem fortgeschriebenen Wert der Vorphase
// vorbelegt, aber bewusst änderbar (Teilzeit, Beförderung, Jobwechsel …).
const baseValue =
typeof pd.amount === "number" ? pd.amount : carried ? context.derivedStart : num(bd.amount);
const baseValue = carried
? typeof pd.amount === "number"
? pd.amount
: context.derivedStart
: typeof bd.amount === "number"
? bd.amount
: num(pd.amount);
const d = context.deflatorStart || 1;
// Info-Gegenwert im ersten Jahr: Einkommen -> real; Ausgaben -> nominal.
const otherValue = isIncome ? Math.round(baseValue / d) : Math.round(baseValue * d);
@@ -815,7 +823,11 @@ export function ElementPhaseFields({
case "REAL_ESTATE": {
// Zinsbetrag zu Phasenbeginn und -ende: die Restschuld sinkt mit der Amortisation,
// der Zinsbetrag also mit. Am Nullpunkt gekappt (analog zur Berechnung).
const hypStart = carried ? context.derivedMortgage : num(pd.mortgage, num(bd.mortgage));
const hypStart = carried
? context.derivedMortgage
: typeof bd.mortgage === "number"
? bd.mortgage
: num(pd.mortgage);
const amortEff = num(pd.amortization, num(context.inheritedValues.amortization));
const hypEnde = Math.max(0, hypStart - amortEff * context.durationYears);
const zinsStart = Math.round((hypStart * num(pd.interestRate)) / 100);