Files
Webklar-Kundenbereich/server/services/termine/rechtstexte.js
T

401 lines
28 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Rechtstext-Bausteine des Terminplaners fuer Gaeste (Spezifikation 2026-10-02-terminplaner-design.md, Abschnitt 11).
* Reine Funktionen und Konstanten, ohne Appwrite; sie nutzen Hilfsfunktionen aus einstellungen.js (zeigtWiderruf) und lesen
* config.termine.holdMinutes (Gueltigkeit des Bestaetigungslinks im Datenschutz-Absatz, bei jedem Aufruf gelesen), sonst keine Konfiguration. 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:
* Fristbeginn „des Vertragsabschlusses.“, Betriebsdaten (Name, Anschrift, Telefon, E-Mail, alle Pflicht), Hinweis auf die
* Widerrufsfunktion als „anderer geeigneter Hinweis“ (ohne Internetadresse) im woertlichen Satzrahmen, Wertersatz fuer Dienstleistungen. Alles Uebrige ist der Gesetzestext, unveraendert.
* Ausgelassen: Textbausteine zu Waren (Besitz, Rueckzahlungsverweigerung, Rueckgabe, Rueckkosten, Wertverlust) und der
* 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 { config } from '../../config.js'
import { zeigtWiderruf } from './einstellungen.js'
/**
* Fassung der Gaestetexte (steht im Nachweis jeder Buchung, archiviert in docs/rechtliches/archiv/termine-gaestetexte-<Fassung>.md).
* Gleich config.termine.avvVersion (test/termineRechtstexte.test.js haelt beide gleich); eine Textaenderung nach der Auslieferung
* bekommt ein neues Datum, ein neues Archiv und einen neuen Hash-Pin. Buchungen aus aelteren Fassungen behalten ihre Fassung.
*/
export const RECHTSTEXTE_VERSION = '2026-10-05'
/**
* Kennzeichen, ob die Gaestetexte noch als Entwurf (nur Pilot, vor dem Einsatz bei fremden Betrieben zu pruefen) gelten. Ist es true,
* nennt die Einbauanleitung das als erste Warnung. Seit der Endfassung der Gaestetexte (Fassung 2026-10-05) false.
*/
export const RECHTSTEXTE_ENTWURF = false
const ZEILENUMBRUCH = '\n'
const ABSATZ = '\n\n'
/** Einzeiliger Text: jeder Leerraum (auch Umbrueche) wird zu einem Leerzeichen, Rand getrimmt; Nicht-Text = ''. */
const einzeilig = (wert) => (typeof wert === 'string' ? wert.replace(/\s+/g, ' ').trim() : '')
/**
* Betriebsdaten fuer die Texte. Name und E-Mail sind immer Pflicht (die Einstellung prueft sie). Mit vollstaendig: true
* auch Anschrift und Telefonnummer (das Muster der Anlage 1 verlangt alle vier): fehlt eine Angabe oder ist sie leer,
* entsteht ein TypeError, nie ein unvollstaendiger Text.
*/
function betriebsdaten(betrieb, { vollstaendig = false } = {}) {
const name = einzeilig(betrieb?.name)
const email = einzeilig(betrieb?.email)
if (!name || !email) throw new TypeError('Betriebsname und E-Mail-Adresse sind für die Rechtstexte erforderlich.')
const adresse = einzeilig(betrieb.adresse)
const telefon = einzeilig(betrieb.telefon)
if (vollstaendig && (!adresse || !telefon)) {
throw new TypeError('Anschrift und Telefonnummer des Betriebs sind für die Widerrufsbelehrung erforderlich.')
}
return { name, email, adresse, telefon }
}
const verbinde = (teile) => teile.filter(Boolean).join(', ')
// ---------------------------------------------------------------- Widerrufsbelehrung (Anlage 1) und Muster-Widerrufsformular (Anlage 2)
const FRIST = 'des Vertragsabschlusses.' // Gestaltungshinweis a): Dienstleistungsvertrag
// Widerrufsfunktion: Satzrahmen des Gesetzes wörtlich („Sie können Ihr Widerrufsrecht auch online unter … ausüben.“); in die
// Lücke „… [Internetadresse oder anderen geeigneten Hinweis …]“ kommt bei den Gästen ein geeigneter Hinweis statt einer
// Internetadresse, bei der Bestellung einer Funktion (WEBklar als Unternehmer) die Adresse der Widerrufsseite.
const EINGANGSBESTAETIGUNG =
'Wenn Sie diese Online-Funktion nutzen, übermitteln wir Ihnen auf einem dauerhaften Datenträger (z. B. durch eine E-Mail) '
+ 'unverzüglich eine Eingangsbestätigung mit Informationen zum Inhalt der Widerrufserklärung sowie dem Datum und der Uhrzeit ihres Eingangs.'
const WIDERRUFSFUNKTION =
'Sie können Ihr Widerrufsrecht auch online unter „Vertrag widerrufen“ (Schaltfläche im Terminbereich auf unserer Website '
+ 'sowie Link „Termin verwalten“ in Ihrer Bestätigungs-E-Mail) ausüben. '
+ EINGANGSBESTAETIGUNG
const WIDERRUFSFUNKTION_WEBKLAR = `Sie können Ihr Widerrufsrecht auch online unter https://project.webklar.com/widerrufen.html ausüben. ${EINGANGSBESTAETIGUNG}`
// Wertersatz bei Dienstleistungen; „oder Lieferung von Wasser/Gas/Strom/Fernwärme [Unzutreffendes streichen]“ ist gestrichen.
const WERTERSATZ =
'Haben Sie verlangt, dass die Dienstleistungen während der Widerrufsfrist beginnen soll, so haben Sie uns einen angemessenen Betrag zu zahlen, '
+ 'der dem Anteil der bis zu dem Zeitpunkt, zu dem Sie uns von der Ausübung des Widerrufsrechts hinsichtlich dieses Vertrags unterrichten, '
+ 'bereits erbrachten Dienstleistungen im Vergleich zum Gesamtumfang der im Vertrag vorgesehenen Dienstleistungen entspricht.'
/** Kontaktangaben fuer „Um Ihr Widerrufsrecht auszuüben, müssen Sie uns (…)“: Name, Anschrift, Telefonnummer, E-Mail-Adresse. */
function kontakt({ name, adresse, telefon, email }) {
return verbinde([name, adresse, `Telefon: ${telefon}`, `E-Mail: ${email}`])
}
function belehrungsAbsaetze(daten, widerrufsfunktion = WIDERRUFSFUNKTION) {
return [
'Widerrufsbelehrung',
'Widerrufsrecht',
'Sie haben das Recht, binnen vierzehn Tagen ohne Angabe von Gründen diesen Vertrag zu widerrufen.',
`Die Widerrufsfrist beträgt vierzehn Tage ab dem Tag ${FRIST}`,
`Um Ihr Widerrufsrecht auszuüben, müssen Sie uns (${kontakt(daten)}) mittels einer eindeutigen Erklärung `
+ '(z. B. ein mit der Post versandter Brief oder eine E-Mail) über Ihren Entschluss, diesen Vertrag zu widerrufen, informieren. '
+ 'Sie können dafür das beigefügte Muster-Widerrufsformular verwenden, das jedoch nicht vorgeschrieben ist.',
widerrufsfunktion,
'Zur Wahrung der Widerrufsfrist reicht es aus, dass Sie die Mitteilung über die Ausübung des Widerrufsrechts vor Ablauf der Widerrufsfrist absenden.',
'Folgen des Widerrufs',
'Wenn Sie diesen Vertrag widerrufen, haben wir Ihnen alle Zahlungen, die wir von Ihnen erhalten haben, einschließlich der Lieferkosten '
+ '(mit Ausnahme der zusätzlichen Kosten, die sich daraus ergeben, dass Sie eine andere Art der Lieferung als die von uns angebotene, '
+ 'günstigste Standardlieferung gewählt haben), unverzüglich und spätestens binnen vierzehn Tagen ab dem Tag zurückzuzahlen, '
+ 'an dem die Mitteilung über Ihren Widerruf dieses Vertrags bei uns eingegangen ist. '
+ 'Für diese Rückzahlung verwenden wir dasselbe Zahlungsmittel, das Sie bei der ursprünglichen Transaktion eingesetzt haben, '
+ 'es sei denn, mit Ihnen wurde ausdrücklich etwas anderes vereinbart; in keinem Fall werden Ihnen wegen dieser Rückzahlung Entgelte berechnet.',
WERTERSATZ,
]
}
function formularAbsaetze({ name, adresse, email }, anZeile = `An ${verbinde([name, adresse, email])}:`) {
const zeilen = [
anZeile,
'Hiermit widerrufe(n) ich/wir (*) den von mir/uns (*) abgeschlossenen Vertrag über den Kauf der folgenden Waren (*)/die Erbringung der folgenden Dienstleistung (*)',
'Bestellt am (*)/erhalten am (*)',
'Name des/der Verbraucher(s)',
'Anschrift des/der Verbraucher(s)',
'Unterschrift des/der Verbraucher(s) (nur bei Mitteilung auf Papier)',
'Datum',
]
return [
'Muster-Widerrufsformular',
'(Wenn Sie den Vertrag widerrufen wollen, dann füllen Sie bitte dieses Formular aus und senden Sie es zurück.)',
zeilen.map((zeile) => `– ${zeile}`).join(ZEILENUMBRUCH),
'(*) Unzutreffendes streichen.',
]
}
/**
* Widerrufsbelehrung und Muster-Widerrufsformular fuer einen Dienstleistungs-Termin, Sie-Form, als Text mit Zeilenumbruechen.
* betrieb: { name, email, adresse, telefon } aus der Einstellung, alle vier Pflicht. Fehlt eine Angabe oder ist sie leer: TypeError
* (eine unvollstaendige gesetzliche Belehrung wird nie stillschweigend erzeugt). Die Einstellungspruefung soll Anschrift und
* Telefon verlangen, sobald Gaeste ein Widerrufsrecht haben koennen (spaeterer Task); bis dahin faengt diese Funktion es ab.
*/
export function widerrufsbelehrung(betrieb) {
const daten = betriebsdaten(betrieb, { vollstaendig: true })
return [...belehrungsAbsaetze(daten), ...formularAbsaetze(daten)].join(ABSATZ)
}
/** WEBklar als Unternehmer (Bestellung einer Funktion im Kundenportal): Kontaktangaben der Widerrufsbelehrung. */
export const WEBKLAR_KONTAKT = Object.freeze({
name: 'WEBklar GbR',
adresse: 'Am Schwimmbad 10, 67722 Winnweiler',
telefon: '0176 23726355',
email: 'support@webklar.com',
})
/**
* Widerrufsbelehrung und Muster-Widerrufsformular fuer die Bestellung der Einrichtung einer Funktion (Terminplaner, News):
* WEBklar ist der Unternehmer, Sie-Form, Text mit Zeilenumbruechen wie widerrufsbelehrung. Gleiche Bausteine wie bei den
* Gaesten (Frist „des Vertragsabschlusses.“, Wertersatz fuer Dienstleistungen), aber die Widerrufsfunktion nennt die Adresse
* der Widerrufsseite (Wortlaut wie in den Abo-Bedingungen, Abschnitt Widerrufsbelehrung) und die „An“-Zeile des Formulars nennt
* die E-Mail-Adresse mit „E-Mail:“. Quelle des Dokuments docs/rechtliches/widerrufsbelehrung-funktionen.md; test/termineRechtstexte.test.js
* haelt beide gleich und gleicht die Belehrung mit public/abo-bedingungen.html ab.
*/
export function widerrufsbelehrungFunktion() {
const daten = betriebsdaten(WEBKLAR_KONTAKT, { vollstaendig: true })
const an = `An ${verbinde([daten.name, daten.adresse, `E-Mail: ${daten.email}`])}:`
return [...belehrungsAbsaetze(daten, WIDERRUFSFUNKTION_WEBKLAR), ...formularAbsaetze(daten, an)].join(ABSATZ)
}
// ---------------------------------------------------------------- Hinweis unter dem Buchungsformular (recherche-recht.md 11.2)
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
* 30 Tage, vergangene Termine einstellung.aufbewahrungTage nach dem Termin. Der Link auf die Datenschutzerklaerung des
* Betriebs (betrieb.datenschutzUrl) steht nicht im Text; das Widget setzt ihn daneben. Die Betriebs-E-Mail steht nicht im Text.
*/
export function formularHinweis(einstellung) {
const daten = betriebsdaten(einstellung?.betrieb)
const du = einstellung.anrede === 'du'
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.`
const betrieben = 'Betrieben wird der Terminkalender in unserem Auftrag von der WEBklar GbR (Server: Hetzner, Deutschland).'
const cookies = 'Es werden keine Cookies gesetzt.'
return du
? `Datenschutz. Wir verwenden deine Angaben, um deinen Termin zu verwalten und zu bestätigen (Art. 6 Abs. 1 lit. b DSGVO). ${betrieben} `
+ `Wir speichern deine Daten ${frist} ${cookies} Bitte mach keine Angaben zu deiner Gesundheit. `
+ `Mehr erfährst du in unserer Datenschutzerklärung. Verantwortlich: ${verantwortlich}.`
: `Datenschutz. Wir verwenden Ihre Angaben, um Ihren Termin zu verwalten und zu bestätigen (Art. 6 Abs. 1 lit. b DSGVO). ${betrieben} `
+ `Wir speichern Ihre Daten ${frist} ${cookies} Bitte machen Sie keine Angaben zu Ihrer Gesundheit. `
+ `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, haltMinuten, ...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 ${d.haltMinuten} 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, zum Beispiel weil unser Vertrag mit WEBklar endet, werden alle Termindaten 30 Tage nach dem Abschalten gelöscht. '
+ '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 ${d.haltMinuten} 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, zum Beispiel weil unser Vertrag mit WEBklar endet, werden alle Termindaten 30 Tage nach dem Abschalten gelöscht. '
+ '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),
haltMinuten: config.termine.holdMinutes, // Gueltigkeit des Bestaetigungslinks, bei jedem Aufruf gelesen
}
return absaetze.map((absatz) => absatz(d)).join(ABSATZ)
}
// ---------------------------------------------------------------- Zustimmungen (Haken) und Hinweis zu Gesundheitsangaben
/**
* Pflicht-Zustimmung zum vorzeitigen Beginn (§ 356 Abs. 5 Nr. 2 BGB, § 357a Abs. 2 BGB): nur bei Leistung mit Preis und
* Verbrauchern, bei sofort buchbaren Leistungen mit Terminbeginn vor Ablauf der Widerrufsfrist, bei Anfragen immer
* (brauchtZustimmungVorzeitig). Sie-Form auch bei Du-Betrieben.
*/
export const ZUSTIMMUNG_VORZEITIG = (name) =>
`Ich verlange ausdrücklich, dass ${name} mit der Leistung vor Ablauf der Widerrufsfrist beginnt. `
+ 'Mir ist bekannt, dass mein Widerrufsrecht mit der vollständigen Erbringung der Leistung erlischt (§ 356 Abs. 5 Nr. 2 BGB). '
+ 'Widerrufe ich vor der vollständigen Erbringung, schulde ich einen angemessenen Betrag für die bis dahin erbrachte Leistung (§ 357a Abs. 2 BGB).'
/** Pflicht-Haken, wenn der Betrieb Stornobedingungen hat und die gebuchte Leistung einen Preis hat (bei kostenlosen Leistungen gibt es ihn nicht). */
export const ZUSTIMMUNG_STORNO = 'Ich habe die Stornobedingungen gelesen.'
/**
* Freiwilliger Haken (nie vorangekreuzt), nur wenn der Betrieb Erinnerungen anbietet; stunden = einstellung.erinnerung.stundenVorher.
* Der zweite Satz weist auf das Widerrufsrecht der Einwilligung hin (Art. 7 Abs. 3 DSGVO); der Hash im Nachweis deckt beide Saetze.
*/
export const ZUSTIMMUNG_ERINNERUNG = (stunden) =>
`Ich möchte ${stunden} Stunden vor dem Termin eine Erinnerung per E-Mail erhalten. Diese Einwilligung kann ich jederzeit widerrufen.`
/** Hinweis ueber dem Nachrichtenfeld (Gesundheitsbereich ist ausgeschlossen, Spezifikation Abschnitt 4). */
export const GESUNDHEIT_HINWEIS = 'Bitte keine Gesundheitsangaben.'