Phasenkopf neu + Bezugsrate (Verzehrrate) beim Sonstigen Vermoegen
Deploy App / deploy (push) Successful in 1m2s

- Sonstiges Vermoegen bekommt "Jaehrliche Bezugsrate (Entnahme)": mindert das Vermoegen
  (gekappt am Bestand) und fliesst jaehrlich ins Cash.
- Phasenkopf neu strukturiert: Einkommen / Ausgaben / Quote, dann Geplante Sparrate
  (3a + Vermoegen-Sparbeitrag + Amortisation + Tilgung) und Geplante Verzehrrate
  (Bezugsraten), dann Kapitalzufluss (Verkaeufe + PK-/3a-Bezuege aus dem Uebergang) und
  Kapitalinvestitionen (Zusatz-/Neuinvestitionen + sofortige Tilgungen), dann Vermoegen.
  Die Cash-Zeile im Kopf entfaellt (die Cash-Zeile in der Matrix bleibt).
- Engine liefert plannedSaveRate/plannedWithdrawRate/capitalInflow/capitalInvest.
- Golden Tests: Bezugsrate ins Cash + Kapitalzufluss/-investitionen (10 gruen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 23:11:40 +02:00
parent 435bef6026
commit 3acac56640
5 changed files with 99 additions and 23 deletions
+35
View File
@@ -129,6 +129,41 @@ describe("V5 Golden Tests", () => {
expect(ph.incomeEnd).toBe(80000);
});
it("Bezugsrate aus Sonstigem Vermoegen fliesst ins Cash (Verzehrrate)", () => {
const p = plan({
age: 65,
retirementAge: 65,
inflation: 0,
phases: [{ id: "p1", durationYears: 3 }],
elements: [el("OTHER_ASSET", "HOUSEHOLD", { p1: { startValue: 30000, expectedReturn: 0, annualContribution: 0, annualWithdrawal: 10000 } })],
});
const ph = computePlan(p).phases[0];
expect(ph.plannedWithdrawRate).toBe(10000);
expect(ph.cashEnd).toBe(30000); // 3 x 10'000 Entnahme -> Cash
const asset = ph.elements.find((e) => e.category === "OTHER_ASSET")!;
expect(asset.endValue).toBe(0);
});
it("Kapitalzufluss/-investitionen: Verkauf in Phase 1, Reinvestition in Phase 2", () => {
const p = plan({
age: 40,
retirementAge: 70,
inflation: 0,
phases: [
{ id: "p1", durationYears: 1 },
{ id: "p2", durationYears: 1 },
],
elements: [
el("OTHER_ASSET", "HOUSEHOLD", { p1: { startValue: 10000, expectedReturn: 0, annualContribution: 0 }, p2: {} }, { p1: { decision: "SELL" } }),
el("OTHER_ASSET", "HOUSEHOLD", { p1: { startValue: 0, expectedReturn: 0, annualContribution: 0 }, p2: { additionalInvestment: 10000, expectedReturn: 0 } }),
],
});
const p2 = computePlan(p).phases[1];
expect(p2.capitalInflow).toBe(10000); // Verkaufserloes aus dem Uebergang
expect(p2.capitalInvest).toBe(10000); // Zusatzinvestition
expect(p2.cashEnd).toBe(0);
});
it("Cash-Anfangswert fliesst in die erste Phase ein", () => {
const p = plan({
age: 40,