feat(pitch-deck): live-computed sum rows in Finanzplan (like Excel formulas)
Some checks failed
Build pitch-deck / build-push-deploy (push) Successful in 1m11s
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 29s
CI / test-python-voice (push) Successful in 33s
CI / test-bqas (push) Has been cancelled
Some checks failed
Build pitch-deck / build-push-deploy (push) Successful in 1m11s
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 29s
CI / test-python-voice (push) Successful in 33s
CI / test-bqas (push) Has been cancelled
Sum rows (is_sum_row=true) are now computed live in the frontend from their detail rows, not read from stale DB values. This means: - Category sums (Versicherungen, Marketing, Sonstige etc.) always match - "Summe sonstige" = all non-personal, non-AfA rows - "SUMME Betriebliche" = all rows including personal + AfA - No more manual recompute needed after DB changes Also: chart labels increased from 7-8px to 11px for readability. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,7 @@ interface SheetRow {
|
||||
position?: string
|
||||
start_date?: string
|
||||
purchase_amount?: number
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const MONTH_LABELS = [
|
||||
@@ -575,7 +576,50 @@ export default function FinanzplanSlide({ lang, investorId, preferredScenarioId,
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map(row => {
|
||||
{(() => {
|
||||
// Live-compute sum rows from detail rows (like Excel formulas)
|
||||
const computedRows = rows.map(row => {
|
||||
const label = getLabel(row)
|
||||
const cat = (row as Record<string, unknown>).category as string || ''
|
||||
if (!row.is_sum_row) return row
|
||||
|
||||
// Find detail rows for this category
|
||||
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 = detailRows
|
||||
if (label.includes('Summe sonstige') || label.includes('SUMME Betriebliche')) {
|
||||
sourceRows = rows.filter(r => {
|
||||
const rCat = (r as Record<string, unknown>).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
|
||||
})
|
||||
}
|
||||
|
||||
if (sourceRows.length === 0) return row
|
||||
|
||||
const computed: Record<string, number> = {}
|
||||
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)
|
||||
}
|
||||
|
||||
return { ...row, values: computed, values_total: computed }
|
||||
})
|
||||
|
||||
return computedRows
|
||||
})().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')
|
||||
|
||||
Reference in New Issue
Block a user