Pensionierung: Entscheid ans Element, AHV-Vorbezug/Aufschub, PK-Kapitalquote
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,58 @@ export function sortedPhases(plan: PlanInput) {
|
||||
return [...plan.phases].sort((a, b) => a.sequenceNumber - b.sequenceNumber);
|
||||
}
|
||||
|
||||
// --- Planungshorizont -----------------------------------------------------------------------
|
||||
//
|
||||
// Bis 0.33 ergab sich das Planende stillschweigend als Summe der Phasendauern. Zwei Szenarien
|
||||
// konnten dadurch unbemerkt verschieden weit rechnen -- und waren dann nicht vergleichbar,
|
||||
// obwohl genau das ihr Zweck ist. Neu ist der Horizont eine erfasste Zahl, und die LETZTE
|
||||
// Phase folgt ihr (dieselbe Richtung wie beim Pensionsalter: Zahl stellen, Struktur folgt).
|
||||
//
|
||||
// Referenzperson ist die aelteste: Sie erreicht ihren Horizont zuerst, und der Plan muss so
|
||||
// lange laufen, bis die LETZTE Person ihren erreicht hat.
|
||||
export function planEndYear(plan: PlanInput): number | null {
|
||||
const years = plan.persons
|
||||
.filter((p) => typeof p.planningHorizonAge === "number")
|
||||
.map((p) => (p.planningHorizonAge as number) - p.age);
|
||||
return years.length > 0 ? Math.max(...years) : null;
|
||||
}
|
||||
|
||||
export interface HorizonChange {
|
||||
lastPhaseId: string;
|
||||
oldDuration: number;
|
||||
newDuration: number;
|
||||
blocked: string | null;
|
||||
}
|
||||
|
||||
// Was muesste an der letzten Phase geschehen, damit der Plan bis zum Horizont laeuft?
|
||||
export function planHorizonChange(plan: PlanInput, horizonAge: number, role: PersonRole): HorizonChange | null {
|
||||
const phases = sortedPhases(plan);
|
||||
const last = phases[phases.length - 1];
|
||||
if (!last) return null;
|
||||
const person = plan.persons.find((p) => p.role === role);
|
||||
if (!person) return null;
|
||||
|
||||
// Zielgesamtdauer aus SICHT DIESER Person; die uebrigen Horizonte bleiben unberuehrt und
|
||||
// koennen laenger sein -- deshalb das Maximum ueber alle.
|
||||
const wish = Math.max(
|
||||
horizonAge - person.age,
|
||||
...plan.persons.filter((p) => p.role !== role && typeof p.planningHorizonAge === "number")
|
||||
.map((p) => (p.planningHorizonAge as number) - p.age)
|
||||
);
|
||||
const before = phases.slice(0, -1).reduce((s, p) => s + p.durationYears, 0);
|
||||
const newDuration = wish - before;
|
||||
const change: HorizonChange = {
|
||||
lastPhaseId: last.id,
|
||||
oldDuration: last.durationYears,
|
||||
newDuration,
|
||||
blocked: null,
|
||||
};
|
||||
if (newDuration < 1) {
|
||||
change.blocked = `Der Horizont liegt vor dem Ende der zweitletzten Lebensphase. Die letzte Phase muss mindestens ein Jahr dauern – kürze zuerst eine frühere Phase.`;
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
// Analysiert für JEDE Person, ob und wie weit sich ihr Pensionsalter verschieben lässt.
|
||||
export function retirementBoundaries(plan: PlanInput): RetirementBoundary[] {
|
||||
const phases = sortedPhases(plan);
|
||||
|
||||
Reference in New Issue
Block a user