feat: A/B Testing + Compliance Report PDF (F5 + F8)
F5: A/B Testing for Consent Rate - Migration 116: banner_variants table + variant tracking in audit log - BannerABService: deterministic sticky bucketing via device hash, chi-squared significance testing, variant CRUD - banner_ab_routes: 6 endpoints (CRUD + stats + assign) - ABTestPanel.tsx: variant creation, traffic sliders, opt-in comparison chart with winner/significance badges - New "A/B-Test" tab in cookie-banner page F8: Compliance Report PDF - CompliancePDFGenerator: reportlab-based A4 PDF covering all modules (Company Profile, TOM, VVT, DSFA, Risks, Vendors, Incidents, Reviews, Consents, Roles) - compliance_report_routes: GET /compliance/report/pdf - "Compliance-Report herunterladen" button on SDK dashboard [migration-approved] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
FastAPI route for Compliance Report PDF generation.
|
||||
|
||||
Endpoint:
|
||||
GET /compliance/report/pdf — generate comprehensive compliance report as PDF
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from fastapi.responses import StreamingResponse
|
||||
from sqlalchemy.orm import Session
|
||||
import io
|
||||
|
||||
from classroom_engine.database import get_db
|
||||
from .tenant_utils import get_tenant_id as _get_tenant_id
|
||||
from compliance.services.compliance_pdf_generator import CompliancePDFGenerator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/compliance/report", tags=["compliance-report"])
|
||||
|
||||
|
||||
@router.get("/pdf")
|
||||
def generate_compliance_report_pdf(
|
||||
project_id: Optional[str] = Query(None),
|
||||
language: str = Query("de"),
|
||||
db: Session = Depends(get_db),
|
||||
tenant_id: str = Depends(_get_tenant_id),
|
||||
):
|
||||
"""Generate a comprehensive compliance PDF report for a project."""
|
||||
generator = CompliancePDFGenerator(db)
|
||||
pdf_bytes, filename = generator.generate(tenant_id, project_id, language)
|
||||
return StreamingResponse(
|
||||
io.BytesIO(pdf_bytes),
|
||||
media_type="application/pdf",
|
||||
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
|
||||
)
|
||||
Reference in New Issue
Block a user