feat(founding-wizard): Gründungs-Wizard für 2-Mann GmbH + 14 Notar-Templates

[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
This commit is contained in:
Benjamin Admin
2026-05-20 09:30:51 +02:00
parent 98ec6d4284
commit 7a5f1e48dd
33 changed files with 6725 additions and 0 deletions
@@ -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 }
)
}
}