From 032df7f4017e1064614f778a155d8b1cf522dbf0 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:19:54 +0200 Subject: [PATCH] =?UTF-8?q?fix(pitch-deck):=20coerce=20pg=20NUMERIC=20to?= =?UTF-8?q?=20Number=20globally=20=E2=80=94=20fixes=20Finanzen=20crash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Finanzen slide crashed on mount with "a.toFixed is not a function". Traced to UnitEconomicsCards.tsx:59 calling ltvCacRatio.toFixed(1), where ltvCacRatio arrives as a string. Root cause: the cached path in /api/financial-model/compute returns raw rows from pitch_fm_results. node-postgres returns NUMERIC / DECIMAL columns as strings by default, so lastResult.ltv_cac_ratio (and every other *_eur / *_pct / *_ratio field) flows through the app as a string. Arithmetic-heavy code paths survived on accidental string-coerce (`-`, `/`, `*`), but direct method calls like .toFixed() don't coerce, which is why Unit Economics was the visible crash site. Fix at the boundary: register a single types.setTypeParser(NUMERIC, …) on the pg Pool so every query returns real numbers. All our NUMERIC values fit well inside Number.MAX_SAFE_INTEGER, so parseFloat is safe. One-line change, no component-level defensive coercions needed. Co-Authored-By: Claude Sonnet 4.6 --- pitch-deck/lib/db.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pitch-deck/lib/db.ts b/pitch-deck/lib/db.ts index 7e32d9b..bce424a 100644 --- a/pitch-deck/lib/db.ts +++ b/pitch-deck/lib/db.ts @@ -1,4 +1,11 @@ -import { Pool } from 'pg' +import { Pool, types } from 'pg' + +// Coerce NUMERIC/DECIMAL columns to JS numbers globally. The default +// node-postgres behavior hands them back as strings, which silently breaks +// every downstream `.toFixed()` / direct-number call (seen crashing +// UnitEconomicsCards on the Finanzen slide). Our values fit comfortably in +// Number.MAX_SAFE_INTEGER, so the precision trade-off is fine. +types.setTypeParser(types.builtins.NUMERIC, (val) => (val === null ? null : parseFloat(val))) const pool = new Pool({ connectionString: process.env.DATABASE_URL || 'postgres://breakpilot:breakpilot123@localhost:5432/breakpilot_db',