Fix: Server/Client-Grenze -- Uebergangsregeln nach lib verschoben
Deploy App / deploy (push) Successful in 1m5s
Deploy App / deploy (push) Successful in 1m5s
Ursache des 500 (danke fuer die Meldung): lib/decisions.ts importierte isTransitionAnswered und isCashTransitionAnswered aus der CLIENT- Komponente ElementDetail. Der PDF-Bericht laeuft serverseitig und brach deshalb ab: "Attempted to call isCashTransitionAnswered() from the server but it is on the client." Die fuenf reinen Uebergangs-Regeln liegen jetzt in lib/transitions.ts; ElementDetail reicht sie nur noch weiter, damit bestehende Importe unveraendert bleiben. Neuer Waechter-Test: kein Modul unter src/lib darf aus src/components importieren. Gegen den echten Fehler verifiziert -- er schlaegt an. Weder tsc noch der Build hatten das gemeldet, nur die Produktion. 225 Tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,15 @@ import { AlertTriangle } from "lucide-react";
|
||||
import { FieldLabel, MoneyField, NumberField, SelectField, TextField } from "@/components/FormField";
|
||||
import { formatChf } from "@/lib/format";
|
||||
import { api } from "@/lib/api-client";
|
||||
// Die reinen Uebergangs-Regeln liegen in lib/transitions.ts (auch serverseitig nutzbar) und
|
||||
// werden hier nur weitergereicht, damit bestehende Importe unveraendert bleiben.
|
||||
export {
|
||||
withTransitionDefaults,
|
||||
isTransitionAnswered,
|
||||
withCashTransitionDefaults,
|
||||
isCashTransitionAnswered,
|
||||
cashTransitionSummary,
|
||||
} from "@/lib/transitions";
|
||||
import {
|
||||
buildRateWrites,
|
||||
changedRateFields,
|
||||
@@ -229,53 +238,6 @@ export function AhvReviewFields({
|
||||
);
|
||||
}
|
||||
|
||||
export function withTransitionDefaults(category: ElementCategory, isRetirement: boolean, td: TransitionData): TransitionData {
|
||||
const out = { ...td };
|
||||
if (category === "AHV") {
|
||||
// Ein Speichern der Prüfung markiert sie als erledigt (gleiches Muster wie bei PK/3a).
|
||||
if (isRetirement && out.reviewed === undefined) out.reviewed = true;
|
||||
} else if (category === "REAL_ESTATE" || category === "OTHER_ASSET") {
|
||||
if (out.decision === undefined) out.decision = "HOLD";
|
||||
} else if (category === "PENSION_FUND") {
|
||||
if (isRetirement) {
|
||||
if (out.payoutMode === undefined) out.payoutMode = "PENSION";
|
||||
} else if (out.withdrawalMode === undefined) {
|
||||
out.withdrawalMode = "NONE";
|
||||
}
|
||||
} else if (category === "PILLAR_3A") {
|
||||
if (!isRetirement && out.withdrawalMode === undefined) out.withdrawalMode = "NONE";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// --- Cash-Übergang: einmalige Sonderein-/ausgaben ---
|
||||
|
||||
export function withCashTransitionDefaults(ct: CashTransitionData): CashTransitionData {
|
||||
return ct.mode === undefined ? { ...ct, mode: "NONE" } : { ...ct };
|
||||
}
|
||||
|
||||
export function isCashTransitionAnswered(ct: CashTransitionData): boolean {
|
||||
return ct.mode !== undefined;
|
||||
}
|
||||
|
||||
// Kurzfassung für die Übergangszelle der Cash-Zeile.
|
||||
export function cashTransitionSummary(ct: CashTransitionData): string {
|
||||
const mode = ct.mode;
|
||||
if (mode === undefined) return "?";
|
||||
const inn = `+${formatChf(num(ct.inflowAmount))}`;
|
||||
const out = `−${formatChf(num(ct.outflowAmount))}`;
|
||||
switch (mode) {
|
||||
case "INFLOW":
|
||||
return inn;
|
||||
case "OUTFLOW":
|
||||
return out;
|
||||
case "BOTH":
|
||||
return `${inn} / ${out}`;
|
||||
default:
|
||||
return "1:1";
|
||||
}
|
||||
}
|
||||
|
||||
// Eingabefelder für den Cash-Entscheid. Erfassungs-Konventionen bewusst wie bei den
|
||||
// laufenden Flows: Zufluss nominal (wie Einkommen), Kosten real (wie Ausgaben).
|
||||
export function CashTransitionFields({
|
||||
@@ -389,24 +351,6 @@ export function CashTransitionFields({
|
||||
);
|
||||
}
|
||||
|
||||
// "Beantwortet" = ein konkreter Entscheid liegt vor (kein offenes Fragezeichen).
|
||||
export function isTransitionAnswered(category: ElementCategory, isRetirement: boolean, td: TransitionData): boolean {
|
||||
switch (category) {
|
||||
case "AHV":
|
||||
// Nur bei der Pensionierung ist eine Prüfung der Beitragskarriere nötig.
|
||||
return isRetirement ? td.reviewed === true : true;
|
||||
case "REAL_ESTATE":
|
||||
case "OTHER_ASSET":
|
||||
return td.decision !== undefined;
|
||||
case "PENSION_FUND":
|
||||
return isRetirement ? td.payoutMode !== undefined : td.withdrawalMode !== undefined;
|
||||
case "PILLAR_3A":
|
||||
return isRetirement ? true : td.withdrawalMode !== undefined;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Wiederverwendbare Feldgruppen (Detail-Panel, Erstell-Popup, Übergangs-Review) ---
|
||||
|
||||
export function ElementPhaseFields({
|
||||
|
||||
Reference in New Issue
Block a user