Terminplaner: Abschluss – Server (Widerruf auch bei Anfragen, Gastdaten löschen vollständig, formMinSekunden)

- R55: Widerrufsbelehrung, Anschrift-Pflicht und Knopf "Vertrag widerrufen" gelten für jede
  Verbraucher-Buchung mit sichtbarer Leistung, auch Anfragen (zeigtWiderruf); der Nachweis
  hält die Belehrung auch bei Anfragen fest. Damit bleibt die Annahme einer Anfrage nie mehr
  still ohne G02.
- "Gastdaten löschen" leert auch absageGrund und löscht noch nicht versandte Mails der Buchung
  (neu: verwerfeWartende in der Warteschlange).
- R53: GET /:siteKey/config nennt formMinSekunden.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-03 08:17:44 +00:00
1 parent 4be886a4de
commit bd65c9dc58
11 files changed
+216 -18

No files matched your search

+7 -1
View File
@@ -3,6 +3,7 @@ import { withLocks } from '../keyedLock.js'
import { aendere, hole, legeAn, loesche } from './buchungen.js'
import { text as bereinigterText } from './einstellungen.js'
import { anGast } from './mails.js'
import { verwerfeWartende } from './outbox.js'
import {
MELDUNG,
VERWALTBAR,
@@ -172,18 +173,23 @@ async function nichterschienen(_ctx, frisch, _eingabe, now) {
/**
* Gastdaten auf Wunsch loeschen: Name "Gelöscht", E-Mail, Telefon, Nachricht und Zusatzfelder leer, keine Erinnerung,
* Links ungueltig (Hashes leer). Status und Zeiten bleiben. Bei abgesagt/abgelehnt bleibt updatedAt stehen, weil davon
* Links ungueltig (Hashes leer), absageGrund leer (er kann den vom Gast getippten Namen einer Widerrufserklaerung oder
* einen frei getippten Grund des Betriebs enthalten). Noch nicht versandte Mails der Buchung (Outbox, Status wartet)
* werden geloescht, sie halten Adresse und Inhalt; zuerst, damit ein Fehler dort noch nichts geaendert hat und ein
* zweiter Klick alles nachholt. Status und Zeiten bleiben. Bei abgesagt/abgelehnt bleibt updatedAt stehen, weil davon
* die Loeschfrist (30 Tage) laeuft. Eine noch nicht bestaetigte Haltung bleibt unberuehrt (409).
*/
async function anonymisieren(_ctx, frisch, _eingabe, now) {
if (frisch.status === 'gehalten') throw nichtMoeglich(MELDUNG_BETRIEB.nochOffen)
const behalteFrist = frisch.status === 'abgesagt' || frisch.status === 'abgelehnt'
await verwerfeWartende(frisch.$id)
const buchung = await aendere(frisch.$id, {
gastName: GELOESCHT,
gastEmail: '',
gastTelefon: '',
gastNachricht: '',
gastZusatz: '',
absageGrund: '',
erinnerung: false,
verifyHash: '',
manageHash: '',