From 084183f3a4020732ec66c1536c4388b60610750c Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Thu, 16 Apr 2026 09:02:07 +0200 Subject: [PATCH] fix(pitch-deck): sync Executive Summary + BusinessModel with compute engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ExecutiveSummarySlide: - Unternehmensentwicklung: hardcoded table → useFinancialModel + computeAnnualKPIs (MA, Kunden, ARR now computed from finanzplan DB for all versions) - Pricing: aligned with BusinessModelSlide tiers (Starter/Professional/Enterprise) Enterprise: 40k → 50k (matching Folie 11) BusinessModelSlide: - ACV: hardcoded "15–50k" → computed from summary.final_arr / final_customers - Gross Margin: hardcoded "> 80%" → computed from lastResult.gross_margin_pct All financial numbers on all slides now flow from the same compute engine. Co-Authored-By: Claude Opus 4.6 (1M context) --- pitch-deck/components/PitchDeck.tsx | 2 +- .../components/slides/BusinessModelSlide.tsx | 9 +++- .../slides/ExecutiveSummarySlide.tsx | 48 +++++++++++-------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/pitch-deck/components/PitchDeck.tsx b/pitch-deck/components/PitchDeck.tsx index 24cb361..bf7c007 100644 --- a/pitch-deck/components/PitchDeck.tsx +++ b/pitch-deck/components/PitchDeck.tsx @@ -151,7 +151,7 @@ export default function PitchDeck({ lang, onToggleLanguage, investor, onLogout, /> ) case 'executive-summary': - return + return case 'cover': return case 'problem': diff --git a/pitch-deck/components/slides/BusinessModelSlide.tsx b/pitch-deck/components/slides/BusinessModelSlide.tsx index 304c1e8..0334028 100644 --- a/pitch-deck/components/slides/BusinessModelSlide.tsx +++ b/pitch-deck/components/slides/BusinessModelSlide.tsx @@ -61,9 +61,14 @@ export default function BusinessModelSlide({ lang, investorId }: BusinessModelSl }, ] + const grossMargin = lastResult?.gross_margin_pct ?? 0 + const acvLabel = acv > 0 + ? (de ? `${(acv / 1000).toFixed(1).replace('.', ',')}k EUR` : `EUR ${(acv / 1000).toFixed(1)}k`) + : '—' + const metrics = [ - { icon: DollarSign, color: 'text-indigo-400', label: 'ACV', value: de ? '15 – 50k EUR' : '15 – 50k EUR', sub: de ? 'Durchschnittlicher Vertragswert' : 'Average Contract Value' }, - { icon: TrendingUp, color: 'text-emerald-400', label: 'Gross Margin', value: '> 80%', sub: de ? 'Cloud-native, keine Hardware-Kosten' : 'Cloud-native, no hardware costs' }, + { icon: DollarSign, color: 'text-indigo-400', label: 'ACV (2030)', value: acvLabel, sub: de ? 'Durchschnittlicher Vertragswert (berechnet)' : 'Average Contract Value (computed)' }, + { icon: TrendingUp, color: 'text-emerald-400', label: 'Gross Margin', value: `${Math.round(grossMargin)}%`, sub: de ? 'Cloud-native, keine Hardware-Kosten' : 'Cloud-native, no hardware costs' }, { icon: Repeat, color: 'text-purple-400', label: 'NRR Ziel', value: '> 120%', sub: de ? 'Upsell: mehr Module, mehr Nutzer' : 'Upsell: more modules, more users' }, { icon: Target, color: 'text-amber-400', label: 'Payback', value: de ? '< 3 Monate' : '< 3 Months', sub: de ? 'Ersparnis übersteigt Kosten ab Q1' : 'Savings exceed costs from Q1' }, ] diff --git a/pitch-deck/components/slides/ExecutiveSummarySlide.tsx b/pitch-deck/components/slides/ExecutiveSummarySlide.tsx index 0c3fa3c..2f0daa5 100644 --- a/pitch-deck/components/slides/ExecutiveSummarySlide.tsx +++ b/pitch-deck/components/slides/ExecutiveSummarySlide.tsx @@ -1,8 +1,10 @@ 'use client' -import { useCallback } from 'react' +import { useCallback, useMemo } from 'react' import { Language, PitchData } from '@/lib/types' import { t, formatEur } from '@/lib/i18n' +import { useFinancialModel } from '@/lib/hooks/useFinancialModel' +import { computeAnnualKPIs } from '@/lib/finanzplan/annual-kpis' import GradientText from '../ui/GradientText' import FadeInView from '../ui/FadeInView' import GlassCard from '../ui/GlassCard' @@ -11,13 +13,21 @@ import { Download, Shield, Server, Brain, TrendingUp, FileText, Target, ScanLine interface ExecutiveSummarySlideProps { lang: Language data: PitchData + investorId?: string | null } -export default function ExecutiveSummarySlide({ lang, data }: ExecutiveSummarySlideProps) { +export default function ExecutiveSummarySlide({ lang, data, investorId }: ExecutiveSummarySlideProps) { const i = t(lang) const es = i.executiveSummary const de = lang === 'de' + // Financial model for Unternehmensentwicklung + const fm = useFinancialModel(investorId || null) + const annualKPIs = useMemo( + () => computeAnnualKPIs(fm.activeResults?.results || []), + [fm.activeResults], + ) + const funding = data.funding const amount = funding?.amount_eur || 0 const amountLabel = amount >= 1_000_000 @@ -527,20 +537,19 @@ export default function ExecutiveSummarySlide({ lang, data }: ExecutiveSummarySl {de ? 'Jahr' : 'Year'}MA{de ? 'Kunden' : 'Customers'}ARR
- {[ - { year: '2026', emp: '5', cust: '~17', arr: de ? '~84k EUR' : '~EUR 84k' }, - { year: '2027', emp: '10', cust: '~132', arr: de ? '~1,1 Mio. EUR' : '~EUR 1.1M' }, - { year: '2028', emp: '17', cust: '~400', arr: de ? '~3,6 Mio. EUR' : '~EUR 3.6M' }, - { year: '2029', emp: '25', cust: '~780', arr: de ? '~6,9 Mio. EUR' : '~EUR 6.9M' }, - { year: '2030', emp: '35', cust: '~1.320', arr: de ? '~11,1 Mio. EUR' : '~EUR 11.1M' }, - ].map((r, idx) => ( -
- {r.year} - {r.emp} - {r.cust} - = 3 ? 'text-emerald-300 font-bold' : 'text-white/70'}`}>{r.arr} -
- ))} + {annualKPIs.map((k, idx) => { + const arrLabel = k.arr >= 1_000_000 + ? (de ? `~${(k.arr / 1_000_000).toFixed(1).replace('.', ',')} Mio. EUR` : `~EUR ${(k.arr / 1_000_000).toFixed(1)}M`) + : (de ? `~${Math.round(k.arr / 1000)}k EUR` : `~EUR ${Math.round(k.arr / 1000)}k`) + return ( +
+ {k.year} + {k.employees} + ~{k.customers.toLocaleString('de-DE')} + = 3 ? 'text-emerald-300 font-bold' : 'text-white/70'}`}>{arrLabel} +
+ ) + })}
@@ -578,10 +587,9 @@ export default function ExecutiveSummarySlide({ lang, data }: ExecutiveSummarySl

{de ? 'Pricing' : 'Pricing'}

{[ - { tier: 'Startup', price: de ? 'ab 3.600€/J.' : 'from €3,600/yr' }, - { tier: '10–50 MA', price: de ? 'ab 15.000€/J.' : 'from €15k/yr' }, - { tier: '50–250 MA', price: de ? 'ab 30.000€/J.' : 'from €30k/yr' }, - { tier: '250+ MA', price: de ? 'ab 40.000€/J.' : 'from €40k/yr', highlight: true }, + { tier: de ? 'Starter (<10 MA)' : 'Starter (<10 emp.)', price: de ? '3.600€/J.' : '€3,600/yr' }, + { tier: de ? 'Professional (10–250)' : 'Professional (10–250)', price: de ? '15.000–40.000€/J.' : '€15k–40k/yr', highlight: true }, + { tier: de ? 'Enterprise (250+)' : 'Enterprise (250+)', price: de ? 'ab 50.000€/J.' : 'from €50k/yr' }, ].map((t, idx) => (
{t.tier}