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>
247 lines
11 KiB
SQL
247 lines
11 KiB
SQL
-- ============================================================================
|
||
-- 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);
|