feat(pitch-deck): live-compute sums for Liquidität + Kunden + Umsatz tabs
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m6s
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 31s
CI / test-python-voice (push) Successful in 30s
CI / test-bqas (push) Successful in 32s
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m6s
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 31s
CI / test-python-voice (push) Successful in 30s
CI / test-bqas (push) Successful in 32s
Extended live-compute to ALL tabs: - Liquidität: "Summe ERTRÄGE" = sum of einzahlung rows, "Summe AUSZAHLUNGEN" = sum of auszahlung rows - Kunden: GESAMT rows = sum of tier detail rows - Umsatz: GESAMTUMSATZ = sum of all revenue rows - Materialaufwand: SUMME = sum of cost rows ÜBERSCHUSS rows kept from DB (complex multi-step formula). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -580,27 +580,47 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
|
|||||||
// Live-compute sum rows from detail rows (like Excel formulas)
|
// Live-compute sum rows from detail rows (like Excel formulas)
|
||||||
const computedRows = rows.map(row => {
|
const computedRows = rows.map(row => {
|
||||||
const label = getLabel(row)
|
const label = getLabel(row)
|
||||||
const cat = (row as Record<string, unknown>).category as string || ''
|
const cat = row.category as string || ''
|
||||||
if (!row.is_sum_row) return row
|
const rowType = (row as Record<string, unknown>).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
|
if (!isSumLabel) return row
|
||||||
const detailRows = rows.filter(r => {
|
|
||||||
const rCat = (r as Record<string, unknown>).category as string || ''
|
|
||||||
return rCat === cat && !r.is_sum_row
|
|
||||||
})
|
|
||||||
|
|
||||||
// For "Summe sonstige" or "SUMME Betriebliche" — sum all non-sum, non-personal, non-abschreibung
|
let sourceRows: SheetRow[] = []
|
||||||
let sourceRows = detailRows
|
|
||||||
if (label.includes('Summe sonstige') || label.includes('SUMME Betriebliche')) {
|
// === 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 => {
|
sourceRows = rows.filter(r => {
|
||||||
const rCat = (r as Record<string, unknown>).category as string || ''
|
const rCat = r.category as string || ''
|
||||||
const rLabel = getLabel(r)
|
const rLabel = getLabel(r)
|
||||||
if (r.is_sum_row) return false
|
return !r.is_sum_row && rCat !== 'personal' && rCat !== 'abschreibungen' && rCat !== 'summe' &&
|
||||||
if (label.includes('Summe sonstige')) {
|
!rLabel.includes('Personalkosten') && !rLabel.includes('Abschreibungen') && !rLabel.includes('Summe') && !rLabel.includes('SUMME')
|
||||||
return rCat !== 'personal' && rCat !== 'abschreibungen' && !rLabel.includes('Personalkosten') && !rLabel.includes('Abschreibungen')
|
})
|
||||||
|
} 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')
|
||||||
}
|
}
|
||||||
// SUMME Betriebliche = everything including personal + abschreibungen
|
|
||||||
return true
|
// === Liquidität: row_type-based sums ===
|
||||||
|
else if (label.includes('Summe') && label.includes('ERTR')) {
|
||||||
|
sourceRows = rows.filter(r => (r as Record<string, unknown>).row_type === 'einzahlung' && !getLabel(r).includes('Summe'))
|
||||||
|
} else if (label.includes('Summe') && label.includes('AUSZAHL')) {
|
||||||
|
sourceRows = rows.filter(r => (r as Record<string, unknown>).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<string, number> = {}
|
const computed: Record<string, number> = {}
|
||||||
for (let m = 1; m <= 60; m++) {
|
for (let m = 1; m <= 60; m++) {
|
||||||
const key = `m${m}`
|
const key = `m${m}`
|
||||||
computed[key] = sourceRows.reduce((sum, r) => {
|
computed[key] = Math.round(sourceRows.reduce((sum, r) => sum + (getValues(r)[key] || 0), 0))
|
||||||
const v = getValues(r)
|
|
||||||
return sum + (v[key] || 0)
|
|
||||||
}, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ...row, values: computed, values_total: computed }
|
return { ...row, values: computed, values_total: computed }
|
||||||
|
|||||||
Reference in New Issue
Block a user