Öffnungszeiten: Fixrunde Server (Schema-Kopplung, K27, Wertersatz, Widerruf, Ticket nachlegen)
- activate() schreibt die Zeiten-Felder (aboEndeAt, behaltenSessionId) nur noch über extra
(nur Abo-Rückkehr und Team-Aktivierung der Zeiten); News und Terminplaner laufen auch vor zeiten-setup.mjs
- Abo-Abgleich: K27 gilt als offen, solange der Marker vor disabledAt liegt (kein Zurücksetzen nach disable() nötig);
K27 geht erst nach dem Ersatz-Ticket raus (scheitert es, wiederholt der nächste Lauf beides);
Löschung setzt auch activatedAt zurück
- Zustimmung "beginn" (bezahlt) mit Wertersatz-Satz (§ 357a Abs. 2 BGB) wie bei News und Terminplaner, Fassung 2026-10-05
- Widerruf: Bestellung "zeiten" in ORDERS, FEATURE_OF_ORDER, orderLabel und widerrufen.html
- Team "Ticket nachlegen" der Zeiten ohne Kauf geht über holeZeitenNach statt über den Zahlungsweg
- Einschalten-Route nimmt nur { zustimmung }, nicht die Altform { consent: true }
- Team-Aktivierung behält kauf/unlockedByPurchase bei einem bisher gekauften Dokument
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c10e50d0b3
commit
ecf67d6978
13 files changed
+337
-48
No files matched your search
@@ -1007,6 +1007,40 @@ test('widerruf_termine_mails: K04 nennt „Terminplaner (Einrichtung)“, T09 de
|
||||
}
|
||||
})
|
||||
|
||||
test('widerruf_zeiten: „Öffnungszeiten live“ gehört zu den Zeiten (nicht zur News), Frist und Produkt in K04 und T09 stimmen', async () => {
|
||||
const newsAt = daysAgo(20)
|
||||
const zeitenAt = daysAgo(3)
|
||||
seedBezahlt({ projectId: 'pn1', projektName: 'Bäckerei News', featureKey: 'news', orderedAt: newsAt, state: 'active' })
|
||||
seedBezahlt({ projectId: 'pz1', projektName: 'Praxis Zeiten', featureKey: 'zeiten', orderedAt: zeitenAt })
|
||||
try {
|
||||
await resetSubH({ units: 0 })
|
||||
const before = st.calls.length
|
||||
assert.equal((await withdraw({ order: 'zeiten', customerNumber: 'KD-9' })).status, 200)
|
||||
const kunde = k04()
|
||||
assert.match(kunde.subject, /WEBklar Öffnungszeiten live$/)
|
||||
assert.match(kunde.text, /Widerruf der Bestellung „Öffnungszeiten live“/)
|
||||
assert.match(kunde.text, /Wir prüfen Ihren Widerruf/)
|
||||
assert.doesNotMatch(kunde.text, /News-Pinnwand|Es erfolgen keine weiteren Abbuchungen/)
|
||||
const team = t09().text
|
||||
assert.ok(team.includes(`Widerruf einer Funktion (${config.features.zeiten.label.name}, ${config.features.zeiten.priceLabel} einmalig)`), team)
|
||||
assert.match(team, /Öffnungszeiten live/)
|
||||
assert.match(team, /RECHTZEITIG/, 'Frist der Zeiten (vor 3 Tagen), nicht die der News (vor 20 Tagen)')
|
||||
assert.ok(team.includes(fmtDate(withdrawalDeadline(zeitenAt).endsAt)), 'Fristende der Zeiten')
|
||||
assert.match(team, /Praxis Zeiten: in Einrichtung/)
|
||||
assert.doesNotMatch(team, /Bäckerei News/, 'die News-Bestellung gehört nicht zu dieser Wahl')
|
||||
assert.equal(st.calls.length, before, 'kein Stripe-Aufruf')
|
||||
assert.equal(aw.docs('portalFeatures').get('f_pz1_zeiten').state, 'setup', 'nichts automatisch geändert')
|
||||
|
||||
// „Funktion“ bleibt die News: ihre Frist ist abgelaufen, die jungen Zeiten retten sie nicht
|
||||
await resetSubH({ units: 0 })
|
||||
assert.equal((await withdraw({ order: 'funktion' })).status, 200)
|
||||
assert.match(t09().text, /NACH Fristende/)
|
||||
assert.doesNotMatch(t09().text, /Praxis Zeiten/)
|
||||
} finally {
|
||||
await raeumeBezahlt('f_pn1_news', 'f_pz1_zeiten')
|
||||
}
|
||||
})
|
||||
|
||||
test('widerruf_anker_vertragAt: Zustimmung zur bezahlten Sitzung früher als das überschriebene orderedAt - Frist aus vertragAt; je Funktion gefiltert', async () => {
|
||||
await resetSubH({ units: 0 })
|
||||
// Terminplaner: Klick vor 13 Tagen, orderedAt (Neubestellung) vor 1 Tag; eine News vor 2 Tagen bestellt (kein Einfluss)
|
||||
@@ -1279,6 +1313,7 @@ test('widerrufen_html_radio: Radioknöpfe order', () => {
|
||||
assert.match(src, /name="order" value="zusatzspeicher"[^>]*> E-Mail-Zusatzspeicher/)
|
||||
assert.match(src, /name="order" value="funktion"[^>]*> Funktion \(z\. B\. News-Pinnwand\)/)
|
||||
assert.match(src, /name="order" value="termine"[^>]*data-text="Terminplaner \(Einrichtung\)"[^>]*> Terminplaner \(Einrichtung\)<\/label>/)
|
||||
assert.match(src, /name="order" value="zeiten"[^>]*data-text="Öffnungszeiten live"[^>]*> Öffnungszeiten live<\/label>/)
|
||||
assert.doesNotMatch(src, /value="WEBklar Wartungs-Abo" disabled/)
|
||||
assert.match(src, /fields: \['order', 'name', 'customerNumber', 'email'\]/)
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user