Memo 2026081701: Kapitalverwendung mit waehlbarem Tilgungsziel, AHV automatisch, Farb- und Textkorrekturen
Deploy App / deploy (push) Successful in 1m18s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 20:04:45 +02:00
parent f9d7ca07fd
commit 113616cc1f
9 changed files with 485 additions and 116 deletions
+92
View File
@@ -0,0 +1,92 @@
// Verwendung des bezogenen Alterskapitals: das Tilgungs-Ziel ist wählbar (0.41).
//
// Bis 0.40 floss die Tilgungs-Quote stur in die erstbeste Immobilie. Wer neben einer Hypothek
// zu 1,5 % einen Konsumkredit zu 6 % trägt, will aber zuerst den Kredit los -- und hatte keine
// Möglichkeit, das zu sagen.
import { describe, it, expect } from "vitest";
import { computePlan } from "@/lib/calculations";
import type { PlanInput } from "@/lib/types";
function plan(debtTarget?: string): PlanInput {
return {
id: "plan",
name: "T",
householdType: "SINGLE",
inflationRateDefault: 0,
initialCash: 0,
startYear: 2026,
persons: [{ id: "A", role: "PERSON_A", name: null, age: 64, retirementAge: 65 }],
phases: [
{ id: "p1", sequenceNumber: 1, name: "Erwerb", durationYears: 1, cashTransition: { mode: "NONE" } },
{ id: "p2", sequenceNumber: 2, name: "Pension", durationYears: 5, cashTransition: { mode: "NONE" } },
],
elements: [
{
id: "pk",
category: "PENSION_FUND" as never,
name: "PK",
ownerRole: "PERSON_A" as never,
orderIndex: 1,
baseData: { currentValue: 400000, expectedReturn: 0 },
phaseValues: { p1: {}, p2: {} },
transitionValues: {},
// Volles Kapital, keine Steuer, alles in die Tilgung: 400'000 stehen zur Verfügung.
retirementDecision: {
capitalSharePct: 100,
capitalTaxRate: 0,
conversionRate: 6,
capitalUseAmortizationPct: 100,
...(debtTarget ? { capitalUseDebtTargetElementId: debtTarget } : {}),
} as never,
},
{
id: "haus",
category: "REAL_ESTATE" as never,
name: "Haus",
ownerRole: "HOUSEHOLD" as never,
orderIndex: 2,
baseData: { purchasePrice: 900000, mortgage: 300000, interestRate: 1.5, valueGrowth: 0 },
phaseValues: { p1: {}, p2: {} },
transitionValues: { p1: { decision: "HOLD" as never } },
},
{
id: "kredit",
category: "OTHER_DEBT" as never,
name: "Konsumkredit",
ownerRole: "HOUSEHOLD" as never,
orderIndex: 3,
baseData: { startValue: 100000 },
phaseValues: { p1: {}, p2: {} },
transitionValues: {},
},
],
};
}
const restOf = (p: PlanInput, id: string) => {
const c = computePlan(p);
const ph = c.phases[1];
const ce = ph.elements.find((e) => e.elementId === id)!;
return id === "haus" ? ce.mortgageStart : Math.abs(ce.startValue);
};
describe("Schuldentilgung aus dem Alterskapital", () => {
it("tilgt ohne Wahl weiterhin die Hypothek", () => {
// Bestandsschutz: Pläne aus der Zeit vor der Zielwahl müssen unverändert rechnen.
const p = plan();
expect(restOf(p, "haus")).toBe(0);
expect(restOf(p, "kredit")).toBe(100000);
});
it("tilgt den gewählten Kredit zuerst", () => {
const p = plan("kredit");
expect(restOf(p, "kredit")).toBe(0);
});
it("lässt eine nicht gewählte Schuld unberührt, wenn die Hypothek gewählt ist", () => {
const p = plan("haus");
expect(restOf(p, "haus")).toBe(0);
expect(restOf(p, "kredit")).toBe(100000);
});
});