DSGVO-Compliance: Einwilligung, Datenschutzerklärung & Consent-Logging im Upload-Portal (STI-89)
- Datenschutzerklärung unter /portal/datenschutz/ öffentlich erreichbar - Link zur Datenschutzerklärung in Nachweis-Aufforderungs-E-Mails (HTML + TXT) - Einwilligungs-Checkbox vor Upload mit Server-Side-Validierung - Consent-Logging: einwilligung_erteilt_am auf UploadToken (Art. 7 Abs. 1 DSGVO) - Regelsatz-Korrektur: 449€→563€ in Onboarding-Template (Stand 01/2024) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.6 on 2026-03-21 22:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('stiftung', '0063_add_anrede_to_destinataer'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='uploadtoken',
|
||||
name='einwilligung_erteilt_am',
|
||||
field=models.DateTimeField(blank=True, help_text='Zeitpunkt der DSGVO-Einwilligung beim Upload (Art. 7 Abs. 1 DSGVO)', null=True, verbose_name='Einwilligung erteilt am'),
|
||||
),
|
||||
]
|
||||
@@ -1362,6 +1362,10 @@ class UploadToken(models.Model):
|
||||
erinnerung_gesendet = models.BooleanField(
|
||||
default=False, verbose_name="Erinnerung gesendet"
|
||||
)
|
||||
einwilligung_erteilt_am = models.DateTimeField(
|
||||
null=True, blank=True, verbose_name="Einwilligung erteilt am",
|
||||
help_text="Zeitpunkt der DSGVO-Einwilligung beim Upload (Art. 7 Abs. 1 DSGVO)"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Upload-Token"
|
||||
|
||||
@@ -6,6 +6,7 @@ Diese URLs sind ohne Login zugänglich (tokenbasierte Authentifizierung).
|
||||
from django.urls import path
|
||||
|
||||
from stiftung.views.portal import (
|
||||
datenschutzerklaerung,
|
||||
onboarding_danke,
|
||||
onboarding_schritt,
|
||||
upload_danke,
|
||||
@@ -15,6 +16,12 @@ from stiftung.views.portal import (
|
||||
app_name = "portal"
|
||||
|
||||
urlpatterns = [
|
||||
# Datenschutzerklärung (öffentlich, kein Token erforderlich)
|
||||
path(
|
||||
"datenschutz/",
|
||||
datenschutzerklaerung,
|
||||
name="datenschutzerklaerung",
|
||||
),
|
||||
# Upload-Portal (bestehende Destinatäre – Token-basiert)
|
||||
path(
|
||||
"upload/<str:token>/",
|
||||
|
||||
@@ -547,6 +547,7 @@ def send_nachweis_aufforderung(self, destinataer_id, nachweis_id, base_url=None)
|
||||
"gueltig_bis": gueltig_bis,
|
||||
"halbjahr_label": halbjahr_label,
|
||||
"quartal_label": quartal_label,
|
||||
"datenschutz_url": f"{base_url}/portal/datenschutz/",
|
||||
}
|
||||
|
||||
subject = f"Nachweis-Aufforderung: {quartal_label} ({halbjahr_label}) – vHTV-Stiftung"
|
||||
@@ -618,6 +619,7 @@ def send_nachweis_erinnerung(self, token_id, base_url=None):
|
||||
"gueltig_bis": upload_token.gueltig_bis,
|
||||
"halbjahr_label": halbjahr_label,
|
||||
"ist_erinnerung": True,
|
||||
"datenschutz_url": f"{base_url}/portal/datenschutz/",
|
||||
}
|
||||
|
||||
subject = f"Erinnerung: Nachweis-Upload noch ausstehend – {halbjahr_label}"
|
||||
|
||||
@@ -33,6 +33,11 @@ from django.views.decorators.http import require_http_methods
|
||||
|
||||
from stiftung.models import DokumentDatei, OnboardingEinladung, UploadToken, VierteljahresNachweis
|
||||
|
||||
|
||||
def datenschutzerklaerung(request):
|
||||
"""Datenschutzerklärung für das öffentliche Portal."""
|
||||
return render(request, "portal/datenschutzerklaerung.html")
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Erlaubte Dateitypen für Uploads
|
||||
@@ -105,6 +110,19 @@ def upload_formular(request, token):
|
||||
if request.method == "GET":
|
||||
return render(request, "portal/upload_formular.html", base_context)
|
||||
|
||||
# POST: Einwilligung prüfen
|
||||
einwilligung = request.POST.get("einwilligung")
|
||||
if not einwilligung:
|
||||
ctx = {
|
||||
**base_context,
|
||||
"einwilligung_fehler": "Bitte erteilen Sie Ihre Einwilligung zur Datenverarbeitung, um fortzufahren.",
|
||||
}
|
||||
for kat in [
|
||||
"studiennachweis", "einkommenssituation", "vermogenssituation", "weitere_dokumente"
|
||||
]:
|
||||
ctx[f"{kat}_text"] = request.POST.get(f"{kat}_text", "")
|
||||
return render(request, "portal/upload_formular.html", ctx)
|
||||
|
||||
# POST: Kategorisierte Dateien und Texte verarbeiten
|
||||
# Kategorien mit ihren DMS-Kontext-Werten und FK-Feldern auf VierteljahresNachweis
|
||||
KATEGORIEN = [
|
||||
@@ -228,6 +246,10 @@ def upload_formular(request, token):
|
||||
if nachweis_update_fields:
|
||||
nachweis.save(update_fields=list(set(nachweis_update_fields)))
|
||||
|
||||
# DSGVO-Einwilligung protokollieren (Art. 7 Abs. 1 DSGVO)
|
||||
upload_token.einwilligung_erteilt_am = timezone.now()
|
||||
upload_token.save(update_fields=["einwilligung_erteilt_am"])
|
||||
|
||||
# Token einlösen
|
||||
ip = _get_client_ip(request)
|
||||
upload_token.einloesen(ip_address=ip)
|
||||
|
||||
@@ -71,7 +71,8 @@
|
||||
</div>
|
||||
<div class="footer">
|
||||
van Hees-Theyssen-Vogel'sche Stiftung • Raesfelder Str. 3 • 46499 Hamminkeln • Tel. 02858/836780<br>
|
||||
Diese E-Mail wurde automatisch erzeugt. Bitte antworten Sie nicht direkt auf diese E-Mail.
|
||||
Diese E-Mail wurde automatisch erzeugt. Bitte antworten Sie nicht direkt auf diese E-Mail.<br>
|
||||
<a href="{{ datenschutz_url }}" style="color:#999;">Datenschutzerklärung</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -35,3 +35,4 @@ Tel. 02858/836780
|
||||
|
||||
---
|
||||
Diese E-Mail wurde automatisch erzeugt. Bitte antworten Sie nicht direkt auf diese E-Mail.
|
||||
Datenschutzerklärung: {{ datenschutz_url }}
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
<div class="mt-3 p-2 rounded" style="background: #fff8e1; border: 1px solid #ffc107; font-size: 0.82rem;">
|
||||
<i class="fas fa-info-circle me-1 text-warning"></i>
|
||||
<strong>Aktuelle Grenzwerte gemäß § 53 Nr. 2 AO (Stand 01/2024):</strong>
|
||||
Bezüge max. 2.245 € monatlich (5× Regelsatz 449 €); Vermögen max. 15.500 €.
|
||||
Bezüge max. 2.815 € monatlich (5× Regelsatz 563 €); Vermögen max. 15.500 €.
|
||||
Bei Haushaltsangehörigen erhöhen sich die Grenzen entsprechend.
|
||||
Maßgeblich sind die jeweils gültigen Werte zum Zeitpunkt der Prüfung.
|
||||
</div>
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
.deadline { font-size: 13px; color: #888; margin-top: 16px; text-align: center; }
|
||||
.footer { text-align: center; margin-top: 24px; font-size: 12px; color: #aaa; }
|
||||
.pflicht-hinweis { font-size: 12px; color: #888; margin-bottom: 16px; }
|
||||
.einwilligung-box { background: #f0f6ff; border: 1px solid #b0cce8; border-radius: 6px; padding: 14px 16px; margin: 20px 0; font-size: 14px; }
|
||||
.einwilligung-box label { font-weight: normal; display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
|
||||
.einwilligung-box input[type="checkbox"] { margin-top: 2px; flex-shrink: 0; width: 16px; height: 16px; cursor: pointer; }
|
||||
.einwilligung-box .einwilligung-fehler { color: #c00; font-size: 13px; margin-top: 6px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -128,6 +132,17 @@
|
||||
<textarea name="weitere_dokumente_text" placeholder="Optionale Anmerkungen oder Beschreibung">{{ weitere_dokumente_text|default:"" }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="einwilligung-box">
|
||||
<label>
|
||||
<input type="checkbox" name="einwilligung" id="einwilligung" required {% if einwilligung_erteilt %}checked{% endif %}>
|
||||
<span>Ich willige ein, dass die van Hees-Theyssen-Vogel'sche Stiftung die von mir hochgeladenen Dokumente und eingegebenen Daten zum Zweck der Förderprüfung verarbeitet und speichert. Ich habe die <a href="{% url 'portal:datenschutzerklaerung' %}" target="_blank">Datenschutzerklärung</a> gelesen und stimme ihr zu. Die Einwilligung kann ich jederzeit widerrufen (stiftung@vhtv-stiftung.de).
|
||||
</span>
|
||||
</label>
|
||||
{% if einwilligung_fehler %}
|
||||
<p class="einwilligung-fehler">{{ einwilligung_fehler }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="submit-btn">Unterlagen jetzt einreichen</button>
|
||||
</form>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user