feat: Dokumentengenerator — Vollständige Vorlage-Bibliothek + Frontend-Redesign
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 36s
CI / test-python-backend-compliance (push) Successful in 31s
CI / test-python-document-crawler (push) Successful in 23s
CI / test-python-dsms-gateway (push) Successful in 18s
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 36s
CI / test-python-backend-compliance (push) Successful in 31s
CI / test-python-document-crawler (push) Successful in 23s
CI / test-python-dsms-gateway (push) Successful in 18s
- Migration 020: Typ-Renames (data_processing_agreement→dpa, withdrawal_policy→widerruf) + 11 neue MIT-Templates (NDA DE/EN, SLA, AUP, Community Guidelines, Copyright Policy, Cloud Service Agreement, Data Usage Clause, Cookie Banner, AGB, Liability Clause) - Backend: VALID_DOCUMENT_TYPES auf 16 Typen erweitert; /legal-templates/status nutzt jetzt dynamisches GROUP BY statt Hard-coded Felder - searchTemplates.ts: loadAllTemplates() für Library-First UX - page.tsx: Vollständig-Rewrite — Template-Bibliothek (immer sichtbar) mit Kategorie-Pills, Sprache-Toggle, optionaler Suche, Inline-Preview-Expand und Kachel-Grid; Generator-Section erscheint per Scroll wenn Vorlage gewählt - Tests: 52/52 bestanden, TestLegalTemplateNewTypes (19 neue Tests) + aktualisierte Typ-Checks Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,12 +32,25 @@ router = APIRouter(prefix="/legal-templates", tags=["legal-templates"])
|
||||
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
|
||||
|
||||
VALID_DOCUMENT_TYPES = {
|
||||
# Original types
|
||||
"privacy_policy",
|
||||
"terms_of_service",
|
||||
"impressum",
|
||||
"data_processing_agreement",
|
||||
"withdrawal_policy",
|
||||
"cookie_policy",
|
||||
# Renamed from data_processing_agreement / withdrawal_policy (Migration 020)
|
||||
"dpa",
|
||||
"widerruf",
|
||||
# New types (Migration 020)
|
||||
"nda",
|
||||
"sla",
|
||||
"acceptable_use",
|
||||
"community_guidelines",
|
||||
"copyright_policy",
|
||||
"cloud_service_agreement",
|
||||
"data_usage_clause",
|
||||
"cookie_banner",
|
||||
"agb",
|
||||
"clause",
|
||||
}
|
||||
VALID_STATUSES = {"published", "draft", "archived"}
|
||||
|
||||
@@ -184,42 +197,38 @@ async def get_templates_status(
|
||||
"""Return template counts by document_type."""
|
||||
tenant_id = _get_tenant_id(x_tenant_id)
|
||||
|
||||
row = db.execute(text("""
|
||||
SELECT
|
||||
COUNT(*) AS total,
|
||||
COUNT(*) FILTER (WHERE status = 'published') AS published,
|
||||
COUNT(*) FILTER (WHERE status = 'draft') AS draft,
|
||||
COUNT(*) FILTER (WHERE status = 'archived') AS archived,
|
||||
COUNT(*) FILTER (WHERE document_type = 'privacy_policy') AS privacy_policy,
|
||||
COUNT(*) FILTER (WHERE document_type = 'terms_of_service') AS terms_of_service,
|
||||
COUNT(*) FILTER (WHERE document_type = 'impressum') AS impressum,
|
||||
COUNT(*) FILTER (WHERE document_type = 'data_processing_agreement') AS data_processing_agreement,
|
||||
COUNT(*) FILTER (WHERE document_type = 'withdrawal_policy') AS withdrawal_policy,
|
||||
COUNT(*) FILTER (WHERE document_type = 'cookie_policy') AS cookie_policy
|
||||
total_row = db.execute(
|
||||
text("SELECT COUNT(*) FROM compliance_legal_templates WHERE tenant_id = :tenant_id"),
|
||||
{"tenant_id": tenant_id},
|
||||
).fetchone()
|
||||
total = int(total_row[0] or 0) if total_row else 0
|
||||
|
||||
status_rows = db.execute(text("""
|
||||
SELECT status, COUNT(*) AS cnt
|
||||
FROM compliance_legal_templates
|
||||
WHERE tenant_id = :tenant_id
|
||||
"""), {"tenant_id": tenant_id}).fetchone()
|
||||
GROUP BY status
|
||||
"""), {"tenant_id": tenant_id}).fetchall()
|
||||
by_status: Dict[str, int] = {r[0]: int(r[1] or 0) for r in status_rows}
|
||||
|
||||
if row:
|
||||
d = dict(row._mapping)
|
||||
counts = {k: int(v or 0) for k, v in d.items()}
|
||||
return {
|
||||
"total": counts["total"],
|
||||
"by_status": {
|
||||
"published": counts["published"],
|
||||
"draft": counts["draft"],
|
||||
"archived": counts["archived"],
|
||||
},
|
||||
"by_type": {
|
||||
"privacy_policy": counts["privacy_policy"],
|
||||
"terms_of_service": counts["terms_of_service"],
|
||||
"impressum": counts["impressum"],
|
||||
"data_processing_agreement": counts["data_processing_agreement"],
|
||||
"withdrawal_policy": counts["withdrawal_policy"],
|
||||
"cookie_policy": counts["cookie_policy"],
|
||||
},
|
||||
}
|
||||
return {"total": 0, "by_status": {}, "by_type": {}}
|
||||
type_rows = db.execute(text("""
|
||||
SELECT document_type, COUNT(*) AS cnt
|
||||
FROM compliance_legal_templates
|
||||
WHERE tenant_id = :tenant_id
|
||||
GROUP BY document_type
|
||||
ORDER BY document_type
|
||||
"""), {"tenant_id": tenant_id}).fetchall()
|
||||
by_type: Dict[str, int] = {r[0]: int(r[1] or 0) for r in type_rows}
|
||||
|
||||
return {
|
||||
"total": total,
|
||||
"by_status": {
|
||||
"published": by_status.get("published", 0),
|
||||
"draft": by_status.get("draft", 0),
|
||||
"archived": by_status.get("archived", 0),
|
||||
},
|
||||
"by_type": by_type,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/sources")
|
||||
|
||||
Reference in New Issue
Block a user