diff --git a/pitch-deck/app/api/data/route.ts b/pitch-deck/app/api/data/route.ts
index cffd15a..0be22e3 100644
--- a/pitch-deck/app/api/data/route.ts
+++ b/pitch-deck/app/api/data/route.ts
@@ -39,6 +39,7 @@ export async function GET() {
metrics: map.metrics || [],
funding: (map.funding || [])[0] || null,
products: map.products || [],
+ fp_scenarios: map.fm_scenarios || [],
})
}
diff --git a/pitch-deck/components/PitchDeck.tsx b/pitch-deck/components/PitchDeck.tsx
index f744a3e..ff13c67 100644
--- a/pitch-deck/components/PitchDeck.tsx
+++ b/pitch-deck/components/PitchDeck.tsx
@@ -72,14 +72,10 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
const [fabOpen, setFabOpen] = useState(false)
const isWandeldarlehen = (data?.funding?.instrument || '').toLowerCase() === 'wandeldarlehen'
- // For version previews: use the version's default FM scenario instead of base table default
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const fmScenarios = (previewData as any)?.fm_scenarios as Array<{ id: string; is_default?: boolean }> | undefined
- const preferredScenarioId = fmScenarios?.[0]?.is_default
- ? fmScenarios[0].id
- : fmScenarios?.length === 1
- ? fmScenarios[0].id
- : null
+ // Derive fp_scenario IDs from version snapshot (fm_scenarios stores fp_scenario IDs directly)
+ const fpScenarios = data?.fp_scenarios || []
+ const fpBaseScenarioId = fpScenarios.find(s => s.is_default)?.id ?? fpScenarios[0]?.id ?? null
+ const preferredScenarioId = fpBaseScenarioId
// Skip cap-table slide for Wandeldarlehen versions
useEffect(() => {
@@ -163,7 +159,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
/>
)
case 'executive-summary':
- return
+ return
case 'cover':
return
case 'problem':
@@ -189,7 +185,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
case 'team':
return
case 'financials':
- return
+ return
case 'the-ask':
return
case 'cap-table':
@@ -200,7 +196,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
case 'ai-qa':
return
case 'annex-assumptions':
- return
+ return
case 'annex-architecture':
return
case 'annex-gtm':
@@ -216,7 +212,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
case 'annex-strategy':
return
case 'annex-finanzplan':
- return
+ return
case 'annex-glossary':
return
case 'risks':
diff --git a/pitch-deck/components/slides/AssumptionsSlide.tsx b/pitch-deck/components/slides/AssumptionsSlide.tsx
index 2d8b525..d9af730 100644
--- a/pitch-deck/components/slides/AssumptionsSlide.tsx
+++ b/pitch-deck/components/slides/AssumptionsSlide.tsx
@@ -1,7 +1,7 @@
'use client'
import { useEffect, useState } from 'react'
-import { Language } from '@/lib/types'
+import { Language, FpScenarioRef } from '@/lib/types'
import { t } from '@/lib/i18n'
import GradientText from '../ui/GradientText'
import FadeInView from '../ui/FadeInView'
@@ -13,6 +13,7 @@ interface AssumptionsSlideProps {
investorId?: string | null
preferredScenarioId?: string | null
isWandeldarlehen?: boolean
+ fpScenarios?: FpScenarioRef[]
}
interface SheetRow {
@@ -72,7 +73,7 @@ async function loadScenarioKPIs(scenarioId: string | null): Promise {
async function load() {
- const baseId = isWandeldarlehen ? 'c0000000-0000-0000-0000-000000000200' : null
- const bearId = isWandeldarlehen ? 'd0000000-0000-0000-0000-000000000201' : 'd0000000-0000-0000-0000-000000000301'
- const bullId = isWandeldarlehen ? 'd0000000-0000-0000-0000-000000000202' : 'd0000000-0000-0000-0000-000000000302'
+ const scenarios = fpScenarios || []
+ const find = (role: 'bear' | 'bull' | 'base') => {
+ if (role === 'base') return scenarios.find(s => s.is_default)?.id ?? null
+ return scenarios.find(s => s.name.toLowerCase().includes(role))?.id ?? null
+ }
+ const baseId = find('base')
+ const bearId = find('bear')
+ const bullId = find('bull')
const [bear, base, bull] = await Promise.all([loadScenarioKPIs(bearId), loadScenarioKPIs(baseId), loadScenarioKPIs(bullId)])
setScenarioData({ bear, base, bull })
}
load()
- }, [isWandeldarlehen])
+ }, [fpScenarios])
const bear = scenarioData?.bear || { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' }
const base = scenarioData?.base || { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' }
diff --git a/pitch-deck/components/slides/ExecutiveSummarySlide.tsx b/pitch-deck/components/slides/ExecutiveSummarySlide.tsx
index 6b3fb99..a73f24d 100644
--- a/pitch-deck/components/slides/ExecutiveSummarySlide.tsx
+++ b/pitch-deck/components/slides/ExecutiveSummarySlide.tsx
@@ -16,15 +16,16 @@ interface ExecutiveSummarySlideProps {
investorId?: string | null
preferredScenarioId?: string | null
isWandeldarlehen?: boolean
+ fpBaseScenarioId?: string | null
}
-export default function ExecutiveSummarySlide({ lang, data, investorId, preferredScenarioId, isWandeldarlehen }: ExecutiveSummarySlideProps) {
+export default function ExecutiveSummarySlide({ lang, data, investorId, preferredScenarioId, isWandeldarlehen, fpBaseScenarioId }: ExecutiveSummarySlideProps) {
const i = t(lang)
const es = i.executiveSummary
const de = lang === 'de'
// Unternehmensentwicklung from fp_* tables (source of truth)
- const { kpis: fpKPIs } = useFpKPIs(isWandeldarlehen)
+ const { kpis: fpKPIs } = useFpKPIs(fpBaseScenarioId)
// Pipeline stats from DB
const [pipelineStats, setPipelineStats] = useState>({})
diff --git a/pitch-deck/components/slides/FinancialsSlide.tsx b/pitch-deck/components/slides/FinancialsSlide.tsx
index f067acf..45187b3 100644
--- a/pitch-deck/components/slides/FinancialsSlide.tsx
+++ b/pitch-deck/components/slides/FinancialsSlide.tsx
@@ -25,9 +25,10 @@ interface FinancialsSlideProps {
investorId: string | null
preferredScenarioId?: string | null
isWandeldarlehen?: boolean
+ fpBaseScenarioId?: string | null
}
-export default function FinancialsSlide({ lang, investorId, preferredScenarioId, isWandeldarlehen }: FinancialsSlideProps) {
+export default function FinancialsSlide({ lang, investorId, preferredScenarioId, isWandeldarlehen, fpBaseScenarioId }: FinancialsSlideProps) {
const i = t(lang)
const fm = useFinancialModel(investorId, preferredScenarioId)
const [activeTab, setActiveTab] = useState('overview')
@@ -38,7 +39,7 @@ export default function FinancialsSlide({ lang, investorId, preferredScenarioId,
const lastResult = activeResults?.results[activeResults.results.length - 1]
// KPI cards from fp_* tables (source of truth)
- const { last: fpLast, kpis: fpKPIs } = useFpKPIs(isWandeldarlehen)
+ const { last: fpLast, kpis: fpKPIs } = useFpKPIs(fpBaseScenarioId)
const kpiArr = fpLast?.arr || summary?.final_arr || 0
const kpiCustomers = fpLast?.customers || summary?.final_customers || 0
const kpiEbit = fpKPIs?.y2029?.ebit // First profitable year
diff --git a/pitch-deck/components/slides/FinanzplanSlide.tsx b/pitch-deck/components/slides/FinanzplanSlide.tsx
index 7d68a9c..af98b00 100644
--- a/pitch-deck/components/slides/FinanzplanSlide.tsx
+++ b/pitch-deck/components/slides/FinanzplanSlide.tsx
@@ -1,7 +1,7 @@
'use client'
import { useCallback, useEffect, useState } from 'react'
-import { Language } from '@/lib/types'
+import { Language, FpScenarioRef } from '@/lib/types'
import ProjectionFooter from '../ui/ProjectionFooter'
import GradientText from '../ui/GradientText'
import FadeInView from '../ui/FadeInView'
@@ -20,14 +20,16 @@ interface FinanzplanSlideProps {
investorId?: string | null
preferredScenarioId?: string | null
isWandeldarlehen?: boolean
+ fpBaseScenarioId?: string | null
+ fpScenarios?: FpScenarioRef[]
}
-export default function FinanzplanSlide({ lang, investorId, preferredScenarioId, isWandeldarlehen }: FinanzplanSlideProps) {
+export default function FinanzplanSlide({ lang, investorId, preferredScenarioId, isWandeldarlehen, fpBaseScenarioId, fpScenarios }: FinanzplanSlideProps) {
const [sheets, setSheets] = useState([])
const [scenarios, setScenarios] = useState([])
const [openCats, setOpenCats] = useState>(new Set())
const toggleCat = (cat: string) => setOpenCats(prev => { const n = new Set(prev); n.has(cat) ? n.delete(cat) : n.add(cat); return n })
- const [selectedScenarioId, setSelectedScenarioId] = useState('')
+ const [selectedScenarioId, setSelectedScenarioId] = useState(fpBaseScenarioId ?? '')
const [activeSheet, setActiveSheet] = useState('guv')
const [rows, setRows] = useState([])
const [loading, setLoading] = useState(false)
@@ -96,18 +98,19 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
loadKPIs()
}, [selectedScenarioId])
- // Load sheet list + scenarios
+ // Load sheet list; populate scenario selector from version data or API fallback
useEffect(() => {
fetch('/api/finanzplan', { cache: 'no-store' })
.then(r => r.json())
.then(data => {
setSheets(data.sheets || [])
- const scens: FpScenario[] = data.scenarios || []
+ // Use version fp_scenarios if available, else fall back to API list
+ const scens: FpScenario[] = fpScenarios && fpScenarios.length > 0
+ ? fpScenarios.map(s => ({ id: s.id, name: s.name, is_default: s.is_default ?? false, color: s.color ?? '#6366f1', description: s.description ?? '' }))
+ : data.scenarios || []
setScenarios(scens)
- // Pick scenario: Wandeldarlehen version → WD scenario, otherwise default
if (!selectedScenarioId) {
- const wdScenario = isWandeldarlehen ? scens.find(s => s.name.toLowerCase().includes('wandeldarlehen') && !s.name.toLowerCase().includes('bear') && !s.name.toLowerCase().includes('bull')) : null
- const def = wdScenario ?? scens.find(s => s.is_default) ?? scens[0]
+ const def = scens.find(s => s.is_default) ?? scens[0]
if (def) setSelectedScenarioId(def.id)
}
})
diff --git a/pitch-deck/lib/hooks/useFpKPIs.ts b/pitch-deck/lib/hooks/useFpKPIs.ts
index 9158971..8f18adb 100644
--- a/pitch-deck/lib/hooks/useFpKPIs.ts
+++ b/pitch-deck/lib/hooks/useFpKPIs.ts
@@ -31,14 +31,14 @@ interface SheetRow {
* Loads annual KPIs directly from fp_* tables (source of truth).
* Returns a map of year keys (y2026-y2030) to KPI objects.
*/
-export function useFpKPIs(isWandeldarlehen?: boolean) {
+export function useFpKPIs(fpBaseScenarioId?: string | null) {
const [kpis, setKpis] = useState>({})
const [loading, setLoading] = useState(true)
useEffect(() => {
async function load() {
try {
- const param = isWandeldarlehen ? '?scenarioId=c0000000-0000-0000-0000-000000000200' : ''
+ const param = fpBaseScenarioId ? `?scenarioId=${fpBaseScenarioId}` : ''
const [guvRes, liqRes, persRes, kundenRes] = await Promise.all([
fetch(`/api/finanzplan/guv${param}`, { cache: 'no-store' }),
fetch(`/api/finanzplan/liquiditaet${param}`, { cache: 'no-store' }),
@@ -102,7 +102,7 @@ export function useFpKPIs(isWandeldarlehen?: boolean) {
setLoading(false)
}
load()
- }, [isWandeldarlehen])
+ }, [fpBaseScenarioId])
// Use of Funds: compute spending breakdown m8-m24 (funding period)
const [useOfFunds, setUseOfFunds] = useState>([])
@@ -110,7 +110,7 @@ export function useFpKPIs(isWandeldarlehen?: boolean) {
useEffect(() => {
async function loadUoF() {
try {
- const param = isWandeldarlehen ? '?scenarioId=c0000000-0000-0000-0000-000000000200' : ''
+ const param = fpBaseScenarioId ? `?scenarioId=${fpBaseScenarioId}` : ''
const [persRes, betriebRes, investRes] = await Promise.all([
fetch(`/api/finanzplan/personalkosten${param}`, { cache: 'no-store' }),
fetch(`/api/finanzplan/betriebliche${param}`, { cache: 'no-store' }),
@@ -168,7 +168,7 @@ export function useFpKPIs(isWandeldarlehen?: boolean) {
} catch { /* ignore */ }
}
loadUoF()
- }, [isWandeldarlehen])
+ }, [fpBaseScenarioId])
const last = kpis.y2030
return { kpis, loading, last, useOfFunds }
diff --git a/pitch-deck/lib/types.ts b/pitch-deck/lib/types.ts
index 17d17bf..cc1eae4 100644
--- a/pitch-deck/lib/types.ts
+++ b/pitch-deck/lib/types.ts
@@ -114,6 +114,14 @@ export interface PitchProduct {
operating_cost_eur: number
}
+export interface FpScenarioRef {
+ id: string
+ name: string
+ is_default?: boolean
+ color?: string
+ description?: string
+}
+
export interface PitchData {
company: PitchCompany
team: PitchTeamMember[]
@@ -125,6 +133,7 @@ export interface PitchData {
metrics: PitchMetric[]
funding: PitchFunding
products: PitchProduct[]
+ fp_scenarios?: FpScenarioRef[]
}
// Financial Model Types