Datenschutzerklärung als unterschreibbare PDF-Vorlage

Neuer Endpoint GET /api/gdpr/customer/:customerId/privacy-pdf
generiert eine PDF mit:
- Titel
- Personalisiertem Kopf (Name / Firma + Kundennummer + Datum)
- Voller Datenschutzerklärung (HTML → Text)
- Einwilligungsklausel
- Unterschriftenblock (Ort/Datum links, Unterschrift rechts,
  zweite Linie "Name in Druckbuchstaben" mit vorausgefuelltem
  Kundennamen)

Auth: customers:read + canAccessCustomer. Filename:
"datenschutzerklaerung-<kundennummer>.pdf".

Im Tab "Einwilligungen / Datenschutz" beim Kunden gibt es jetzt
direkt neben dem Upload-Feld den Link "Vorlage zum Unterschreiben"
– Ausdrucken, unterschreiben lassen, scannen, wieder hochladen.

Verifiziert auf dev: Magic-Bytes %PDF-1.3, %%EOF-Marker am Ende,
2 KB Output, pdftotext zeigt korrekten Aufbau inkl. Unterschrift-
Linien.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 15:30:11 +02:00
parent 69a52ffe03
commit 897abc7b21
5 changed files with 162 additions and 5 deletions
+8
View File
@@ -1812,6 +1812,14 @@ export const gdprApi = {
const res = await api.post<ApiResponse<{ url: string; channel: string; hash: string }>>(`/gdpr/customer/${customerId}/send-consent-link`, { channel });
return res.data;
},
// Unterschreibbare Datenschutzerklärung als PDF (Papierform).
// Liefert die URL inkl. Auth-Token, damit window.open/<a download> klappt
// (Browser senden bei plain links keinen Authorization-Header).
getSignablePrivacyPdfUrl: (customerId: number): string => {
const token = getAccessToken();
const base = `/api/gdpr/customer/${customerId}/privacy-pdf`;
return token ? `${base}?token=${encodeURIComponent(token)}` : base;
},
// Portal: Eigene Datenschutzseite
getMyPrivacy: async () => {
const res = await api.get<ApiResponse<{ privacyPolicyHtml: string; consents: CustomerConsent[] }>>('/gdpr/my-privacy');