From fcac514d9f6f5c935fbae18a1e667509867995a3 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Mon, 20 Apr 2026 20:05:27 +0200 Subject: [PATCH] fix(pitch-deck): GESAMTUMSATZ sum, Engineering stats, betriebliche accordion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix GESAMTUMSATZ: only sum section='revenue' rows (not price/quantity) - Fix Materialaufwand SUMME: only sum section='cost' rows - Kunden GESAMT: trust DB values instead of wrong frontend recompute - Engineering: 500K+ LoC, 385 RAG docs, 25K+ controls, remove modules card - Betriebliche Aufwendungen: clickable category headers with ▸/▾ toggle Co-Authored-By: Claude Opus 4.6 (1M context) --- .../components/slides/EngineeringSlide.tsx | 15 ++----- .../components/slides/FinanzplanSlide.tsx | 45 ++++++++++++++++--- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/pitch-deck/components/slides/EngineeringSlide.tsx b/pitch-deck/components/slides/EngineeringSlide.tsx index 20907b7..112c252 100644 --- a/pitch-deck/components/slides/EngineeringSlide.tsx +++ b/pitch-deck/components/slides/EngineeringSlide.tsx @@ -30,33 +30,26 @@ export default function EngineeringSlide({ lang }: EngineeringSlideProps) { const heroStats = [ { - value: '481K', + value: '500K+', label: de ? 'Zeilen Code' : 'Lines of Code', sub: 'Go · Python · TypeScript', color: 'text-indigo-400', borderColor: 'border-indigo-500/30', }, { - value: '320', + value: '385', label: de ? 'Dokumente im RAG' : 'Documents in RAG', sub: de ? 'EU · DACH · Frameworks · Urteile' : 'EU · DACH · Frameworks · Rulings', color: 'text-emerald-400', borderColor: 'border-emerald-500/30', }, { - value: '70K+', + value: '25K+', label: de ? 'Compliance Controls' : 'Compliance Controls', sub: de ? '6 Pipeline-Versionen' : '6 pipeline versions', color: 'text-purple-400', borderColor: 'border-purple-500/30', }, - { - value: '12', - label: de ? 'Produkt-Module' : 'Product Modules', - sub: de ? 'Security · Compliance · KI' : 'Security · Compliance · AI', - color: 'text-amber-400', - borderColor: 'border-amber-500/30', - }, ] const languageBreakdown = [ @@ -139,7 +132,7 @@ export default function EngineeringSlide({ lang }: EngineeringSlideProps) { {/* Hero Stats */} -
+
{heroStats.map((stat, idx) => (
([]) 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 [activeSheet, setActiveSheet] = useState('guv') const [rows, setRows] = useState([]) @@ -644,15 +646,27 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId, return row } - // === Kunden/Umsatz GESAMT rows === - else if (label.includes('GESAMT') || label.includes('Bestandskunden gesamt') || label.includes('GESAMTUMSATZ') || label.includes('SUMME Material')) { - // Sum all non-sum rows + // === Umsatzerlöse: GESAMTUMSATZ = sum of revenue rows only === + else if (label.includes('GESAMTUMSATZ')) { sourceRows = rows.filter(r => { - const rLabel = getLabel(r) - return !rLabel.includes('GESAMT') && !rLabel.includes('Summe') && !rLabel.includes('SUMME') && !rLabel.includes('Bestandskunden gesamt') && !rLabel.includes('GESAMTUMSATZ') + const sec = (r as Record).section as string || '' + return sec === 'revenue' && !getLabel(r).includes('GESAMTUMSATZ') }) } + // === Materialaufwand: SUMME = sum of cost rows only === + else if (label.includes('SUMME Material') || (activeSheet === 'materialaufwand' && label === 'SUMME')) { + sourceRows = rows.filter(r => { + const sec = (r as Record).section as string || '' + return sec === 'cost' && getLabel(r) !== 'SUMME' + }) + } + + // === Kunden GESAMT rows — trust DB values (engine computed) === + else if (label.includes('GESAMT') || label.includes('Bestandskunden gesamt')) { + return row + } + if (sourceRows.length === 0) return row const computed: Record = {} @@ -665,12 +679,26 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId, }) return computedRows - })().map(row => { + })().filter(row => { + // For betriebliche: hide detail rows if their category is collapsed + if (activeSheet !== 'betriebliche') return true + const cat = row.category as string || '' + const label = getLabel(row) + // Always show: sum rows, Personalkosten, Abschreibungen, category="summe" + if (row.is_sum_row || cat === 'summe' || cat === 'personal' || cat === 'abschreibungen') return true + if (label === 'Personalkosten' || label === 'Abschreibungen') return true + // Detail rows: only show if category is open + return openCats.has(cat) + }).map(row => { const values = getValues(row) const label = getLabel(row) const isSumRow = row.is_sum_row || label.includes('GESAMT') || label.includes('Summe') || label.includes('ÜBERSCHUSS') || label.includes('LIQUIDITÄT') || label.includes('UEBERSCHUSS') || label.includes('LIQUIDITAET') const isTotalRow = label.includes('GESAMT') || label.includes('Bestandskunden gesamt') || label.includes('GESAMTUMSATZ') || label.includes('SUMME') const isEditable = false // read-only for investors + const cat = row.category as string || '' + // Make category sum rows clickable (accordion) + const isCatHeader = activeSheet === 'betriebliche' && row.is_sum_row && cat !== 'summe' && cat !== 'personal' && cat !== 'abschreibungen' + const isCatOpen = openCats.has(cat) // Balance rows show Dec value, flow rows show annual sum const isBalanceRow = label.includes('Kontostand') || label === 'LIQUIDITÄT' || label === 'LIQUIDITAET' const isUnitPrice = (row as Record).section === 'unit_cost' || (row as Record).section === 'einkauf' || label.includes('Einkaufspreis') @@ -692,8 +720,11 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId, key={row.id} className={`${isTotalRow ? 'border-t-2 border-t-white/20 border-b border-b-white/[0.03]' : 'border-b border-white/[0.03]'} ${isSumRow ? 'bg-white/[0.03]' : ''} hover:bg-white/[0.02]`} > - + toggleCat(cat) : undefined} + >
+ {isCatHeader && {isCatOpen ? '▾' : '▸'}} {isEditable && } {row.position && ({row.position})}