Install LOC guardrails (check-loc.sh, architecture.md, pre-commit hook) and split all 44 files exceeding 500 LOC into domain-focused modules: - consent-service (Go): models, handlers, services, database splits - backend-core (Python): security_api, rbac_api, pdf_service, auth splits - admin-core (TypeScript): 5 page.tsx + sidebar extractions - pitch-deck (TypeScript): 6 slides, 3 UI components, engine.ts splits - voice-service (Python): enhanced_task_orchestrator split Result: 0 violations, 36 exempted (pipeline, tests, pure-data files). Go build verified clean. No behavior changes — pure structural splits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
2.3 KiB
TypeScript
69 lines
2.3 KiB
TypeScript
// FinanzplanSlide helpers — extracted from FinanzplanSlide.tsx
|
||
|
||
export interface SheetMeta {
|
||
name: string
|
||
label_de: string
|
||
label_en: string
|
||
rows: number
|
||
}
|
||
|
||
export interface SheetRow {
|
||
id: number
|
||
row_label?: string
|
||
person_name?: string
|
||
item_name?: string
|
||
category?: string
|
||
section?: string
|
||
is_editable?: boolean
|
||
is_sum_row?: boolean
|
||
values?: Record<string, number>
|
||
values_total?: Record<string, number>
|
||
values_brutto?: Record<string, number>
|
||
brutto_monthly?: number
|
||
position?: string
|
||
start_date?: string
|
||
purchase_amount?: number
|
||
[key: string]: unknown
|
||
}
|
||
|
||
export interface FpScenario {
|
||
id: string
|
||
name: string
|
||
is_default: boolean
|
||
}
|
||
|
||
export const MONTH_LABELS = [
|
||
'Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun',
|
||
'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez',
|
||
]
|
||
|
||
export function getLabel(row: SheetRow): string {
|
||
return row.row_label || row.person_name || row.item_name || '—'
|
||
}
|
||
|
||
export const FORMULA_TOOLTIPS: Record<string, string> = {
|
||
'Fort-/Weiterbildungskosten (F)': 'Mitarbeiter (ohne Gründer) × 300 EUR/Mon',
|
||
'Fahrzeugkosten (F)': 'Mitarbeiter (ohne Gründer) × 200 EUR/Mon',
|
||
'KFZ-Steuern (F)': 'Mitarbeiter (ohne Gründer) × 25 EUR/Mon',
|
||
'KFZ-Versicherung (F)': 'Mitarbeiter (ohne Gründer) × 150 EUR/Mon',
|
||
'Reisekosten (F)': 'Headcount gesamt × 75 EUR/Mon',
|
||
'Bewirtungskosten (F)': 'Bestandskunden × 50 EUR/Mon',
|
||
'Internet/Mobilfunk (F)': 'Headcount gesamt × 50 EUR/Mon',
|
||
'Cloud-Hosting (SysEleven/Hetzner)': '1.500 EUR Basis + (Kunden - 10) × 100 EUR (erste 10 inkl.)',
|
||
'Berufsgenossenschaft (F)': '0,5% der Brutto-Lohnsumme (VBG IT/Büro)',
|
||
'Allgemeine Marketingkosten (F)': '8% vom Umsatz (2026-2028), 10% ab 2029',
|
||
'Gewerbesteuer (F)': '12,25% vom Gewinn (Messzahl 3,5% × Hebesatz 350%, nur bei Gewinn)',
|
||
'Personalkosten': 'Summe aus Tab Personalkosten',
|
||
'Abschreibungen': 'Summe AfA aus Tab Investitionen',
|
||
}
|
||
|
||
export function getValues(row: SheetRow): Record<string, number> {
|
||
return row.values || row.values_total || row.values_brutto || (row as Record<string, unknown>).values_invest as Record<string, number> || {}
|
||
}
|
||
|
||
export function formatCell(v: number | undefined): string {
|
||
if (v === undefined || v === null) return ''
|
||
if (v === 0) return '—'
|
||
return Math.round(v).toLocaleString('de-DE', { maximumFractionDigits: 0 })
|
||
}
|