Terminplaner: Datenschutz-Absatz als Rechtstext-Baustein
datenschutzAbsatz(einstellung, anrede) liefert den Absatz "Online-Terminbuchung" fuer die Datenschutzerklaerung der Betriebs-Website als reinen Text (Sie- und Du-Fassung, fuenf bedingte Saetze: Telefon-Feld, Nachricht/Zusatzfelder, Erinnerung, Widerruf ueber zeigtWiderruf, Telefon des Betriebs). RECHTSTEXTE_ENTWURF = true. Test pinnt den Wortlaut gegen die Markdown-Quelle in allen 32 Bedingungskombinationen. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1ac142b92f
commit
06ebcd1b0a
2 files changed
+403
-5
No files matched your search
@@ -2,8 +2,9 @@
|
||||
* ENTWURF – nur Pilot, vor Einsatz bei fremden Betrieben prüfen.
|
||||
*
|
||||
* Rechtstext-Bausteine des Terminplaners fuer Gaeste (Spezifikation 2026-10-02-terminplaner-design.md, Abschnitt 11).
|
||||
* Reine Funktionen und Konstanten, ohne Appwrite und ohne config. Die Texte sind Rechtstexte und stehen deshalb immer
|
||||
* in der Sie-Form (auch bei Du-Betrieben); nur der Datenschutz-Hinweis unter dem Formular folgt der Anrede des Betriebs.
|
||||
* Reine Funktionen und Konstanten, ohne Appwrite; sie nutzen nur Hilfsfunktionen aus einstellungen.js (zeigtWiderruf). Die Texte
|
||||
* sind Rechtstexte und stehen deshalb immer in der Sie-Form (auch bei Du-Betrieben); nur der Datenschutz-Hinweis unter dem
|
||||
* Formular und der Datenschutz-Absatz folgen der Anrede.
|
||||
*
|
||||
* widerrufsbelehrung: Muster der Anlage 1 und Muster-Widerrufsformular der Anlage 2 zu Art. 246a § 1 Abs. 2 Satz 2 EGBGB
|
||||
* (docs/rechtliches/quellen/, abgerufen 2026-10-02), Gestaltungshinweise fuer einen Dienstleistungsvertrag angewendet:
|
||||
@@ -13,11 +14,20 @@
|
||||
* Absatz zum elektronischen Webformular (es gibt nur die Widerrufsfunktion). test/termineRechtstexte.test.js prueft
|
||||
* den Wortlaut gegen die Quelldateien.
|
||||
*
|
||||
* datenschutzAbsatz: Absatz „Online-Terminbuchung“ fuer die Datenschutzerklaerung der Website des Betriebs (Betrieb = Verantwortlicher).
|
||||
* Der Wortlaut steht auch in docs/rechtliches/termine-datenschutz-absatz.md (Fassung Sie / Fassung Du); test/termineRechtstexte.test.js
|
||||
* haelt beide gleich. Aenderungen am Text immer in Markdown und Funktion gemeinsam.
|
||||
*
|
||||
* Die Rueckgabe ist reiner Text mit Zeilenumbruechen und NICHT HTML-maskiert: Die Mailvorlage maskiert beim Einsetzen.
|
||||
*/
|
||||
|
||||
import { zeigtWiderruf } from './einstellungen.js'
|
||||
|
||||
export const RECHTSTEXTE_VERSION = '2026-10-02'
|
||||
|
||||
/** true, solange die Rechtstexte als ENTWURF gelten (Kopf KOPF der Dokumente in docs/rechtliches/); Block F setzt false zusammen mit den Koepfen. */
|
||||
export const RECHTSTEXTE_ENTWURF = true
|
||||
|
||||
const ZEILENUMBRUCH = '\n'
|
||||
const ABSATZ = '\n\n'
|
||||
|
||||
@@ -123,6 +133,13 @@ const LOESCHFRIST_ABGESAGT_TAGE = 30
|
||||
const LOESCHFRIST_UNBESTAETIGT_STUNDEN = 48
|
||||
const AUFBEWAHRUNG_VORGABE_TAGE = 90
|
||||
|
||||
/**
|
||||
* Aufbewahrung vergangener Termine in Tagen; ein nicht ganzzahliger Wert ist die Vorgabe (90). Den Bereich 14 bis 365 stellt die
|
||||
* Einstellung sicher (normalisiereEinstellung); der Loeschlauf (jobs.js) prueft ihn zusaetzlich beim Lesen.
|
||||
*/
|
||||
const aufbewahrungNachTermin = (einstellung) =>
|
||||
Number.isInteger(einstellung?.aufbewahrungTage) ? einstellung.aufbewahrungTage : AUFBEWAHRUNG_VORGABE_TAGE
|
||||
|
||||
/**
|
||||
* Kurzer Datenschutz-Hinweis (Art. 13 DSGVO gestuft) vor dem Absenden; Sie oder Du nach einstellung.anrede.
|
||||
* Die Loeschfristen entsprechen dem Loeschlauf: nicht bestaetigt 48 Stunden nach Ablauf der Bestaetigungsfrist, abgesagt
|
||||
@@ -132,7 +149,7 @@ const AUFBEWAHRUNG_VORGABE_TAGE = 90
|
||||
export function formularHinweis(einstellung) {
|
||||
const daten = betriebsdaten(einstellung?.betrieb)
|
||||
const du = einstellung.anrede === 'du'
|
||||
const tage = Number.isInteger(einstellung.aufbewahrungTage) ? einstellung.aufbewahrungTage : AUFBEWAHRUNG_VORGABE_TAGE
|
||||
const tage = aufbewahrungNachTermin(einstellung)
|
||||
const verantwortlich = verbinde([daten.name, daten.adresse])
|
||||
const frist = `bis ${tage} Tage nach dem Termin, abgesagte Termine ${LOESCHFRIST_ABGESAGT_TAGE} Tage, `
|
||||
+ `nicht bestätigte Buchungen ${LOESCHFRIST_UNBESTAETIGT_STUNDEN} Stunden nach Ablauf der Bestätigungsfrist.`
|
||||
@@ -147,6 +164,179 @@ export function formularHinweis(einstellung) {
|
||||
+ `Mehr erfahren Sie in unserer Datenschutzerklärung. Verantwortlich: ${verantwortlich}.`
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- Datenschutz-Absatz „Online-Terminbuchung“ (recherche-recht.md 11.1)
|
||||
|
||||
const DS_PROTOKOLL_TAGE = 14 // Server-Protokolle (Datenschutzerklaerung von WEBklar, Abschnitt 3)
|
||||
const DS_EMAIL_WARTESCHLANGE =
|
||||
'Bis zum Versand liegt die E-Mail in einer Warteschlange; nach dem Versand wird dort die Empfängeradresse samt Inhalt gelöscht, '
|
||||
+ 'nicht zustellbare E-Mails nach 48 Stunden.'
|
||||
|
||||
/** Auftragsverarbeiter und Server: in beiden Anreden derselbe Text. */
|
||||
const DS_AUFTRAGSVERARBEITER =
|
||||
'Wer verarbeitet die Daten in unserem Auftrag? Den Terminkalender betreibt die WEBklar GbR, Am Schwimmbad 10, 67722 Winnweiler, '
|
||||
+ 'als unser Auftragsverarbeiter nach Art. 28 DSGVO. Die Daten liegen auf Servern der Hetzner Online GmbH, Industriestraße 25, '
|
||||
+ '91710 Gunzenhausen, in Deutschland (Rechenzentren Falkenstein und Nürnberg). Der E-Mail-Versand läuft ebenfalls über Hetzner. '
|
||||
+ 'Eine Übermittlung in Drittländer findet nicht statt.'
|
||||
|
||||
const wenn = (bedingung, text) => (bedingung ? text : '')
|
||||
/** Sätze eines Absatzes, durch ein Leerzeichen getrennt; ein weggelassener Satz (leer) hinterlässt keine Lücke. */
|
||||
const saetze = (...liste) => liste.filter(Boolean).join(' ')
|
||||
|
||||
/**
|
||||
* Die fuenf bedingten Stellen des Absatzes (in der Markdown-Quelle „[[wenn …: …]]“): Telefon-Feld, Nachricht oder Zusatzfelder,
|
||||
* Erinnerung, Widerruf (wie der Widerrufsknopf im Widget: zeigtWiderruf), Telefonnummer des Betriebs.
|
||||
*/
|
||||
function datenschutzBedingungen(einstellung, daten) {
|
||||
const gast = einstellung.gastFelder || {}
|
||||
return {
|
||||
telefonFeld: gast.telefon !== 'aus',
|
||||
freitext: gast.nachricht !== 'aus' || (Array.isArray(gast.zusatz) && gast.zusatz.length > 0),
|
||||
erinnerung: Boolean(einstellung.erinnerung?.anbieten),
|
||||
widerruf: zeigtWiderruf(einstellung),
|
||||
telefon: daten.telefon !== '',
|
||||
}
|
||||
}
|
||||
|
||||
// Absaetze der Sie-Fassung, je Absatz eine kleine Funktion; d = { firma, verantwortlich, email, telefon, tage, ...Bedingungen }
|
||||
const DS_SIE = [
|
||||
() => 'Online-Terminbuchung',
|
||||
() => 'Auf unserer Website können Sie Termine online buchen. Dafür verarbeiten wir die folgenden Daten:',
|
||||
(d) =>
|
||||
'Welche Daten? Ihren Namen, Ihre E-Mail-Adresse, den gewählten Termin, die gewählte Leistung und die gewählte Person oder den gewählten Platz'
|
||||
+ wenn(d.telefonFeld, ', auf Wunsch Ihre Telefonnummer')
|
||||
+ wenn(d.freitext, ' und die Angaben, die Sie uns im Formular mitteilen')
|
||||
+ '. Außerdem speichern wir, wann Sie den Termin bestätigt haben, welche Fassung der Hinweise Sie bei der Buchung gesehen haben '
|
||||
+ 'und welche Zustimmungen Sie erteilt haben'
|
||||
+ wenn(d.erinnerung, ', zum Beispiel ob Sie eine Erinnerung gewünscht haben')
|
||||
+ '.',
|
||||
(d) =>
|
||||
saetze(
|
||||
'Wofür und auf welcher Grundlage?',
|
||||
'Wir brauchen die Daten, um Ihren Termin zu verwalten, Ihnen den Termin zu bestätigen und Sie über Änderungen oder Absagen zu informieren.',
|
||||
'Rechtsgrundlage ist Art. 6 Abs. 1 lit. b DSGVO (Vertrag über den gebuchten Termin, bei einer Terminanfrage vorvertragliche Maßnahmen auf Ihre Anfrage).',
|
||||
wenn(
|
||||
d.erinnerung,
|
||||
'Wenn Sie eine Erinnerung vor dem Termin wünschen, beruht diese auf Ihrer Einwilligung nach Art. 6 Abs. 1 lit. a DSGVO. '
|
||||
+ 'Sie können sie jederzeit mit Wirkung für die Zukunft widerrufen, indem Sie uns eine kurze Nachricht senden oder den Termin über den Link in der E-Mail absagen.',
|
||||
),
|
||||
wenn(
|
||||
d.widerruf,
|
||||
'Widerrufen Sie einen Vertrag über die Schaltfläche „Vertrag widerrufen“, speichern wir Ihre Erklärung mit Datum und Uhrzeit '
|
||||
+ 'und senden Ihnen eine Eingangsbestätigung (Art. 6 Abs. 1 lit. c DSGVO in Verbindung mit § 356a BGB).',
|
||||
),
|
||||
'Zum Schutz vor Missbrauch (zum Beispiel automatisierten Buchungen) und um die Zahl der Anfragen zu begrenzen, merken wir uns Ihre IP-Adresse '
|
||||
+ 'kurzzeitig nur im Arbeitsspeicher des Servers, nicht dauerhaft (Art. 6 Abs. 1 lit. f DSGVO; unser berechtigtes Interesse ist der sichere Betrieb der Terminbuchung).',
|
||||
),
|
||||
(d) =>
|
||||
'E-Mails. Sie erhalten eine E-Mail, in der Sie Ihre E-Mail-Adresse und den Termin per Link bestätigen, danach eine Bestätigung'
|
||||
+ wenn(d.erinnerung, ' und, wenn Sie das angekreuzt haben, eine Erinnerung')
|
||||
+ `. Sagen wir den Termin ab oder verschieben ihn, informieren wir Sie ebenfalls per E-Mail. Die E-Mails enthalten keine Werbung und keine Tracking-Pixel. `
|
||||
+ `Absender ist ${d.firma}, Ihre Antworten gehen an uns. ${DS_EMAIL_WARTESCHLANGE}`,
|
||||
() => DS_AUFTRAGSVERARBEITER,
|
||||
() =>
|
||||
'Beim Aufruf der Terminbuchung. Beim Aufruf dieser Seite lädt Ihr Browser das Programm der Terminbuchung vom Server der WEBklar GbR (project.webklar.com), '
|
||||
+ 'beim Öffnen der Terminbuchung zusätzlich die Termine und Texte. Dabei werden technisch bedingt Ihre IP-Adresse und Angaben zu Ihrem Browser übertragen. '
|
||||
+ `Der Server speichert sie kurzzeitig in Protokollen und löscht sie nach ${DS_PROTOKOLL_TAGE} Tagen (Art. 6 Abs. 1 lit. f DSGVO; berechtigtes Interesse ist der sichere und funktionsfähige Betrieb). `
|
||||
+ 'Wir setzen dafür keine Cookies und speichern nichts auf Ihrem Gerät.',
|
||||
(d) =>
|
||||
`Wie lange speichern wir? Nicht bestätigte Buchungen (der Bestätigungslink gilt 30 Minuten) löschen wir ${LOESCHFRIST_UNBESTAETIGT_STUNDEN} Stunden nach Ablauf dieser Frist. `
|
||||
+ `Bestätigte Termine löschen wir ${d.tage} Tage nach dem Termin, abgesagte oder abgelehnte Termine ${LOESCHFRIST_ABGESAGT_TAGE} Tage nach der Absage oder Ablehnung. `
|
||||
+ 'Terminanfragen, die wir bis zum Terminbeginn nicht beantworten, behandeln wir als abgelehnt. '
|
||||
+ 'Wird die Online-Terminbuchung abgeschaltet, löschen wir alle Termindaten 30 Tage nach dem Abschalten. '
|
||||
+ 'Gesetzliche Aufbewahrungspflichten für Geschäftsunterlagen (zum Beispiel Rechnungen) bleiben davon unberührt; sie erfüllen wir außerhalb des Terminkalenders.',
|
||||
(d) =>
|
||||
saetze(
|
||||
'Pflicht zur Angabe. Ohne Name, E-Mail-Adresse und Terminwahl können wir keinen Termin online vergeben.',
|
||||
wenn(d.telefon, `Sie können uns auch telefonisch erreichen: ${d.telefonnummer}.`),
|
||||
'Eine automatisierte Entscheidungsfindung findet nicht statt. Bitte machen Sie bei der Buchung keine Angaben zu Ihrer Gesundheit.',
|
||||
),
|
||||
(d) =>
|
||||
'Ihre Rechte. Sie haben das Recht auf Auskunft, Berichtigung, Löschung, Einschränkung der Verarbeitung und Datenübertragbarkeit sowie das Recht, '
|
||||
+ 'der Verarbeitung auf Grundlage berechtigter Interessen zu widersprechen (Art. 15 bis 21 DSGVO). Eine erteilte Einwilligung können Sie jederzeit widerrufen. '
|
||||
+ `Sie können sich bei einer Datenschutzaufsichtsbehörde beschweren. Verantwortlich ist ${d.verantwortlich}, E-Mail ${d.email}.`,
|
||||
]
|
||||
|
||||
// Absaetze der Du-Fassung, gleicher Aufbau wie DS_SIE
|
||||
const DS_DU = [
|
||||
() => 'Online-Terminbuchung',
|
||||
() => 'Auf unserer Website kannst du Termine online buchen. Dafür verarbeiten wir die folgenden Daten:',
|
||||
(d) =>
|
||||
'Welche Daten? Deinen Namen, deine E-Mail-Adresse, den gewählten Termin, die gewählte Leistung und die gewählte Person oder den gewählten Platz'
|
||||
+ wenn(d.telefonFeld, ', auf Wunsch deine Telefonnummer')
|
||||
+ wenn(d.freitext, ' und die Angaben, die du uns im Formular mitteilst')
|
||||
+ '. Außerdem speichern wir, wann du den Termin bestätigt hast, welche Fassung der Hinweise du bei der Buchung gesehen hast '
|
||||
+ 'und welche Zustimmungen du erteilt hast'
|
||||
+ wenn(d.erinnerung, ', zum Beispiel ob du eine Erinnerung gewünscht hast')
|
||||
+ '.',
|
||||
(d) =>
|
||||
saetze(
|
||||
'Wofür und auf welcher Grundlage?',
|
||||
'Wir brauchen die Daten, um deinen Termin zu verwalten, dir den Termin zu bestätigen und dich über Änderungen oder Absagen zu informieren.',
|
||||
'Rechtsgrundlage ist Art. 6 Abs. 1 lit. b DSGVO (Vertrag über den gebuchten Termin, bei einer Terminanfrage vorvertragliche Maßnahmen auf deine Anfrage).',
|
||||
wenn(
|
||||
d.erinnerung,
|
||||
'Wenn du eine Erinnerung vor dem Termin wünschst, beruht diese auf deiner Einwilligung nach Art. 6 Abs. 1 lit. a DSGVO. '
|
||||
+ 'Du kannst sie jederzeit mit Wirkung für die Zukunft widerrufen, indem du uns eine kurze Nachricht sendest oder den Termin über den Link in der E-Mail absagst.',
|
||||
),
|
||||
wenn(
|
||||
d.widerruf,
|
||||
'Widerrufst du einen Vertrag über die Schaltfläche „Vertrag widerrufen“, speichern wir deine Erklärung mit Datum und Uhrzeit '
|
||||
+ 'und senden dir eine Eingangsbestätigung (Art. 6 Abs. 1 lit. c DSGVO in Verbindung mit § 356a BGB).',
|
||||
),
|
||||
'Zum Schutz vor Missbrauch (zum Beispiel automatisierten Buchungen) und um die Zahl der Anfragen zu begrenzen, merken wir uns deine IP-Adresse '
|
||||
+ 'kurzzeitig nur im Arbeitsspeicher des Servers, nicht dauerhaft (Art. 6 Abs. 1 lit. f DSGVO; unser berechtigtes Interesse ist der sichere Betrieb der Terminbuchung).',
|
||||
),
|
||||
(d) =>
|
||||
'E-Mails. Du erhältst eine E-Mail, in der du deine E-Mail-Adresse und den Termin per Link bestätigst, danach eine Bestätigung'
|
||||
+ wenn(d.erinnerung, ' und, wenn du das angekreuzt hast, eine Erinnerung')
|
||||
+ `. Sagen wir den Termin ab oder verschieben ihn, informieren wir dich ebenfalls per E-Mail. Die E-Mails enthalten keine Werbung und keine Tracking-Pixel. `
|
||||
+ `Absender ist ${d.firma}, deine Antworten gehen an uns. ${DS_EMAIL_WARTESCHLANGE}`,
|
||||
() => DS_AUFTRAGSVERARBEITER,
|
||||
() =>
|
||||
'Beim Aufruf der Terminbuchung. Beim Aufruf dieser Seite lädt dein Browser das Programm der Terminbuchung vom Server der WEBklar GbR (project.webklar.com), '
|
||||
+ 'beim Öffnen der Terminbuchung zusätzlich die Termine und Texte. Dabei werden technisch bedingt deine IP-Adresse und Angaben zu deinem Browser übertragen. '
|
||||
+ `Der Server speichert sie kurzzeitig in Protokollen und löscht sie nach ${DS_PROTOKOLL_TAGE} Tagen (Art. 6 Abs. 1 lit. f DSGVO; berechtigtes Interesse ist der sichere und funktionsfähige Betrieb). `
|
||||
+ 'Wir setzen dafür keine Cookies und speichern nichts auf deinem Gerät.',
|
||||
(d) =>
|
||||
`Wie lange speichern wir? Nicht bestätigte Buchungen (der Bestätigungslink gilt 30 Minuten) löschen wir ${LOESCHFRIST_UNBESTAETIGT_STUNDEN} Stunden nach Ablauf dieser Frist. `
|
||||
+ `Bestätigte Termine löschen wir ${d.tage} Tage nach dem Termin, abgesagte oder abgelehnte Termine ${LOESCHFRIST_ABGESAGT_TAGE} Tage nach der Absage oder Ablehnung. `
|
||||
+ 'Terminanfragen, die wir bis zum Terminbeginn nicht beantworten, behandeln wir als abgelehnt. '
|
||||
+ 'Wird die Online-Terminbuchung abgeschaltet, löschen wir alle Termindaten 30 Tage nach dem Abschalten. '
|
||||
+ 'Gesetzliche Aufbewahrungspflichten für Geschäftsunterlagen (zum Beispiel Rechnungen) bleiben davon unberührt; sie erfüllen wir außerhalb des Terminkalenders.',
|
||||
(d) =>
|
||||
saetze(
|
||||
'Pflicht zur Angabe. Ohne Name, E-Mail-Adresse und Terminwahl können wir keinen Termin online vergeben.',
|
||||
wenn(d.telefon, `Du kannst uns auch telefonisch erreichen: ${d.telefonnummer}.`),
|
||||
'Eine automatisierte Entscheidungsfindung findet nicht statt. Bitte mach bei der Buchung keine Angaben zu deiner Gesundheit.',
|
||||
),
|
||||
(d) =>
|
||||
'Deine Rechte. Du hast das Recht auf Auskunft, Berichtigung, Löschung, Einschränkung der Verarbeitung und Datenübertragbarkeit sowie das Recht, '
|
||||
+ 'der Verarbeitung auf Grundlage berechtigter Interessen zu widersprechen (Art. 15 bis 21 DSGVO). Eine erteilte Einwilligung kannst du jederzeit widerrufen. '
|
||||
+ `Du kannst dich bei einer Datenschutzaufsichtsbehörde beschweren. Verantwortlich ist ${d.verantwortlich}, E-Mail ${d.email}.`,
|
||||
]
|
||||
|
||||
/**
|
||||
* Absatz „Online-Terminbuchung“ fuer die Datenschutzerklaerung der Website des Betriebs, als reiner Text (nicht HTML-maskiert):
|
||||
* Absaetze durch eine Leerzeile, erste Zeile „Online-Terminbuchung“. anrede === 'du' ist die Du-Fassung, alles andere die Sie-Fassung
|
||||
* (wie formularHinweis); die Anrede kommt aus dem Parameter, nicht aus einstellung.anrede. Sätze, die zu abgeschalteten Funktionen
|
||||
* gehören, fehlen (Telefon-Feld, Nachricht oder Zusatzfelder, Erinnerung, Widerruf, Telefonnummer des Betriebs, siehe datenschutzBedingungen).
|
||||
* Die Aufbewahrung nach dem Termin ist einstellung.aufbewahrungTage (ungültig: 90). Fehlt der Betriebsname oder die E-Mail-Adresse:
|
||||
* TypeError (wie bei den anderen Rechtstexten); eine fehlende Anschrift steht einfach nicht im Text.
|
||||
*/
|
||||
export function datenschutzAbsatz(einstellung, anrede) {
|
||||
const daten = betriebsdaten(einstellung?.betrieb)
|
||||
const absaetze = anrede === 'du' ? DS_DU : DS_SIE
|
||||
const d = {
|
||||
...datenschutzBedingungen(einstellung, daten),
|
||||
firma: daten.name,
|
||||
verantwortlich: verbinde([daten.name, daten.adresse]),
|
||||
email: daten.email,
|
||||
telefonnummer: daten.telefon,
|
||||
tage: aufbewahrungNachTermin(einstellung),
|
||||
}
|
||||
return absaetze.map((absatz) => absatz(d)).join(ABSATZ)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- Zustimmungen (Haken) und Hinweis zu Gesundheitsangaben
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user