fix: derive fp_scenario IDs from version snapshot, eliminate hardcoded UUIDs
Build pitch-deck / build-push-deploy (push) Successful in 1m30s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 33s
CI / test-python-voice (push) Successful in 32s
CI / test-bqas (push) Successful in 31s
Build pitch-deck / build-push-deploy (push) Successful in 1m30s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 33s
CI / test-python-voice (push) Successful in 32s
CI / test-bqas (push) Successful in 31s
The fm_scenarios array in each pitch version snapshot already stores the fp_scenario IDs directly (same pattern 1 Mio used). Wandeldarlehen snapshots were missing Bear/Bull entries — updated in DB to add them. - /api/data: include fp_scenarios in version response (was omitted) - PitchDeck: derive fpBaseScenarioId from data.fp_scenarios - useFpKPIs: accept fpBaseScenarioId instead of isWandeldarlehen boolean - AssumptionsSlide: find Bear/Base/Bull by name from fpScenarios prop - FinanzplanSlide: initialize from fpBaseScenarioId, use version scenarios for selector - FinancialsSlide / ExecutiveSummarySlide: pass fpBaseScenarioId to hook - types: add FpScenarioRef + fp_scenarios field to PitchData No UUID hardcoded in any component. Adding a new pitch version only requires setting the correct fp_scenario IDs in its fm_scenarios snapshot. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,7 @@ export async function GET() {
|
|||||||
metrics: map.metrics || [],
|
metrics: map.metrics || [],
|
||||||
funding: (map.funding || [])[0] || null,
|
funding: (map.funding || [])[0] || null,
|
||||||
products: map.products || [],
|
products: map.products || [],
|
||||||
|
fp_scenarios: map.fm_scenarios || [],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,14 +72,10 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
|
|||||||
const [fabOpen, setFabOpen] = useState(false)
|
const [fabOpen, setFabOpen] = useState(false)
|
||||||
const isWandeldarlehen = (data?.funding?.instrument || '').toLowerCase() === 'wandeldarlehen'
|
const isWandeldarlehen = (data?.funding?.instrument || '').toLowerCase() === 'wandeldarlehen'
|
||||||
|
|
||||||
// For version previews: use the version's default FM scenario instead of base table default
|
// Derive fp_scenario IDs from version snapshot (fm_scenarios stores fp_scenario IDs directly)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const fpScenarios = data?.fp_scenarios || []
|
||||||
const fmScenarios = (previewData as any)?.fm_scenarios as Array<{ id: string; is_default?: boolean }> | undefined
|
const fpBaseScenarioId = fpScenarios.find(s => s.is_default)?.id ?? fpScenarios[0]?.id ?? null
|
||||||
const preferredScenarioId = fmScenarios?.[0]?.is_default
|
const preferredScenarioId = fpBaseScenarioId
|
||||||
? fmScenarios[0].id
|
|
||||||
: fmScenarios?.length === 1
|
|
||||||
? fmScenarios[0].id
|
|
||||||
: null
|
|
||||||
|
|
||||||
// Skip cap-table slide for Wandeldarlehen versions
|
// Skip cap-table slide for Wandeldarlehen versions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -163,7 +159,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'executive-summary':
|
case 'executive-summary':
|
||||||
return <ExecutiveSummarySlide lang={lang} data={data} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} />
|
return <ExecutiveSummarySlide lang={lang} data={data} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} fpBaseScenarioId={fpBaseScenarioId} />
|
||||||
case 'cover':
|
case 'cover':
|
||||||
return <CoverSlide lang={lang} onNext={nav.nextSlide} funding={data.funding} />
|
return <CoverSlide lang={lang} onNext={nav.nextSlide} funding={data.funding} />
|
||||||
case 'problem':
|
case 'problem':
|
||||||
@@ -189,7 +185,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
|
|||||||
case 'team':
|
case 'team':
|
||||||
return <TeamSlide lang={lang} team={data.team} />
|
return <TeamSlide lang={lang} team={data.team} />
|
||||||
case 'financials':
|
case 'financials':
|
||||||
return <FinancialsSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} />
|
return <FinancialsSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} fpBaseScenarioId={fpBaseScenarioId} />
|
||||||
case 'the-ask':
|
case 'the-ask':
|
||||||
return <TheAskSlide lang={lang} funding={data.funding} isWandeldarlehen={isWandeldarlehen} />
|
return <TheAskSlide lang={lang} funding={data.funding} isWandeldarlehen={isWandeldarlehen} />
|
||||||
case 'cap-table':
|
case 'cap-table':
|
||||||
@@ -200,7 +196,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
|
|||||||
case 'ai-qa':
|
case 'ai-qa':
|
||||||
return <AIQASlide lang={lang} />
|
return <AIQASlide lang={lang} />
|
||||||
case 'annex-assumptions':
|
case 'annex-assumptions':
|
||||||
return <AssumptionsSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} />
|
return <AssumptionsSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} fpScenarios={fpScenarios} />
|
||||||
case 'annex-architecture':
|
case 'annex-architecture':
|
||||||
return <ArchitectureSlide lang={lang} />
|
return <ArchitectureSlide lang={lang} />
|
||||||
case 'annex-gtm':
|
case 'annex-gtm':
|
||||||
@@ -216,7 +212,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout,
|
|||||||
case 'annex-strategy':
|
case 'annex-strategy':
|
||||||
return <StrategySlide lang={lang} isWandeldarlehen={isWandeldarlehen} />
|
return <StrategySlide lang={lang} isWandeldarlehen={isWandeldarlehen} />
|
||||||
case 'annex-finanzplan':
|
case 'annex-finanzplan':
|
||||||
return <FinanzplanSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} />
|
return <FinanzplanSlide lang={lang} investorId={investor?.id || null} preferredScenarioId={preferredScenarioId} isWandeldarlehen={isWandeldarlehen} fpBaseScenarioId={fpBaseScenarioId} fpScenarios={fpScenarios} />
|
||||||
case 'annex-glossary':
|
case 'annex-glossary':
|
||||||
return <GlossarySlide lang={lang} />
|
return <GlossarySlide lang={lang} />
|
||||||
case 'risks':
|
case 'risks':
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Language } from '@/lib/types'
|
import { Language, FpScenarioRef } from '@/lib/types'
|
||||||
import { t } from '@/lib/i18n'
|
import { t } from '@/lib/i18n'
|
||||||
import GradientText from '../ui/GradientText'
|
import GradientText from '../ui/GradientText'
|
||||||
import FadeInView from '../ui/FadeInView'
|
import FadeInView from '../ui/FadeInView'
|
||||||
@@ -13,6 +13,7 @@ interface AssumptionsSlideProps {
|
|||||||
investorId?: string | null
|
investorId?: string | null
|
||||||
preferredScenarioId?: string | null
|
preferredScenarioId?: string | null
|
||||||
isWandeldarlehen?: boolean
|
isWandeldarlehen?: boolean
|
||||||
|
fpScenarios?: FpScenarioRef[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SheetRow {
|
interface SheetRow {
|
||||||
@@ -72,7 +73,7 @@ async function loadScenarioKPIs(scenarioId: string | null): Promise<ScenarioKPIs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AssumptionsSlide({ lang, isWandeldarlehen }: AssumptionsSlideProps) {
|
export default function AssumptionsSlide({ lang, isWandeldarlehen, fpScenarios }: AssumptionsSlideProps) {
|
||||||
const i = t(lang)
|
const i = t(lang)
|
||||||
const de = lang === 'de'
|
const de = lang === 'de'
|
||||||
|
|
||||||
@@ -80,14 +81,19 @@ export default function AssumptionsSlide({ lang, isWandeldarlehen }: Assumptions
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function load() {
|
async function load() {
|
||||||
const baseId = isWandeldarlehen ? 'c0000000-0000-0000-0000-000000000200' : null
|
const scenarios = fpScenarios || []
|
||||||
const bearId = isWandeldarlehen ? 'd0000000-0000-0000-0000-000000000201' : 'd0000000-0000-0000-0000-000000000301'
|
const find = (role: 'bear' | 'bull' | 'base') => {
|
||||||
const bullId = isWandeldarlehen ? 'd0000000-0000-0000-0000-000000000202' : 'd0000000-0000-0000-0000-000000000302'
|
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)])
|
const [bear, base, bull] = await Promise.all([loadScenarioKPIs(bearId), loadScenarioKPIs(baseId), loadScenarioKPIs(bullId)])
|
||||||
setScenarioData({ bear, base, bull })
|
setScenarioData({ bear, base, bull })
|
||||||
}
|
}
|
||||||
load()
|
load()
|
||||||
}, [isWandeldarlehen])
|
}, [fpScenarios])
|
||||||
|
|
||||||
const bear = scenarioData?.bear || { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' }
|
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: '—' }
|
const base = scenarioData?.base || { arr: 0, customers: 0, headcount: 0, cash: 0, breakEvenYear: '—' }
|
||||||
|
|||||||
@@ -16,15 +16,16 @@ interface ExecutiveSummarySlideProps {
|
|||||||
investorId?: string | null
|
investorId?: string | null
|
||||||
preferredScenarioId?: string | null
|
preferredScenarioId?: string | null
|
||||||
isWandeldarlehen?: boolean
|
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 i = t(lang)
|
||||||
const es = i.executiveSummary
|
const es = i.executiveSummary
|
||||||
const de = lang === 'de'
|
const de = lang === 'de'
|
||||||
|
|
||||||
// Unternehmensentwicklung from fp_* tables (source of truth)
|
// Unternehmensentwicklung from fp_* tables (source of truth)
|
||||||
const { kpis: fpKPIs } = useFpKPIs(isWandeldarlehen)
|
const { kpis: fpKPIs } = useFpKPIs(fpBaseScenarioId)
|
||||||
|
|
||||||
// Pipeline stats from DB
|
// Pipeline stats from DB
|
||||||
const [pipelineStats, setPipelineStats] = useState<Record<string, { value: number }>>({})
|
const [pipelineStats, setPipelineStats] = useState<Record<string, { value: number }>>({})
|
||||||
|
|||||||
@@ -25,9 +25,10 @@ interface FinancialsSlideProps {
|
|||||||
investorId: string | null
|
investorId: string | null
|
||||||
preferredScenarioId?: string | null
|
preferredScenarioId?: string | null
|
||||||
isWandeldarlehen?: boolean
|
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 i = t(lang)
|
||||||
const fm = useFinancialModel(investorId, preferredScenarioId)
|
const fm = useFinancialModel(investorId, preferredScenarioId)
|
||||||
const [activeTab, setActiveTab] = useState<FinTab>('overview')
|
const [activeTab, setActiveTab] = useState<FinTab>('overview')
|
||||||
@@ -38,7 +39,7 @@ export default function FinancialsSlide({ lang, investorId, preferredScenarioId,
|
|||||||
const lastResult = activeResults?.results[activeResults.results.length - 1]
|
const lastResult = activeResults?.results[activeResults.results.length - 1]
|
||||||
|
|
||||||
// KPI cards from fp_* tables (source of truth)
|
// 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 kpiArr = fpLast?.arr || summary?.final_arr || 0
|
||||||
const kpiCustomers = fpLast?.customers || summary?.final_customers || 0
|
const kpiCustomers = fpLast?.customers || summary?.final_customers || 0
|
||||||
const kpiEbit = fpKPIs?.y2029?.ebit // First profitable year
|
const kpiEbit = fpKPIs?.y2029?.ebit // First profitable year
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { Language } from '@/lib/types'
|
import { Language, FpScenarioRef } from '@/lib/types'
|
||||||
import ProjectionFooter from '../ui/ProjectionFooter'
|
import ProjectionFooter from '../ui/ProjectionFooter'
|
||||||
import GradientText from '../ui/GradientText'
|
import GradientText from '../ui/GradientText'
|
||||||
import FadeInView from '../ui/FadeInView'
|
import FadeInView from '../ui/FadeInView'
|
||||||
@@ -20,14 +20,16 @@ interface FinanzplanSlideProps {
|
|||||||
investorId?: string | null
|
investorId?: string | null
|
||||||
preferredScenarioId?: string | null
|
preferredScenarioId?: string | null
|
||||||
isWandeldarlehen?: boolean
|
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<SheetMeta[]>([])
|
const [sheets, setSheets] = useState<SheetMeta[]>([])
|
||||||
const [scenarios, setScenarios] = useState<FpScenario[]>([])
|
const [scenarios, setScenarios] = useState<FpScenario[]>([])
|
||||||
const [openCats, setOpenCats] = useState<Set<string>>(new Set())
|
const [openCats, setOpenCats] = useState<Set<string>>(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 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<string>('')
|
const [selectedScenarioId, setSelectedScenarioId] = useState<string>(fpBaseScenarioId ?? '')
|
||||||
const [activeSheet, setActiveSheet] = useState<string>('guv')
|
const [activeSheet, setActiveSheet] = useState<string>('guv')
|
||||||
const [rows, setRows] = useState<SheetRow[]>([])
|
const [rows, setRows] = useState<SheetRow[]>([])
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
@@ -96,18 +98,19 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
|
|||||||
loadKPIs()
|
loadKPIs()
|
||||||
}, [selectedScenarioId])
|
}, [selectedScenarioId])
|
||||||
|
|
||||||
// Load sheet list + scenarios
|
// Load sheet list; populate scenario selector from version data or API fallback
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch('/api/finanzplan', { cache: 'no-store' })
|
fetch('/api/finanzplan', { cache: 'no-store' })
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
setSheets(data.sheets || [])
|
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)
|
setScenarios(scens)
|
||||||
// Pick scenario: Wandeldarlehen version → WD scenario, otherwise default
|
|
||||||
if (!selectedScenarioId) {
|
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 = scens.find(s => s.is_default) ?? scens[0]
|
||||||
const def = wdScenario ?? scens.find(s => s.is_default) ?? scens[0]
|
|
||||||
if (def) setSelectedScenarioId(def.id)
|
if (def) setSelectedScenarioId(def.id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ interface SheetRow {
|
|||||||
* Loads annual KPIs directly from fp_* tables (source of truth).
|
* Loads annual KPIs directly from fp_* tables (source of truth).
|
||||||
* Returns a map of year keys (y2026-y2030) to KPI objects.
|
* 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<Record<string, FpAnnualKPIs>>({})
|
const [kpis, setKpis] = useState<Record<string, FpAnnualKPIs>>({})
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function load() {
|
async function load() {
|
||||||
try {
|
try {
|
||||||
const param = isWandeldarlehen ? '?scenarioId=c0000000-0000-0000-0000-000000000200' : ''
|
const param = fpBaseScenarioId ? `?scenarioId=${fpBaseScenarioId}` : ''
|
||||||
const [guvRes, liqRes, persRes, kundenRes] = await Promise.all([
|
const [guvRes, liqRes, persRes, kundenRes] = await Promise.all([
|
||||||
fetch(`/api/finanzplan/guv${param}`, { cache: 'no-store' }),
|
fetch(`/api/finanzplan/guv${param}`, { cache: 'no-store' }),
|
||||||
fetch(`/api/finanzplan/liquiditaet${param}`, { cache: 'no-store' }),
|
fetch(`/api/finanzplan/liquiditaet${param}`, { cache: 'no-store' }),
|
||||||
@@ -102,7 +102,7 @@ export function useFpKPIs(isWandeldarlehen?: boolean) {
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
load()
|
load()
|
||||||
}, [isWandeldarlehen])
|
}, [fpBaseScenarioId])
|
||||||
|
|
||||||
// Use of Funds: compute spending breakdown m8-m24 (funding period)
|
// Use of Funds: compute spending breakdown m8-m24 (funding period)
|
||||||
const [useOfFunds, setUseOfFunds] = useState<Array<{ category: string; label_de: string; label_en: string; percentage: number }>>([])
|
const [useOfFunds, setUseOfFunds] = useState<Array<{ category: string; label_de: string; label_en: string; percentage: number }>>([])
|
||||||
@@ -110,7 +110,7 @@ export function useFpKPIs(isWandeldarlehen?: boolean) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function loadUoF() {
|
async function loadUoF() {
|
||||||
try {
|
try {
|
||||||
const param = isWandeldarlehen ? '?scenarioId=c0000000-0000-0000-0000-000000000200' : ''
|
const param = fpBaseScenarioId ? `?scenarioId=${fpBaseScenarioId}` : ''
|
||||||
const [persRes, betriebRes, investRes] = await Promise.all([
|
const [persRes, betriebRes, investRes] = await Promise.all([
|
||||||
fetch(`/api/finanzplan/personalkosten${param}`, { cache: 'no-store' }),
|
fetch(`/api/finanzplan/personalkosten${param}`, { cache: 'no-store' }),
|
||||||
fetch(`/api/finanzplan/betriebliche${param}`, { cache: 'no-store' }),
|
fetch(`/api/finanzplan/betriebliche${param}`, { cache: 'no-store' }),
|
||||||
@@ -168,7 +168,7 @@ export function useFpKPIs(isWandeldarlehen?: boolean) {
|
|||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
}
|
}
|
||||||
loadUoF()
|
loadUoF()
|
||||||
}, [isWandeldarlehen])
|
}, [fpBaseScenarioId])
|
||||||
|
|
||||||
const last = kpis.y2030
|
const last = kpis.y2030
|
||||||
return { kpis, loading, last, useOfFunds }
|
return { kpis, loading, last, useOfFunds }
|
||||||
|
|||||||
@@ -114,6 +114,14 @@ export interface PitchProduct {
|
|||||||
operating_cost_eur: number
|
operating_cost_eur: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FpScenarioRef {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
is_default?: boolean
|
||||||
|
color?: string
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface PitchData {
|
export interface PitchData {
|
||||||
company: PitchCompany
|
company: PitchCompany
|
||||||
team: PitchTeamMember[]
|
team: PitchTeamMember[]
|
||||||
@@ -125,6 +133,7 @@ export interface PitchData {
|
|||||||
metrics: PitchMetric[]
|
metrics: PitchMetric[]
|
||||||
funding: PitchFunding
|
funding: PitchFunding
|
||||||
products: PitchProduct[]
|
products: PitchProduct[]
|
||||||
|
fp_scenarios?: FpScenarioRef[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Financial Model Types
|
// Financial Model Types
|
||||||
|
|||||||
Reference in New Issue
Block a user