feat: Finanzplan Phase 1-4 — DB + Engine + API + Spreadsheet-UI
Phase 1: DB-Schema (12 fp_* Tabellen) + Excel-Import (332 Zeilen importiert) Phase 2: Compute Engine (Personal, Invest, Umsatz, Material, Betrieblich, Liquiditaet, GuV) Phase 3: API (/api/finanzplan/ — GET sheets, PUT cells, POST compute) Phase 4: Spreadsheet-UI (FinanzplanSlide als Annex mit Tab-Leiste, editierbarem Grid, Jahres-Navigation) Zusaetzlich: - Gruendungsdatum verschoben: Feb→Aug 2026 (DB + Personalkosten) - Neue Preisstaffel: Startup/<10 MA ab 3.600 EUR/Jahr (14-Tage-Test, Kreditkarte) - Competition-Slide: Pricing-Tiers aktualisiert Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
246
pitch-deck/scripts/001_finanzplan_tables.sql
Normal file
246
pitch-deck/scripts/001_finanzplan_tables.sql
Normal file
@@ -0,0 +1,246 @@
|
||||
-- ============================================================================
|
||||
-- BreakPilot ComplAI — Finanzplan Database Schema
|
||||
-- Mirrors Excel: "Breakpilot ComplAI Finanzplan.xlsm" (10 Reiter)
|
||||
-- Monthly granularity: Jan 2026 – Dec 2030 (60 months)
|
||||
-- Values stored as JSONB: {"m1": ..., "m2": ..., "m60": ...}
|
||||
-- ============================================================================
|
||||
|
||||
-- Scenarios (extends existing pitch_fm_scenarios)
|
||||
CREATE TABLE IF NOT EXISTS fp_scenarios (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL DEFAULT 'Base Case',
|
||||
description TEXT,
|
||||
is_default BOOLEAN DEFAULT false,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Insert default scenario
|
||||
INSERT INTO fp_scenarios (name, description, is_default)
|
||||
VALUES ('Base Case', 'Basisdaten aus Excel-Import', true)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- ============================================================================
|
||||
-- KUNDEN (6 Segmente × ~20 Zeilen = ~120 Datenzeilen)
|
||||
-- Each segment has: base customer count (editable) + module percentages
|
||||
-- Formulas: module_count = ROUNDDOWN(base_count * percentage)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_kunden (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
segment_name TEXT NOT NULL, -- 'Care (Privat)', 'Horse (Händler)', etc.
|
||||
segment_index INT NOT NULL, -- 1-6
|
||||
row_label TEXT NOT NULL, -- 'Modul 1', 'Modul 2', ...
|
||||
row_index INT NOT NULL, -- position within segment
|
||||
percentage NUMERIC(5,3), -- multiplier (e.g. 0.9, 0.25)
|
||||
formula_type TEXT, -- 'literal', 'roundup_pct', 'rounddown_pct', 'cumulative', null
|
||||
is_editable BOOLEAN DEFAULT false, -- true for base inputs (Modul 1 per segment)
|
||||
values JSONB NOT NULL DEFAULT '{}', -- {m1: 0, m2: 0, ... m60: 0}
|
||||
excel_row INT, -- original Excel row number
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Summary rows (aggregated across all 6 segments)
|
||||
CREATE TABLE fp_kunden_summary (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
row_label TEXT NOT NULL, -- 'Modul 1', 'Modul 2', ...
|
||||
row_index INT NOT NULL,
|
||||
values JSONB NOT NULL DEFAULT '{}', -- computed: sum of 6 segments
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- UMSATZERLOESE (Revenue = Quantity × Price)
|
||||
-- Section 1 (rows 3-23): Computed revenue per module
|
||||
-- Section 2 (rows 27-46): Quantity (from Kunden)
|
||||
-- Section 3 (rows 49-73): Prices (editable VK excl. MwSt.)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_umsatzerloese (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
section TEXT NOT NULL, -- 'revenue', 'quantity', 'price'
|
||||
row_label TEXT NOT NULL, -- 'Modul 1', 'Modul 2', ...
|
||||
row_index INT NOT NULL,
|
||||
is_editable BOOLEAN DEFAULT false, -- only prices are editable
|
||||
values JSONB NOT NULL DEFAULT '{}',
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- MATERIALAUFWAND (sehr einfach: nur Mac Mini + Mac Studio)
|
||||
-- Cost = Quantity × Unit Cost (EK)
|
||||
-- Mac Mini EK: 3.200 EUR, VK: 4.800 EUR (50% Aufschlag)
|
||||
-- Mac Studio EK: 13.000 EUR, VK: 19.500 EUR (50% Aufschlag)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_materialaufwand (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
section TEXT NOT NULL, -- 'cost', 'quantity', 'unit_cost'
|
||||
row_label TEXT NOT NULL,
|
||||
row_index INT NOT NULL,
|
||||
is_editable BOOLEAN DEFAULT false, -- only unit costs are editable
|
||||
values JSONB NOT NULL DEFAULT '{}',
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- PERSONALKOSTEN (20 Positionen)
|
||||
-- Structured: Name, Position, Start, End, Brutto, Raise%
|
||||
-- Computed: monthly salary × AG-Sozialversicherung
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_personalkosten (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
person_name TEXT NOT NULL,
|
||||
person_nr TEXT, -- '001', '002', ...
|
||||
position TEXT, -- 'GF', 'Vertrieb', 'Entwicklung', ...
|
||||
start_date DATE,
|
||||
end_date DATE, -- null = permanent
|
||||
brutto_monthly NUMERIC(10,2), -- Bruttogehalt/Monat
|
||||
annual_raise_pct NUMERIC(5,2) DEFAULT 3.0,
|
||||
ag_sozial_pct NUMERIC(5,2) DEFAULT 20.425, -- AG-Anteil Sozialversicherung
|
||||
is_editable BOOLEAN DEFAULT true,
|
||||
-- Computed monthly values
|
||||
values_brutto JSONB NOT NULL DEFAULT '{}', -- monthly brutto
|
||||
values_sozial JSONB NOT NULL DEFAULT '{}', -- monthly AG-Sozial
|
||||
values_total JSONB NOT NULL DEFAULT '{}', -- brutto + sozial
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- BETRIEBLICHE AUFWENDUNGEN (~40 Kostenposten)
|
||||
-- Most are fixed monthly values (editable)
|
||||
-- Some are computed (Summen, Abschreibungen)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_betriebliche_aufwendungen (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
category TEXT NOT NULL, -- 'raumkosten', 'versicherungen', 'marketing', etc.
|
||||
row_label TEXT NOT NULL,
|
||||
row_index INT NOT NULL,
|
||||
is_editable BOOLEAN DEFAULT true,
|
||||
is_sum_row BOOLEAN DEFAULT false, -- true for category subtotals
|
||||
formula_desc TEXT, -- e.g. 'SUM(rows 9-18)', '=Personalkosten!Y4'
|
||||
values JSONB NOT NULL DEFAULT '{}',
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- INVESTITIONEN (Anlagegüter mit AfA)
|
||||
-- Each item: name, amount, purchase date, useful life, depreciation
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_investitionen (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
item_name TEXT NOT NULL,
|
||||
category TEXT, -- 'gwg', 'ausstattung', etc.
|
||||
purchase_amount NUMERIC(12,2) NOT NULL,
|
||||
purchase_date DATE,
|
||||
afa_years INT, -- useful life in years
|
||||
afa_end_date DATE, -- computed end date
|
||||
is_editable BOOLEAN DEFAULT true,
|
||||
-- Computed: monthly investment amount (in purchase month) and depreciation
|
||||
values_invest JSONB NOT NULL DEFAULT '{}', -- investment amount per month
|
||||
values_afa JSONB NOT NULL DEFAULT '{}', -- monthly depreciation
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- SONST. BETRIEBLICHE ERTRAEGE (6 Kategorien × 3 Zeilen)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_sonst_ertraege (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
category TEXT NOT NULL, -- '1-Interne Kostenstellen', '2-Entwicklung National', etc.
|
||||
row_label TEXT,
|
||||
row_index INT NOT NULL,
|
||||
is_editable BOOLEAN DEFAULT true,
|
||||
is_sum_row BOOLEAN DEFAULT false,
|
||||
values JSONB NOT NULL DEFAULT '{}',
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- LIQUIDITAET (computed from all above)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_liquiditaet (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
row_label TEXT NOT NULL,
|
||||
row_type TEXT NOT NULL, -- 'einzahlung', 'auszahlung', 'ueberschuss', 'kontostand'
|
||||
is_editable BOOLEAN DEFAULT false, -- only Eigenkapital, Fremdkapital, Entnahmen editable
|
||||
formula_desc TEXT,
|
||||
values JSONB NOT NULL DEFAULT '{}',
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- GUV JAHRESABSCHLUSS (annual summary, 5 years)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_guv (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
row_label TEXT NOT NULL,
|
||||
row_index INT NOT NULL,
|
||||
is_sum_row BOOLEAN DEFAULT false,
|
||||
formula_desc TEXT,
|
||||
values JSONB NOT NULL DEFAULT '{}', -- {y2026: ..., y2027: ..., y2030: ...}
|
||||
excel_row INT,
|
||||
sort_order INT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- CELL OVERRIDES (for scenario-specific manual edits)
|
||||
-- ============================================================================
|
||||
CREATE TABLE fp_cell_overrides (
|
||||
id SERIAL PRIMARY KEY,
|
||||
scenario_id UUID REFERENCES fp_scenarios(id) ON DELETE CASCADE,
|
||||
sheet_name TEXT NOT NULL, -- 'kunden', 'personalkosten', etc.
|
||||
row_id INT NOT NULL, -- references the id in the sheet table
|
||||
month_key TEXT NOT NULL, -- 'm1', 'm2', ... 'm60' or 'y2026', etc.
|
||||
override_value NUMERIC,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(scenario_id, sheet_name, row_id, month_key)
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- INDEXES
|
||||
-- ============================================================================
|
||||
CREATE INDEX idx_fp_kunden_scenario ON fp_kunden(scenario_id);
|
||||
CREATE INDEX idx_fp_kunden_summary_scenario ON fp_kunden_summary(scenario_id);
|
||||
CREATE INDEX idx_fp_umsatz_scenario ON fp_umsatzerloese(scenario_id);
|
||||
CREATE INDEX idx_fp_material_scenario ON fp_materialaufwand(scenario_id);
|
||||
CREATE INDEX idx_fp_personal_scenario ON fp_personalkosten(scenario_id);
|
||||
CREATE INDEX idx_fp_betrieb_scenario ON fp_betriebliche_aufwendungen(scenario_id);
|
||||
CREATE INDEX idx_fp_invest_scenario ON fp_investitionen(scenario_id);
|
||||
CREATE INDEX idx_fp_sonst_scenario ON fp_sonst_ertraege(scenario_id);
|
||||
CREATE INDEX idx_fp_liquid_scenario ON fp_liquiditaet(scenario_id);
|
||||
CREATE INDEX idx_fp_guv_scenario ON fp_guv(scenario_id);
|
||||
CREATE INDEX idx_fp_overrides_lookup ON fp_cell_overrides(scenario_id, sheet_name, row_id);
|
||||
Reference in New Issue
Block a user