diff --git a/src/lib/calculations.ts b/src/lib/calculations.ts index b148eae..160a302 100644 --- a/src/lib/calculations.ts +++ b/src/lib/calculations.ts @@ -187,13 +187,42 @@ export function computePlan(plan: PlanInput): PlanComputed { } // --- Elemente dieser Phase berechnen --- + const orderedElements = [...plan.elements].sort((a, b) => a.orderIndex - b.orderIndex); + + // --- Vorlauf: Quoten-Vorzeichen bestimmen (Einkommen inkl. Renten minus Ausgaben) --- + // Wird VOR der Element-Schleife gebraucht, damit sonstiges Vermoegen in Verzehrphasen + // die Rate abzieht (Bezug) statt sie zu addieren (Sparen). + let preIncome = 0; + let preExpense = 0; + for (const e of orderedElements) { + const carry = carries.get(e.id)!; + if (carry.status !== "ACTIVE") continue; + const pd = e.phaseValues[phase.id] ?? {}; + const owner = e.ownerRole && e.ownerRole !== "HOUSEHOLD" ? personByRole(persons, e.ownerRole) : null; + const ownerWorking = owner ? workingByPerson.get(owner.id) ?? false : anyWorking; + switch (e.category) { + case "INCOME": + preIncome += Math.round(num(pd.amount)); + break; + case "EXPENSE": + preExpense += Math.round(num(pd.amount)); + break; + case "AHV": + if (owner && !ownerWorking) preIncome += ahvFinal.get(owner.id) ?? 0; + break; + case "PENSION_FUND": + if (!ownerWorking && carry.pkPensionAnnual > 0) preIncome += carry.pkPensionAnnual; + break; + } + } + const isConsumptionPhase = preIncome - preExpense < 0; + const elementsComputed: ElementPhaseComputed[] = []; let incomeTotal = 0; let expenseTotal = 0; let quotaAllocated = 0; let capitalUsed = 0; - const orderedElements = [...plan.elements].sort((a, b) => a.orderIndex - b.orderIndex); for (const e of orderedElements) { const carry = carries.get(e.id)!; const pd = e.phaseValues[phase.id] ?? {}; @@ -312,11 +341,13 @@ export function computePlan(plan: PlanInput): PlanComputed { ec.startValue = start; ec.capitalUse = topUp; capitalUsed += topUp; - // In Erwerbsphasen Sparbeitrag, in Verzehrphasen Bezugsrate -- beides zaehlt gegen - // die Quote (Vorzeichen ergibt sich aus der Phasenquote). + // In Erwerbsphasen Sparbeitrag (wird eingezahlt/waechst), in Verzehrphasen + // Bezugsrate (wird entnommen/mindert das Vermoegen). Beides zaehlt betragsmaessig + // gegen die Quote. ec.quotaUse = contribution; quotaAllocated += contribution; - ec.endValue = growAsset(start, r, contribution, phase.durationYears); + const annual = isConsumptionPhase ? -contribution : contribution; + ec.endValue = growAsset(start, r, annual, phase.durationYears); ec.summary = fmt(ec.endValue); break; }