Datenschutz: neue Fassung vom 29.10.2026 zum Umschalten der Kundenansicht (R14)
Prüfpunkte D1 bis D8 der Rechtsrunde umgesetzt: Kundenart im Kundenkonto (D3), Nachweis beim Einschalten einer Funktion ohne Zahlung (D1, D4), Wortlaut und Kundenart im Nachweis bei Abo, Wechsel, Zusatzspeicher (D2) und Übernahmegutschrift, Website-Analyse im Hosting- und Wartungs-Abo (D5), Ende und Löschfristen der Funktionen im Abo-Modell (D6), Vorschuss im Stundenkonto (D7). Neu Abschnitt 6e Öffnungszeiten live, auf den die Leistungsbeschreibung Fassung 6 verweist. Der Bestand einzeln gekaufter Funktionen bleibt beschrieben. PDF neu gedruckt, Pins nachgezogen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
756f7e6153
commit
b1a582cb20
7 files changed
+77
-19
No files matched your search
+46
-6
@@ -384,7 +384,7 @@ test('Rechtsrunde: Zusatzspeicher ganz oder teilweise kündbar, auch über „Ve
|
||||
|
||||
test('Rechtsrunde Datenschutz: Aufbewahrung nach dem Ende des letzten Abos, Zahl der Pakete, kurzer UptimeRobot-Eintrag', () => {
|
||||
const html = read(DS), ds = strip(html)
|
||||
assert.equal(ds.split('drei Jahre nach Ablauf des Jahres, in dem Ihr letztes Abo endet').length - 1, 3, 'Abschnitt 7 (Bestellungen, Funktionsbestellung) und Kündigungs-/Widerrufsseite')
|
||||
assert.equal(ds.split('drei Jahre nach Ablauf des Jahres, in dem Ihr letztes Abo endet').length - 1, 5, 'Abschnitt 7 (Bestellungen, Funktionsbestellung, Einschalten einer Funktion, Nachweis der Übernahmegutschrift) und Kündigungs-/Widerrufsseite')
|
||||
for (const s of ['drei Jahre nach Vertragsende', 'nach dem Ende Ihres letzten Abos']) assert.ok(!ds.includes(s), `noch da: ${s}`)
|
||||
// Abschnitt 6 (Kundenkonto) verweist für Abos und Bestellungen auf die Fristen in Abschnitt 7
|
||||
assert.ok(between(ds, '6. Kundenportal', '7. Abos').includes('Für Ihre Abos und Bestellungen gelten die Fristen in Abschnitt 7.'))
|
||||
@@ -613,8 +613,8 @@ test('legal_datenschutz_webshop: Abschnitt 6d steht zwischen 6c und 7 und nennt
|
||||
const html = read(DS)
|
||||
const termine = html.indexOf('id="termine"')
|
||||
const webshop = html.indexOf('id="webshop"')
|
||||
const sieben = html.indexOf('<h2 id="buchungskalender">') // 6f folgt auf 6d (Buchungskalender)
|
||||
assert.ok(termine > 0 && webshop > termine && sieben > webshop && html.indexOf('<h2>7. ') > sieben, 'Reihenfolge 6c < 6d < 6f < 7')
|
||||
const sieben = html.indexOf('<h2 id="zeiten">') // 6e (Öffnungszeiten live) folgt auf 6d, danach 6f (Buchungskalender)
|
||||
assert.ok(termine > 0 && webshop > termine && sieben > webshop && html.indexOf('<h2 id="buchungskalender">') > sieben && html.indexOf('<h2>7. ') > sieben, 'Reihenfolge 6c < 6d < 6e < 6f < 7')
|
||||
assert.equal(html.split('id="webshop"').length - 1, 1)
|
||||
assert.ok(html.includes('<h2 id="webshop">6d. Webshop auf Websites unserer Kunden</h2>'))
|
||||
const roh = html.slice(webshop, sieben)
|
||||
@@ -631,9 +631,11 @@ test('legal_datenschutz_webshop: Abschnitt 6d steht zwischen 6c und 7 und nennt
|
||||
// Orte und Fristen wie im AVV Webshop
|
||||
for (const s of ['Falkenstein', 'Nürnberg', 'nach 30 Tagen', 'drei Jahre nach dem Ende des Jahres der Bestellung', '90 Tage', 'bis zu sieben Tage', 'Sitzungsspeicher', 'nicht dauerhaft']) assert.ok(text.includes(s), `6d: ${s}`)
|
||||
assert.ok(text.includes('Eine Ausnahme ist das Einrichtungs-Ticket'))
|
||||
// kein Abo-Bezug: der Webshop endet mit dem Vertrag über den Betrieb der Website (Entscheidung W5)
|
||||
// Bestand der einzeln gekauften Webshops (Entscheidung W5): der Satz über den Vertrag über den Betrieb der Website bleibt unverändert
|
||||
assert.ok(text.includes('endet der Vertrag über den Betrieb seiner Website'))
|
||||
assert.ok(!text.includes('Wartungs-Abo') && !text.includes('Hosting-Abo'), '6d nennt kein bestimmtes Abo')
|
||||
// Fassung 6 (R14, D6): im Wartungs-Abo eingeschaltet oder beim Bau eingebaut endet er mit dem Wartungs-Abo (auch beim Wechsel ins Hosting-Abo), spätestens am Folgetag; ein neues Wartungs-Abo in den 90 Tagen holt ihn von selbst zurück
|
||||
assert.ok(text.includes('Abweichend davon gilt für einen Webshop, den der Kunde im Wartungs-Abo eingeschaltet hat oder den wir auf Wunsch des Kunden schon beim Bau der Website eingebaut haben: Er endet mit dem Wartungs-Abo, auch bei einem Wechsel ins Hosting-Abo; wir schalten ihn dann spätestens am folgenden Tag ab.'))
|
||||
assert.ok(text.includes('Beginnt in dieser Frist wieder ein Wartungs-Abo, schalten wir ihn von selbst wieder ein; ein Hosting-Abo genügt dafür nicht.'))
|
||||
// Empfängerliste nennt den Webshop bei Stripe
|
||||
assert.ok(strip(html).includes('Eröffnung des Stripe-Kontos für den Webshop und den Buchungskalender unserer Kunden (Abschnitte 6d, 6f und 7)'))
|
||||
})
|
||||
@@ -739,7 +741,7 @@ test('legal_datenschutz_4a: eigene Website-Analyse auf webklar.com mit Rolle, Re
|
||||
test('legal_datenschutz_anfragen: Abschnitt 11 beschreibt nur den Anfrage-Weg (KI bewertet, Mitarbeiter sendet von Hand), mit Anker, Quelle, Daten, Rechtsgrundlage, Fristen und Widerspruch', () => {
|
||||
const html = read(DS)
|
||||
// Stand-Pin: der Tag der Fassung (das endgültige Datum setzt der Push, dann auch hier)
|
||||
assert.ok(html.includes('<p class="meta">Stand 22.10.2026</p>'), 'Stand 22.10.2026')
|
||||
assert.ok(html.includes('<p class="meta">Stand 29.10.2026</p>'), 'Stand 29.10.2026')
|
||||
assert.match(html, /<a id="interessenten"><\/a>\s*<h2>11\. Interessenten: Antworten auf öffentliche Anfragen<\/h2>/)
|
||||
assert.equal(html.split('id="interessenten"').length - 1, 1, 'der Anker steht genau einmal da')
|
||||
const s = between(strip(html), '11. Interessenten: Antworten auf öffentliche Anfragen', '12. Empfänger im Überblick')
|
||||
@@ -883,3 +885,41 @@ test('legal_datenschutz_anfragen: Abschnitt 2, 12 und 14 passen zu Abschnitt 11
|
||||
// Abschnitt 8 (E-Mail über Hetzner) bleibt unverändert gültig, Abschnitt 11 verweist darauf, statt davon abzuweichen
|
||||
assert.ok(between(ds, '8. E-Mail', '9. Buchhaltung').includes('versenden und empfangen wir über den E-Mail-Dienst der Hetzner Online GmbH'))
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------- Fassung vom 29.10.2026: Umschalten der Kundenansicht (R14, Prüfpunkte D1 bis D8)
|
||||
|
||||
test('legal_datenschutz_umschalten: Kundenart, Einschalten ohne Zahlung, Abo-Ende und Fristen wie die Leistungsbeschreibungen der Fassung 6', () => {
|
||||
const html = read(DS), ds = strip(html)
|
||||
// D3: Kundenart im Kundenkonto
|
||||
const konto = between(ds, '6. Kundenportal', '6a. News')
|
||||
assert.ok(konto.includes('Zu Ihrem Kundenkonto gehört außerdem Ihre Kundenart: „Betrieb“ oder „privat“.') && konto.includes('ist keine hinterlegt, gilt Ihr Konto als privat'))
|
||||
// D7: Vorschuss als Teil des Stundenkontingents
|
||||
assert.ok(konto.includes('Stundenkontingent (verfügbare Zeit, Verbrauch, Ablaufdaten und, wenn die Einrichtung einer Funktion mehr Zeit braucht, als verfügbar ist, ein Vorschuss)'))
|
||||
// D1, D2, D4: Nachweis beim Einschalten ohne Zahlung, Wortlaut und Kundenart, alle sechs Funktionen
|
||||
const sieben = between(ds, '7. Abos und Zahlung über Stripe', '8. E-Mail')
|
||||
assert.ok(sieben.includes('Im Kundenportal speichern wir außerdem den Wortlaut der Zeilen und Häkchen, die Ihnen beim Klick angezeigt wurden, und Ihre Kundenart zu diesem Zeitpunkt (Abschnitt 6).'))
|
||||
assert.ok(sieben.includes('Schalten Sie eine Funktion im Kundenportal ein (News-Pinnwand, Terminplaner, Webshop, Buchungskalender, Öffnungszeiten live oder Website-Analyse), gehört das zu Ihrem Abo. Es löst keine Zahlung aus, und es gibt keine Stripe-Sitzung.'))
|
||||
assert.ok(sieben.includes('Bestellen Sie eine Funktion (News-Pinnwand, Terminplaner), speichern wir als Nachweis'), 'der Bestand der einzeln gekauften Funktionen bleibt beschrieben')
|
||||
// D5: Website-Analyse in beiden Abos, 60 Tage (AVV Website-Analyse Nr. 9)
|
||||
const analyse = section(html, 'analyse', 'termine')
|
||||
assert.ok(analyse.includes('Kunden mit Hosting-Abo oder Wartungs-Abo') && analyse.includes('wechselt der Kunde vom Wartungs- ins Hosting-Abo, bleibt sie') && analyse.includes('60 Tage nach dem Abschalten'))
|
||||
// D6: Funktionen im Abo enden mit dem Wartungs-Abo, die Fristen wie in den Leistungsbeschreibungen
|
||||
const news = section(html, 'news', 'analyse')
|
||||
assert.ok(news.includes('im Wartungs-Abo eingeschaltet oder haben wir sie auf Ihren Wunsch schon beim Bau Ihrer Website eingebaut, gilt stattdessen: Sie endet mit dem Wartungs-Abo'))
|
||||
assert.ok(news.includes('spätestens am folgenden Tag ab und löschen alle Beiträge und Fotos 30 Tage nach dem Abschalten'))
|
||||
const shop = section(html, 'webshop', 'zeiten'), buchung = strip(html.slice(html.indexOf('id="buchungskalender"'), html.indexOf('<h2>7. ')))
|
||||
for (const [text, name] of [[shop, 'Webshop'], [buchung, 'Buchungskalender']]) {
|
||||
assert.ok(text.includes(`im Wartungs-Abo eingeschaltet hat oder den wir auf Wunsch des Kunden schon beim Bau der Website eingebaut haben: Er endet mit dem Wartungs-Abo, auch bei einem Wechsel ins Hosting-Abo; wir schalten ihn dann spätestens am folgenden Tag ab.`), `${name}: Ende mit dem Abo`)
|
||||
assert.ok(text.includes('Beginnt in dieser Frist wieder ein Wartungs-Abo, schalten wir ihn von selbst wieder ein; ein Hosting-Abo genügt dafür nicht.'), `${name}: Rückkehr von selbst`)
|
||||
assert.ok(text.includes('90 Tage'), `${name}: 90 Tage`)
|
||||
}
|
||||
// Öffnungszeiten live (§ 6e): 30 Tage Weiterlauf, danach 30 Tage Eingaben, kein Behalten
|
||||
const zeiten = section(html, 'zeiten', 'buchungskalender')
|
||||
assert.ok(zeiten.includes('läuft die Funktion noch 30 Tage unverändert weiter; danach schalten wir sie ab. Die Eingaben des Kunden bleiben nach dem Abschalten 30 Tage gespeichert und werden danach gelöscht'))
|
||||
assert.ok(!/behalten/i.test(zeiten))
|
||||
// D8: die Seiten Kündigen und Widerrufen bleiben unverändert (kein neues Datum)
|
||||
assert.ok(ds.includes('Über die Seiten project.webklar.com/kuendigen.html und project.webklar.com/widerrufen.html können Sie Ihren Vertrag ohne Anmeldung kündigen oder widerrufen'))
|
||||
// Stand und Du-Form: die öffentliche Erklärung bleibt in der Sie-Form
|
||||
assert.ok(html.includes('<p class="meta">Stand 29.10.2026</p>'))
|
||||
assert.ok(!/\b(du|dein\w*|dir|dich)\b/i.test(ds), 'keine Du-Form')
|
||||
})
|
||||
Reference in new issue
Block a user