// «Ein Wert, ein Ort» -- durchgesetzt im Rechenkern, nicht nur in der Oberfläche // (SPEZIFIKATION 3.14.3). // // Der Bestand bei Planbeginn gehört in die Stammdaten. In der ersten Phase stand dafür bis // 0.39 zusätzlich ein Eingabefeld; eine dort gespeicherte Zahl überschattete die Stammdaten // still. Seit 0.40 ist das Feld read-only -- womit so ein Altwert unerreichbar WÄRE, wenn er // weiterhin gewönne. Deshalb entscheidet die Regel der Rechenkern. import { describe, it, expect } from "vitest"; import { computePlan, firstPhaseValues } from "@/lib/calculations"; import type { PlanInput } from "@/lib/types"; function plan(elements: PlanInput["elements"]): PlanInput { return { id: "plan", name: "T", householdType: "SINGLE", inflationRateDefault: 0, initialCash: 0, startYear: 2026, persons: [{ id: "A", role: "PERSON_A", name: null, age: 40, retirementAge: 65 }], phases: [{ id: "p1", sequenceNumber: 1, name: "P1", durationYears: 10, cashTransition: { mode: "NONE" } }], elements, }; } function haus(phaseValues: Record>) { return [ { id: "e1", category: "REAL_ESTATE" as never, name: "Haus", ownerRole: "HOUSEHOLD" as never, orderIndex: 1, baseData: { purchasePrice: 800000, mortgage: 500000 } as Record, phaseValues: phaseValues as never, transitionValues: {}, }, ]; } describe("Bestandsfelder in der ersten Phase", () => { it("nimmt den Bestand aus den Stammdaten", () => { const c = computePlan(plan(haus({}))); expect(c.phases[0].elements[0].startValue).toBe(300000); }); it("lässt sich von einem Phasenwert NICHT überschatten", () => { // Genau der Fall aus der Testrunde: In 0.39 schrieb das Speichern der Zelle eine 0 -- // seither stand das Haus mit Startwert 0 da, ohne dass man es noch korrigieren konnte. const c = computePlan(plan(haus({ p1: { confirmed: true, purchasePrice: 0, mortgage: 0 } }))); expect(c.phases[0].elements[0].startValue).toBe(300000); }); it("fällt auf den Phasenwert zurück, solange die Stammdaten leer sind", () => { // Ohne diesen Rückfall wären Pläne aus der Zeit vor den Stammdaten schlagartig auf 0. const els = haus({ p1: { purchasePrice: 600000, mortgage: 400000 } }); els[0].baseData = {}; expect(computePlan(plan(els)).phases[0].elements[0].startValue).toBe(200000); }); it("lässt die ANNAHMEN in der ersten Phase überschreibbar", () => { // Eine Rendite gilt für einen Zeitraum, kein Anfangsbestand -- sie darf je Phase abweichen. const merged = firstPhaseValues( { startValue: 100000, expectedReturn: 3 }, { expectedReturn: 7, startValue: 0 } ); expect(merged.expectedReturn).toBe(7); expect(merged.startValue).toBe(100000); }); });