// Ad-hoc sanity check, not a real test runner. // pnpm exec tsx src/data/__check.ts import { loadBudget } from "./load.js"; function fmtEUR(n: number): string { return new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR", maximumFractionDigits: 0, }).format(n); } const tree = await loadBudget(); console.log(`Years: ${tree.years.length} (${tree.years[0]}–${tree.years.at(-1)})`); console.log(`Produktbereiche: ${tree.produktbereiche.length}`); console.log( `Produktgruppen total: ${tree.produktbereiche.reduce( (n, b) => n + b.produktgruppen.length, 0 )}` ); console.log(`Overlap notes (>5% disagreement): ${tree.overlaps.length}`); // Bucket overlaps by year to confirm they're concentrated in the expected // triple-counted years (2025/26/27 appear in two plans each). const byYear: Record = {}; for (const o of tree.overlaps) byYear[o.year] = (byYear[o.year] ?? 0) + 1; console.log("Overlaps by year:", byYear); // Sample 3 overlaps to confirm they're plausible plan revisions, not bugs. console.log("\nSample overlaps:"); for (const o of tree.overlaps.slice(0, 3)) { console.log( ` ${o.produktbereich} > ${o.produktgruppe} · ${o.year} · ${o.category}` ); for (const v of o.values) { console.log(` ${v.source.padEnd(50)} ${fmtEUR(v.value)}`); } console.log(` Δ = ${(o.divergencePct * 100).toFixed(1)}%`); } for (const year of [2022, 2025, 2026, 2028]) { const t = tree.totals[year]; if (!t) continue; console.log( `\n${year}: Aufw ${fmtEUR(t.aufwendungen.total)} · Ertr ${fmtEUR( t.ertraege.total )} · Saldo ${fmtEUR(t.ertraege.total - t.aufwendungen.total)}` ); } console.log("\nTop 5 Produktbereiche by Aufwand 2026:"); const ranked = [...tree.produktbereiche] .map((b) => ({ name: b.name, aufwand: b.totals[2026]?.aufwendungen.total ?? 0 })) .sort((a, b) => b.aufwand - a.aufwand) .slice(0, 5); for (const r of ranked) { console.log(` ${r.name.padEnd(42)} ${fmtEUR(r.aufwand)}`); }