Terminplaner: Aktionen des Betriebs, manuelle Termine, Sperren
Neues Modul ablaufBetrieb.js: aktion (annehmen, ablehnen, absagen, verschieben, nichterschienen, anonymisieren), manuell, sperre, entsperre. ablauf.js exportiert die gemeinsamen Bausteine (Pruefungen, Meldungen, mailSicher, pruefeSlot, verschiebeKern). R31: brauchtZustimmungVorzeitig folgt der Berliner Widerrufsfrist (withdrawalDeadline ab now + Haltezeit); bei einer Anfrage mit Preis immer. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c4ec24448e
commit
be49d38e0c
8 files changed
+1563
-79
No files matched your search
@@ -721,28 +721,56 @@ test('istVerbraucher: nicht nur Unternehmer und keine Freizeitleistung', () => {
|
||||
assert.equal(istVerbraucher({ recht: { gaesteSind: 'verbraucher', freizeit: true } }), false)
|
||||
})
|
||||
|
||||
test('brauchtZustimmungVorzeitig: verbindlich + Preis + Verbraucher + Beginn in weniger als 14 Tagen', () => {
|
||||
test('brauchtZustimmungVorzeitig: verbindlich + Preis + Verbraucher + Beginn bis zum Ende der Widerrufsfrist (Berliner Kalender, §§ 187, 188, 193 BGB)', () => {
|
||||
const verbraucher = { recht: { gaesteSind: 'verbraucher', freizeit: false } }
|
||||
const unternehmer = { recht: { gaesteSind: 'unternehmer', freizeit: false } }
|
||||
const freizeit = { recht: { gaesteSind: 'verbraucher', freizeit: true } }
|
||||
const mitPreis = { buchungsart: 'sofort', preisArt: 'fest', preisCent: 4500 }
|
||||
const inTagen = (n) => new Date(NOW.getTime() + n * TAG)
|
||||
// NOW = Freitag 02.10.2026, 12:00 Berlin; Vertragsschluss spaetestens nach der Haltezeit (30 Minuten): Fristende
|
||||
// Freitag 16.10.2026, 23:59:59,999 Uhr Berlin = 21:59:59,999 Uhr UTC (MESZ)
|
||||
const FRISTENDE = Date.parse('2026-10-16T21:59:59.999Z')
|
||||
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, inTagen(3), NOW), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, inTagen(20), NOW), false)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, inTagen(14), NOW), false)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date(inTagen(14).getTime() - 1), NOW), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, inTagen(0), NOW), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, inTagen(20), NOW), false)
|
||||
// Grenze: die letzte Millisekunde der Frist ja, die naechste nein
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date(FRISTENDE), NOW), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date(FRISTENDE + 1), NOW), false)
|
||||
// 14 mal 24 Stunden reichen nicht: 14 Tage nach der Buchung um 12:00 liegen noch in der Frist (bis 24 Uhr des Tages)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, inTagen(14), NOW), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, { ...mitPreis, preisArt: 'ab' }, inTagen(3), NOW), true)
|
||||
// Unternehmer, Freizeit, kein Preis, Anfrage: keine Zustimmung noetig
|
||||
// Fristende auf einem Wochenende ⇒ naechster Werktag: Samstag 10.10.2026 + 14 = Samstag 24.10. ⇒ Montag 26.10., 23:59:59,999 Uhr Berlin (MEZ)
|
||||
const SAMSTAG = new Date('2026-10-10T10:00:00.000Z')
|
||||
const wochenendeEnde = Date.parse('2026-10-26T22:59:59.999Z')
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date(wochenendeEnde), SAMSTAG), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date(wochenendeEnde + 1), SAMSTAG), false)
|
||||
// die Haltezeit zaehlt mit: wer um 23:45 Uhr bucht, schliesst den Vertrag erst nach Mitternacht (Fristende einen Tag spaeter)
|
||||
// (Samstag 03.10. + 14 = Samstag 17.10. ⇒ Montag 19.10., 23:59:59,999 Uhr Berlin = 21:59:59,999 Uhr UTC)
|
||||
const spaet = new Date('2026-10-02T21:45:00.000Z') // 23:45 Uhr Berlin, Freitag; + 30 Minuten = Samstag 00:15 Uhr
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date(Date.parse('2026-10-16T21:59:59.999Z') + 1), spaet), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date(Date.parse('2026-10-19T21:59:59.999Z') + 1), spaet), false)
|
||||
// Unternehmer, Freizeit, kein Preis: keine Zustimmung noetig
|
||||
assert.equal(brauchtZustimmungVorzeitig(unternehmer, mitPreis, inTagen(3), NOW), false)
|
||||
assert.equal(brauchtZustimmungVorzeitig(freizeit, mitPreis, inTagen(3), NOW), false)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, { ...mitPreis, preisArt: 'keiner', preisCent: 0 }, inTagen(3), NOW), false)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, { ...mitPreis, buchungsart: 'anfrage' }, inTagen(3), NOW), false)
|
||||
// ungueltiger Beginn: lieber die Zustimmung verlangen
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, mitPreis, new Date('kaputt'), NOW), true)
|
||||
})
|
||||
|
||||
test('brauchtZustimmungVorzeitig: bei einer Anfrage mit Preis fuer Verbraucher immer (der Tag der Annahme ist unbekannt)', () => {
|
||||
const verbraucher = { recht: { gaesteSind: 'verbraucher', freizeit: false } }
|
||||
const anfrage = { buchungsart: 'anfrage', preisArt: 'fest', preisCent: 4500 }
|
||||
const inTagen = (n) => new Date(NOW.getTime() + n * TAG)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, anfrage, inTagen(3), NOW), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, anfrage, inTagen(60), NOW), true)
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, anfrage, new Date('kaputt'), NOW), true)
|
||||
// ohne Preis, Unternehmer, Freizeit: nein
|
||||
assert.equal(brauchtZustimmungVorzeitig(verbraucher, { ...anfrage, preisArt: 'keiner', preisCent: 0 }, inTagen(3), NOW), false)
|
||||
assert.equal(brauchtZustimmungVorzeitig({ recht: { gaesteSind: 'unternehmer', freizeit: false } }, anfrage, inTagen(3), NOW), false)
|
||||
assert.equal(brauchtZustimmungVorzeitig({ recht: { gaesteSind: 'verbraucher', freizeit: true } }, anfrage, inTagen(3), NOW), false)
|
||||
})
|
||||
|
||||
test('preisText, preisHinweis, zahlungText', () => {
|
||||
assert.equal(preisText({ preisArt: 'fest', preisCent: 4500 }), '45,00 €')
|
||||
assert.equal(preisText({ preisArt: 'ab', preisCent: 4500 }), 'ab 45,00 €')
|
||||
|
||||
Reference in new issue
Block a user