diff --git a/pitch-deck/lib/finanzplan/engine.ts b/pitch-deck/lib/finanzplan/engine.ts index fd6a385..0360d39 100644 --- a/pitch-deck/lib/finanzplan/engine.ts +++ b/pitch-deck/lib/finanzplan/engine.ts @@ -205,8 +205,69 @@ export async function computeFinanzplan(pool: Pool, scenarioId: string): Promise await pool.query('UPDATE fp_materialaufwand SET values = $1 WHERE id = $2', [JSON.stringify(totalMaterial), matSumme.id]) } - // 6. Betriebliche Aufwendungen — compute sum rows + // 5b. Headcount without founders (for formula-based costs) + const NUM_FOUNDERS = 2 + const hcWithoutFounders = emptyMonthly() + for (let m = 1; m <= MONTHS; m++) { + hcWithoutFounders[`m${m}`] = Math.max(0, headcount[`m${m}`] - NUM_FOUNDERS) + } + + // 5c. Enterprise customers (for Bewirtungskosten) + const kundenRows = await pool.query( + "SELECT segment_name, row_label, values FROM fp_kunden WHERE scenario_id = $1 AND row_label = 'Bestandskunden' ORDER BY sort_order", + [scenarioId] + ) + const enterpriseKunden = emptyMonthly() + for (const row of kundenRows.rows) { + if (row.segment_name?.toLowerCase().includes('enterprise')) { + for (let m = 1; m <= MONTHS; m++) { + enterpriseKunden[`m${m}`] = row.values?.[`m${m}`] || 0 + } + } + } + + // 6. Betriebliche Aufwendungen — compute formula-based rows + sum rows const betrieb = betriebRows.rows as FPBetrieblicheAufwendungen[] + + // Formula-based rows: derive from headcount (excl. founders) or customers + const formulaRows: { label: string; perUnit: number; source: MonthlyValues }[] = [ + { label: 'Fort-/Weiterbildungskosten (F)', perUnit: 500, source: hcWithoutFounders }, + { label: 'Fahrzeugkosten (F)', perUnit: 400, source: hcWithoutFounders }, + { label: 'KFZ-Steuern (F)', perUnit: 50, source: hcWithoutFounders }, + { label: 'KFZ-Versicherung (F)', perUnit: 500, source: hcWithoutFounders }, + { label: 'Reisekosten (F)', perUnit: 100, source: headcount }, + { label: 'Bewirtungskosten (F)', perUnit: 200, source: enterpriseKunden }, + ] + + for (const fr of formulaRows) { + const row = betrieb.find(r => r.row_label === fr.label) + if (row) { + const computed = emptyMonthly() + for (let m = 1; m <= MONTHS; m++) { + computed[`m${m}`] = Math.round((fr.source[`m${m}`] || 0) * fr.perUnit) + } + await pool.query('UPDATE fp_betriebliche_aufwendungen SET values = $1 WHERE id = $2', [JSON.stringify(computed), row.id]) + row.values = computed + } + } + + // Serverkosten: Bestandskunden * 100 + 500 Basis + const totalKunden = emptyMonthly() + for (const row of kundenRows.rows) { + for (let m = 1; m <= MONTHS; m++) { + totalKunden[`m${m}`] += row.values?.[`m${m}`] || 0 + } + } + const serverRow = betrieb.find(r => r.row_label === 'Serverkosten Cloud (F)' || r.row_label === 'Serverkosten (Cloud)') + if (serverRow) { + const computed = emptyMonthly() + for (let m = 1; m <= MONTHS; m++) { + computed[`m${m}`] = Math.round((totalKunden[`m${m}`] || 0) * 100 + 500) + } + await pool.query('UPDATE fp_betriebliche_aufwendungen SET values = $1 WHERE id = $2', [JSON.stringify(computed), serverRow.id]) + serverRow.values = computed + } + // Update Personalkosten row const persBetrieb = betrieb.find(r => r.row_label === 'Personalkosten') if (persBetrieb) { @@ -246,7 +307,7 @@ export async function computeFinanzplan(pool: Pool, scenarioId: string): Promise } // Gesamtkosten - const gesamtBetrieb = betrieb.find(r => r.row_label.includes('Gesamtkosten')) + const gesamtBetrieb = betrieb.find(r => r.row_label.includes('Gesamtkosten') || r.row_label.includes('SUMME Betriebliche')) const totalSonstige = sonstSumme?.values || emptyMonthly() if (gesamtBetrieb) { const g = emptyMonthly()