diff --git a/pitch-deck/components/slides/FinanzplanSlide.tsx b/pitch-deck/components/slides/FinanzplanSlide.tsx index 4b64c53..08e5011 100644 --- a/pitch-deck/components/slides/FinanzplanSlide.tsx +++ b/pitch-deck/components/slides/FinanzplanSlide.tsx @@ -580,27 +580,47 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId, // Live-compute sum rows from detail rows (like Excel formulas) const computedRows = rows.map(row => { const label = getLabel(row) - const cat = (row as Record).category as string || '' - if (!row.is_sum_row) return row + const cat = row.category as string || '' + const rowType = (row as Record).row_type as string || '' + const isSumLabel = row.is_sum_row || label.includes('Summe') || label.includes('SUMME') || label.includes('ÜBERSCHUSS') || label.includes('UEBERSCHUSS') - // Find detail rows for this category - const detailRows = rows.filter(r => { - const rCat = (r as Record).category as string || '' - return rCat === cat && !r.is_sum_row - }) + if (!isSumLabel) return row - // For "Summe sonstige" or "SUMME Betriebliche" — sum all non-sum, non-personal, non-abschreibung - let sourceRows = detailRows - if (label.includes('Summe sonstige') || label.includes('SUMME Betriebliche')) { + let sourceRows: SheetRow[] = [] + + // === Betriebliche Aufwendungen: category-based sums === + if (cat && cat !== 'summe') { + sourceRows = rows.filter(r => (r.category as string) === cat && !r.is_sum_row && getLabel(r) !== label) + } else if (label.includes('Summe sonstige')) { sourceRows = rows.filter(r => { - const rCat = (r as Record).category as string || '' + const rCat = r.category as string || '' const rLabel = getLabel(r) - if (r.is_sum_row) return false - if (label.includes('Summe sonstige')) { - return rCat !== 'personal' && rCat !== 'abschreibungen' && !rLabel.includes('Personalkosten') && !rLabel.includes('Abschreibungen') - } - // SUMME Betriebliche = everything including personal + abschreibungen - return true + return !r.is_sum_row && rCat !== 'personal' && rCat !== 'abschreibungen' && rCat !== 'summe' && + !rLabel.includes('Personalkosten') && !rLabel.includes('Abschreibungen') && !rLabel.includes('Summe') && !rLabel.includes('SUMME') + }) + } else if (label.includes('SUMME Betriebliche')) { + sourceRows = rows.filter(r => !r.is_sum_row && !getLabel(r).includes('Summe') && !getLabel(r).includes('SUMME') && (r.category as string) !== 'summe') + } + + // === Liquidität: row_type-based sums === + else if (label.includes('Summe') && label.includes('ERTR')) { + sourceRows = rows.filter(r => (r as Record).row_type === 'einzahlung' && !getLabel(r).includes('Summe')) + } else if (label.includes('Summe') && label.includes('AUSZAHL')) { + sourceRows = rows.filter(r => (r as Record).row_type === 'auszahlung' && !getLabel(r).includes('Summe')) + } + + // === Liquidität: ÜBERSCHUSS = Erträge - Auszahlungen === + else if (label.includes('ÜBERSCHUSS') || label.includes('UEBERSCHUSS')) { + // These are complex formulas — keep DB values for now + 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 + 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') }) } @@ -609,10 +629,7 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId, const computed: Record = {} for (let m = 1; m <= 60; m++) { const key = `m${m}` - computed[key] = sourceRows.reduce((sum, r) => { - const v = getValues(r) - return sum + (v[key] || 0) - }, 0) + computed[key] = Math.round(sourceRows.reduce((sum, r) => sum + (getValues(r)[key] || 0), 0)) } return { ...row, values: computed, values_total: computed }