fix(pitch-deck): betriebliche accordion header-first, umsatz labels, annual display
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m25s
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 37s
CI / test-python-voice (push) Successful in 33s
CI / test-bqas (push) Successful in 36s

- Betriebliche: category header (sum_row) now renders BEFORE detail rows
- Umsatzerlöse: renamed to Preis/Monat, Anzahl Kunden, Umsatz per tier
- Engine: tier matching via parentheses extraction (handles renamed labels)
- Annual column: quantity=Dec value, price=Dec value (not cumulated)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-22 09:11:21 +02:00
parent d0bbfbb744
commit 4265f5175a
4 changed files with 61 additions and 25 deletions

View File

@@ -163,11 +163,14 @@ export async function computeFinanzplan(pool: Pool, scenarioId: string): Promise
const totalRevenue = emptyMonthly()
// Revenue = quantity × price for each module (if qty+price exist)
// Match by tier name extracted from parentheses, or exact label match
const extractTier = (label: string) => { const m = label.match(/\(([^)]+)\)/); return m ? m[1] : label }
// Revenue rows WITHOUT matching qty/price are kept as-is (e.g. Beratung & Service)
for (const rev of revenueRows) {
if (rev.row_label === 'GESAMTUMSATZ') continue
const qty = quantities.find(q => q.row_label === rev.row_label)
const price = prices.find(p => p.row_label === rev.row_label)
const tier = extractTier(rev.row_label)
const qty = quantities.find(q => extractTier(q.row_label) === tier) || quantities.find(q => q.row_label === rev.row_label)
const price = prices.find(p => extractTier(p.row_label) === tier) || prices.find(p => p.row_label === rev.row_label)
if (qty && price) {
for (let m = 1; m <= MONTHS; m++) {
const v = (qty.values[`m${m}`] || 0) * (price.values[`m${m}`] || 0)