feat(pitch-deck): NRR + Payback formula-based from fp_* data
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 39s
CI / test-python-voice (push) Successful in 33s
CI / test-bqas (push) Has been cancelled

- NRR: Revenue year N / Revenue year N-1 × 100 (no more "target > 120%")
- Payback: CAC / monthly gross profit (no more "target < 3 months")
- Both computed in useFpKPIs hook from fp_guv data
- BusinessModelSlide shows computed values with "(berechnet)" label

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-19 17:47:11 +02:00
parent e524786ac0
commit 7be1a296c6
2 changed files with 22 additions and 3 deletions

View File

@@ -17,6 +17,8 @@ export interface FpAnnualKPIs {
revPerEmp: number
ebitMargin: number
grossMargin: number
nrr: number // Net Revenue Retention %
paybackMonths: number // CAC Payback Period in months
}
interface SheetRow {
@@ -75,7 +77,24 @@ export function useFpKPIs(isWandeldarlehen?: boolean) {
const ebitMargin = revenue > 0 ? Math.round((ebit / revenue) * 100) : 0
const grossMargin = revenue > 0 ? Math.round(((revenue - (findGuv('Summe Materialaufwand')?.values?.[yk] || 0)) / revenue) * 100) : 0
result[yk] = { revenue, ebit, personal, netIncome, steuern, liquiditaet, customers, headcount, mrr, arr, arpu, revPerEmp, ebitMargin, grossMargin }
// NRR: compare Dec revenue of this year vs Dec revenue of prior year
// NRR = (MRR_Dec_thisYear / MRR_Dec_lastYear) * 100
const prevMk = `m${(y - 2026) * 12}` // December of prior year (m0 for 2026 = no prior)
const prevRevenue = y > 2026 ? (findGuv('Umsatzerlöse')?.values?.[`y${y - 1}`] || 0) : 0
const nrr = prevRevenue > 0 ? Math.round((revenue / prevRevenue) * 100) : 0
// Payback: Marketing costs / monthly gross profit per new customer
// Simplified: annual marketing spend / (new customers * monthly ARPU)
const sonstAufw = findGuv('Sonst. betriebl. Aufwend')?.values?.[yk] || 0
// Marketing ~ 10% of sonstige (rough estimate from our formula)
const marketingSpend = Math.round(revenue * 0.10)
const prevCustomers = y > 2026 ? (kundenGesamt?.values?.[`m${(y - 2026) * 12}`] || 0) : 0
const newCustomers = Math.max(customers - prevCustomers, 1)
const cac = newCustomers > 0 ? Math.round(marketingSpend / newCustomers) : 0
const monthlyGrossProfit = arpu > 0 ? arpu * (grossMargin / 100) : 0
const paybackMonths = monthlyGrossProfit > 0 ? Math.round(cac / monthlyGrossProfit) : 0
result[yk] = { revenue, ebit, personal, netIncome, steuern, liquiditaet, customers, headcount, mrr, arr, arpu, revPerEmp, ebitMargin, grossMargin, nrr, paybackMonths }
}
setKpis(result)