Bestelltexte des Terminplaners (vier Zustimmungen, Belehrung im Nachweis, Fassung)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-05 03:10:29 +00:00
1 parent 49acd13f84
commit 03bdeb4461
7 files changed
+408 -40

No files matched your search

+71 -27
View File
@@ -148,21 +148,78 @@ const ticketProjektName = (project) => project?.projectName || project?.subdomai
/**
* Rechtsunterlage des Terminplaners mit Fassung und Adresse aus config.termine.avvVersion (bei jedem Zugriff gelesen).
* Tests duerfen sie ueberschreiben (Zuweisung); wird der aktuelle Standardwert zurueckgeschrieben (Wiederherstellen nach
* dem Test) oder null/undefined zugewiesen, gilt wieder der Standard und die Unterlage folgt der Konstante.
* dem Test) oder undefined zugewiesen, gilt wieder der Standard und die Unterlage folgt der Konstante. null gilt ebenso,
* ausser bei nullIstWert (Widerrufsbelehrung): dort heisst null "keine Unterlage" (so setzen Tests eine Bestellung ohne sie).
*/
function termineRechtsunterlage(slug) {
let ueberschrieben = null
function termineRechtsunterlage(slug, { nullIstWert = false } = {}) {
let ueberschrieben // undefined = Standard
const standard = () => ({ version: config.termine.avvVersion, url: `/rechtliches/${slug}-${config.termine.avvVersion}.html` })
return {
get: () => ueberschrieben ?? standard(),
get: () => (ueberschrieben === undefined ? standard() : ueberschrieben),
set(wert) {
const std = standard()
ueberschrieben = wert == null || (wert.version === std.version && wert.url === std.url) ? null : wert
const zurueck = wert === undefined || (wert === null && !nullIstWert) || (wert !== null && wert.version === std.version && wert.url === std.url)
ueberschrieben = zurueck ? undefined : wert
},
}
}
const termineLb = termineRechtsunterlage('leistungsbeschreibung-terminplaner')
const termineAvv = termineRechtsunterlage('avv-terminplaner')
const termineWiderruf = termineRechtsunterlage('widerrufsbelehrung-funktionen', { nullIstWert: true })
const TERMINE_PREIS = '149 €'
const TERMINE_DAUER = 'meist innerhalb von 1–2 Wochen'
/**
* Bestelltexte des Terminplaners (Task F7): vier Haken, alle Besteller (D1), ohne Adressen im Text (die versionierten Links
* zeigt die Bestellseite daneben aus bestellung.dokumente). Die Fassung (consent.version) ist config.termine.avvVersion; die
* dynamischen Teile (Fassung, Preis, Umsatzsteuer-Hinweis, Dauer) stehen fertig im Text, gespeichert wird immer dieser Text.
* Die Haken werden je Fassung einmal gebaut und danach unveraendert herausgegeben (Tests aendern einzelne Texte und stellen sie
* zurueck); aendert sich die Fassung zur Laufzeit, entstehen sie neu. Bei Textaenderung neues Fassungsdatum und neuen Hash im
* Pin von test/featureConsentTexte.test.js. Zitat und Wertersatz-Satz von "beginn" und die Pflichtinformationen sind Entwurf bis
* zur Kanzlei (Kanzlei-Paket, Fragen Q3, Q5, Q19, Q20).
*/
function termineConsent() {
let versionGesetzt // undefined = config.termine.avvVersion
let gebaut = null // { version, items }
const version = () => versionGesetzt ?? config.termine.avvVersion
const items = (v) => [
{
id: 'unterlagen',
haken: true,
text: `Ich stimme der Leistungsbeschreibung Terminplaner und dem Auftragsverarbeitungsvertrag Terminplaner in der Fassung ${v} zu.`,
},
{
id: 'gesundheit',
haken: true,
text: 'Mein Angebot liegt nicht im Gesundheitsbereich (zum Beispiel keine Arzt-, Zahnarzt-, Psychotherapie-, Heilpraktiker- oder Physiotherapiepraxis).',
},
{
id: 'beginn',
haken: true,
text: 'Ich verlange ausdrücklich, dass WEBklar vor Ablauf der Widerrufsfrist mit der Einrichtung des Terminplaners beginnt. Mir ist bekannt, dass mein Widerrufsrecht mit der vollständigen Erbringung der Einrichtung 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).',
},
{
id: 'information',
haken: true,
text: `Ich habe die Pflichtinformationen zu dieser Bestellung gelesen: Leistung (Einrichtung des Terminplaners für diese Website: ein Widget an einer Stelle, gestaltet nach dem Fragebogen, mit Einbau und Datenschutz-Absatz), Gesamtpreis ${TERMINE_PREIS} einmalig (${ustHinweis}), voraussichtliche Dauer ${TERMINE_DAUER}, der Terminplaner endet mit dem Wartungs-Abo. Die Widerrufsbelehrung mit Muster-Widerrufsformular habe ich gelesen.`,
},
]
return {
get version() {
return version()
},
set version(wert) {
versionGesetzt = wert === undefined || wert === null || wert === config.termine.avvVersion ? undefined : wert
},
knopf: `Zahlungspflichtig bestellen · ${TERMINE_PREIS}`,
get items() {
const v = version()
if (gebaut?.version !== v) gebaut = { version: v, items: items(v) }
return gebaut.items
},
}
}
/**
* Register der kaufbaren Funktionen (News-Pinnwand, Terminplaner): Preis, Zustimmungen, Rechtsunterlagen,
@@ -243,27 +300,9 @@ const features = {
key: 'termine',
product: 'termineSetup',
label: { name: 'Terminplaner', kurz: 'Termine', keine: 'keinen Terminplaner' },
priceLabel: '149 €',
setupEstimate: 'meist innerhalb von 1–2 Wochen',
// Platzhalter bis Block F (Rechtsrunde): Struktur und IDs stehen, Texte und Fassung ersetzt Block F
consent: {
version: 'ENTWURF-2026-10-03',
knopf: 'Zahlungspflichtig bestellen · 149 €',
items: [
{ id: 'unterlagen', haken: true, text: 'ENTWURF (Block F): Zustimmung zu Leistungsbeschreibung und Auftragsverarbeitungsvertrag (AVV) Terminplaner.' },
{ id: 'gesundheit', haken: true, text: 'ENTWURF (Block F): Bestätigung, dass der Terminplaner nicht im Gesundheitsbereich eingesetzt wird.' },
{
id: 'beginn',
haken: true,
text: 'ENTWURF (Block F): Ausdrückliches Verlangen, dass vor Ablauf der Widerrufsfrist mit dem Einbau begonnen wird, mit Hinweis auf das Erlöschen des Widerrufsrechts und den Wertersatz.',
},
{
id: 'information',
haken: true,
text: 'ENTWURF (Block F): Pflichtinformationen zu Leistung, Gesamtpreis, Ende mit dem Wartungs-Abo und Einrichtungsdauer.',
},
],
},
priceLabel: TERMINE_PREIS,
setupEstimate: TERMINE_DAUER,
consent: termineConsent(),
// Fassung und Adresse folgen config.termine.avvVersion bei jedem Zugriff (Slugs wie in services/legalDocs.js; config.js
// importiert keine Dienste, test/legalDocs.test.js gleicht beide ab)
get leistungsbeschreibung() {
@@ -278,7 +317,12 @@ const features = {
set avv(wert) {
termineAvv.set(wert)
},
widerruf: null,
get widerruf() {
return termineWiderruf.get()
},
set widerruf(wert) {
termineWiderruf.set(wert)
},
returnHash: 'termine',
returnProjekt: true,
ticket: {
+8 -4
View File
@@ -39,10 +39,14 @@ async function termineFreischaltbar(doc) {
}
/**
* Platzhalter der Widerrufsbelehrung mit Muster-Widerrufsformular, die die Bestellseite vor dem Knopf zeigt und der
* Zustimmungsnachweis speichert. Block F (Task F7) ersetzt den Haken belehrung durch widerrufsbelehrungFunktion().
* Widerrufsbelehrung mit Muster-Widerrufsformular der Funktionen (Gesetzesmuster, Sie-Form), die die Bestellseite vor dem Knopf
* zeigt und der Zustimmungsnachweis speichert: dieselbe Zeichenkette an beiden Stellen (Task F7, Text aus Task F3). Geladen
* wird sie erst beim Aufruf (kein Importzyklus).
*/
export const BELEHRUNG_PLATZHALTER = 'ENTWURF (Block F): Widerrufsbelehrung mit Muster-Widerrufsformular.'
async function termineBelehrung() {
const { widerrufsbelehrungFunktion } = await import('./termine/rechtstexte.js')
return widerrufsbelehrungFunktion()
}
/**
* Standard-Haken je Funktion (Funktionen, nicht Daten). B6 fuellt verfuegbar, bestellpruefung und unterlagenBereit
@@ -56,7 +60,7 @@ const STANDARD_HAKEN = {
verfuegbar: (email) => termineFuerKunde(email),
bestellpruefung: termineBestellpruefung,
unterlagenBereit: async () => true,
belehrung: async () => BELEHRUNG_PLATZHALTER,
belehrung: termineBelehrung,
freischaltbar: termineFreischaltbar,
},
}