From 7a5f1e48dd2aec0051bdda4011e473dc5f6d6138 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Wed, 20 May 2026 09:30:51 +0200 Subject: [PATCH] =?UTF-8?q?feat(founding-wizard):=20Gr=C3=BCndungs-Wizard?= =?UTF-8?q?=20f=C3=BCr=202-Mann=20GmbH=20+=2014=20Notar-Templates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [migration-approved] Templates (Migrations 123-136): - 123 GO-GF (Geschäftsordnung Geschäftsführung) - 124 SHA (Shareholders' Agreement, 56 Platzhalter) - 125 Satzung (Articles of Association mit UG-Variante) - 126 GF-Dienstvertrag (Trennungsprinzip Organ/Anstellung) - 127 Arbeitsvertrag (AGG-neutral, NachwG, eAU) - 128 Gesellschafterliste (§ 40 GmbHG) - 129 GF-Bestellungsbeschluss (mit § 6 Abs. 2 Versicherung) - 130 HRB-Anmeldung (§§ 7, 8, 39 GmbHG, § 12 HGB) - 131 IP-Assignment Agreement (Gründer→GmbH) - 132 Term Sheet (Pre-Seed/Seed VC-Standard) - 133 Wandeldarlehensvertrag (Convertible Loan) - 134 Beteiligungsvertrag (Subscription Agreement) - 135 ESOP/VSOP-Plan (3 Varianten) - 136 Cap Table Kategorisierung (Migrations 137-138): - ALTER TABLE compliance_legal_templates ADD lifecycle_stage TEXT[], functional_category TEXT (mit CHECK Constraints + GIN-Index) - Backfill aller 105 Templates: lifecycle_stage (pre_founding|founding| startup|kmu|konzern) + functional_category (founding_legal|employment| investor_funding|...) Backend Founding-Wizard Service: - template_renderer.py: Handlebars-light ({{VAR}}, {{#IF FLAG}}...{{/IF}}) - wizard_to_context.py: Mapping Wizard-State → SCREAMING_SNAKE_CASE Vars - markdown_to_docx.py: Markdown → DOCX via python-docx - founding_wizard_routes.py: POST /v1/founding-wizard/generate → liefert base64-DOCX-Files für ausgewählte Templates Frontend Founding-Wizard (/sdk/founding-wizard): - 8-Step Wizard (Basics, Gesellschafter, GF, Kapital, Notar, SHA, GF-Verträge, Generate) - useFoundingWizardForm Hook mit localStorage-Persistenz - TypeScript Code-Registry (template-categories.ts) als Backup zur DB - Word-Download via data:URLs (base64) Tests: - 20 Unit-Tests grün (Renderer, Context-Mapping, DOCX-Conversion) - Playwright E2E-Test mit 2-Mann GmbH (Benjamin + Sharang) Test-Daten --- .../api/v1/founding-wizard/generate/route.ts | 58 ++ .../_components/StepBasics.tsx | 125 +++ .../_components/StepGenerate.tsx | 146 ++++ .../_components/StepGesellschafter.tsx | 179 ++++ .../_components/StepsSimpleConfig.tsx | 321 ++++++++ .../_hooks/useFoundingWizardForm.ts | 187 +++++ .../app/sdk/founding-wizard/page.tsx | 141 ++++ .../lib/sdk/founding/template-categories.ts | 123 +++ admin-compliance/lib/sdk/founding/types.ts | 184 +++++ .../founding-wizard/founding-wizard.spec.ts | 196 +++++ backend-compliance/compliance/api/__init__.py | 1 + .../compliance/api/founding_wizard_routes.py | 183 +++++ .../services/founding_wizard/__init__.py | 12 + .../founding_wizard/markdown_to_docx.py | 176 ++++ .../founding_wizard/template_renderer.py | 95 +++ .../founding_wizard/wizard_to_context.py | 178 ++++ .../123_geschaeftsordnung_gf_template.sql | 279 +++++++ .../migrations/124_sha_template.sql | 766 ++++++++++++++++++ .../migrations/125_satzung_template.sql | 469 +++++++++++ .../126_gf_dienstvertrag_template.sql | 265 ++++++ .../127_arbeitsvertrag_template.sql | 262 ++++++ .../128_gesellschafterliste_template.sql | 101 +++ .../129_bestellungsbeschluss_template.sql | 128 +++ .../migrations/130_hrb_anmeldung_template.sql | 169 ++++ .../migrations/131_ip_assignment_template.sql | 178 ++++ .../migrations/132_term_sheet_template.sql | 264 ++++++ .../133_wandeldarlehen_template.sql | 251 ++++++ .../134_beteiligungsvertrag_template.sql | 338 ++++++++ .../migrations/135_esop_template.sql | 310 +++++++ .../migrations/136_cap_table_template.sql | 205 +++++ .../137_template_categorization.sql | 53 ++ .../138_template_backfill_categories.sql | 163 ++++ .../tests/test_founding_wizard.py | 219 +++++ 33 files changed, 6725 insertions(+) create mode 100644 admin-compliance/app/api/v1/founding-wizard/generate/route.ts create mode 100644 admin-compliance/app/sdk/founding-wizard/_components/StepBasics.tsx create mode 100644 admin-compliance/app/sdk/founding-wizard/_components/StepGenerate.tsx create mode 100644 admin-compliance/app/sdk/founding-wizard/_components/StepGesellschafter.tsx create mode 100644 admin-compliance/app/sdk/founding-wizard/_components/StepsSimpleConfig.tsx create mode 100644 admin-compliance/app/sdk/founding-wizard/_hooks/useFoundingWizardForm.ts create mode 100644 admin-compliance/app/sdk/founding-wizard/page.tsx create mode 100644 admin-compliance/lib/sdk/founding/template-categories.ts create mode 100644 admin-compliance/lib/sdk/founding/types.ts create mode 100644 admin-compliance/tests/playwright/founding-wizard/founding-wizard.spec.ts create mode 100644 backend-compliance/compliance/api/founding_wizard_routes.py create mode 100644 backend-compliance/compliance/services/founding_wizard/__init__.py create mode 100644 backend-compliance/compliance/services/founding_wizard/markdown_to_docx.py create mode 100644 backend-compliance/compliance/services/founding_wizard/template_renderer.py create mode 100644 backend-compliance/compliance/services/founding_wizard/wizard_to_context.py create mode 100644 backend-compliance/migrations/123_geschaeftsordnung_gf_template.sql create mode 100644 backend-compliance/migrations/124_sha_template.sql create mode 100644 backend-compliance/migrations/125_satzung_template.sql create mode 100644 backend-compliance/migrations/126_gf_dienstvertrag_template.sql create mode 100644 backend-compliance/migrations/127_arbeitsvertrag_template.sql create mode 100644 backend-compliance/migrations/128_gesellschafterliste_template.sql create mode 100644 backend-compliance/migrations/129_bestellungsbeschluss_template.sql create mode 100644 backend-compliance/migrations/130_hrb_anmeldung_template.sql create mode 100644 backend-compliance/migrations/131_ip_assignment_template.sql create mode 100644 backend-compliance/migrations/132_term_sheet_template.sql create mode 100644 backend-compliance/migrations/133_wandeldarlehen_template.sql create mode 100644 backend-compliance/migrations/134_beteiligungsvertrag_template.sql create mode 100644 backend-compliance/migrations/135_esop_template.sql create mode 100644 backend-compliance/migrations/136_cap_table_template.sql create mode 100644 backend-compliance/migrations/137_template_categorization.sql create mode 100644 backend-compliance/migrations/138_template_backfill_categories.sql create mode 100644 backend-compliance/tests/test_founding_wizard.py diff --git a/admin-compliance/app/api/v1/founding-wizard/generate/route.ts b/admin-compliance/app/api/v1/founding-wizard/generate/route.ts new file mode 100644 index 00000000..a666ddd2 --- /dev/null +++ b/admin-compliance/app/api/v1/founding-wizard/generate/route.ts @@ -0,0 +1,58 @@ +/** + * Next.js Proxy: leitet POST /api/v1/founding-wizard/generate an Backend. + * + * Konvertiert das Backend-Response (base64 DOCX) in data: URLs, + * die das Frontend direkt als Download anbieten kann. + */ + +import { NextRequest, NextResponse } from 'next/server' + +const BACKEND_URL = process.env.BACKEND_COMPLIANCE_URL || 'http://bp-compliance-backend:8002' + +export async function POST(req: NextRequest) { + try { + const body = await req.json() + + const backendRes = await fetch(`${BACKEND_URL}/v1/founding-wizard/generate`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }) + + if (!backendRes.ok) { + const errorText = await backendRes.text() + return NextResponse.json( + { error: 'Backend-Generierung fehlgeschlagen', detail: errorText }, + { status: backendRes.status } + ) + } + + const data = await backendRes.json() + const documents = (data.documents || []).map((doc: { + document_type: string + title: string + filename: string + content_base64: string + size_bytes: number + generated_at: string + }) => ({ + document_type: doc.document_type, + title: doc.title, + filename: doc.filename, + download_url: `data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,${doc.content_base64}`, + size_bytes: doc.size_bytes, + generated_at: doc.generated_at, + })) + + return NextResponse.json({ + documents, + warnings: data.warnings || [], + }) + } catch (e: unknown) { + const message = e instanceof Error ? e.message : 'Unbekannter Fehler' + return NextResponse.json( + { error: 'Proxy-Fehler', detail: message }, + { status: 500 } + ) + } +} diff --git a/admin-compliance/app/sdk/founding-wizard/_components/StepBasics.tsx b/admin-compliance/app/sdk/founding-wizard/_components/StepBasics.tsx new file mode 100644 index 00000000..abb07705 --- /dev/null +++ b/admin-compliance/app/sdk/founding-wizard/_components/StepBasics.tsx @@ -0,0 +1,125 @@ +'use client' + +import type { FoundingWizardState } from '@/lib/sdk/founding/types' + +interface Props { + state: FoundingWizardState + update: (k: K, v: FoundingWizardState[K]) => void +} + +export function StepBasics({ state, update }: Props) { + const b = state.basics + return ( +
+
+
+ + update('basics', { ...b, company_name: e.target.value })} + placeholder="Breakpilot GmbH" + className="w-full px-3 py-2 border rounded-lg" + /> +
+
+ + +
+
+ + update('basics', { ...b, company_seat: e.target.value })} + placeholder="z.B. Stuttgart" + className="w-full px-3 py-2 border rounded-lg" + /> +
+
+ + update('basics', { ...b, company_address: e.target.value })} + placeholder="Straße, PLZ Ort" + className="w-full px-3 py-2 border rounded-lg" + /> +
+
+ + update('basics', { ...b, industry: e.target.value })} + placeholder="z.B. SaaS, Beratung, Handwerk" + className="w-full px-3 py-2 border rounded-lg" + /> +
+
+ + update('basics', { ...b, business_year: e.target.value })} + className="w-full px-3 py-2 border rounded-lg" + /> +
+
+ +
+ +