feat(dsr): Go DSR deprecated, Python Export-Endpoint, Frontend an Backend-APIs anbinden
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 34s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 17s

- Go: DEPRECATED-Kommentare an allen DSR-Handlern und Routes
- Python: GET /dsr/export?format=csv|json (Semikolon-CSV, 12 Spalten)
- API-Client: 12 neue Funktionen (verify, assign, extend, complete, reject, communications, exception-checks, history)
- Detail-Seite: Alle Actions verdrahtet (keine Coming-soon-Alerts mehr), Communications + Art.17(3)-Checks + Audit-Log live
- Haupt-Seite: CSV-Export-Button im Header
- Tests: 54/54 bestanden (4 neue Export-Tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-06 18:21:43 +01:00
parent 3593a4ff78
commit 095eff26d9
7 changed files with 526 additions and 102 deletions

View File

@@ -4,11 +4,14 @@ DSR (Data Subject Request) Routes — Betroffenenanfragen nach DSGVO Art. 15-21.
Native Python/FastAPI Implementierung, ersetzt Go consent-service Proxy.
"""
import io
import csv
import uuid
from datetime import datetime, timedelta
from typing import Optional, List, Dict, Any
from fastapi import APIRouter, Depends, HTTPException, Query, Header
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from sqlalchemy.orm import Session
from sqlalchemy import text, func, and_, or_, cast, String
@@ -438,6 +441,61 @@ async def get_dsr_stats(
}
# =============================================================================
# Export
# =============================================================================
@router.get("/export")
async def export_dsrs(
format: str = Query("csv", pattern="^(csv|json)$"),
tenant_id: str = Depends(_get_tenant),
db: Session = Depends(get_db),
):
"""Exportiert alle DSRs als CSV oder JSON."""
tid = uuid.UUID(tenant_id)
dsrs = db.query(DSRRequestDB).filter(
DSRRequestDB.tenant_id == tid,
).order_by(DSRRequestDB.created_at.desc()).all()
if format == "json":
return {
"exported_at": datetime.utcnow().isoformat(),
"total": len(dsrs),
"requests": [_dsr_to_dict(d) for d in dsrs],
}
# CSV export (semicolon-separated, matching Go format + extended fields)
output = io.StringIO()
writer = csv.writer(output, delimiter=';', quoting=csv.QUOTE_MINIMAL)
writer.writerow([
"ID", "Referenznummer", "Typ", "Name", "E-Mail", "Status",
"Prioritaet", "Eingegangen", "Frist", "Abgeschlossen", "Quelle", "Zugewiesen",
])
for dsr in dsrs:
writer.writerow([
str(dsr.id),
dsr.request_number or "",
dsr.request_type or "",
dsr.requester_name or "",
dsr.requester_email or "",
dsr.status or "",
dsr.priority or "",
dsr.received_at.strftime("%Y-%m-%d") if dsr.received_at else "",
dsr.deadline_at.strftime("%Y-%m-%d") if dsr.deadline_at else "",
dsr.completed_at.strftime("%Y-%m-%d") if dsr.completed_at else "",
dsr.source or "",
dsr.assigned_to or "",
])
output.seek(0)
return StreamingResponse(
output,
media_type="text/csv; charset=utf-8",
headers={"Content-Disposition": "attachment; filename=dsr_export.csv"},
)
# =============================================================================
# Deadline Processing (MUST be before /{dsr_id} to avoid path conflicts)
# =============================================================================