Öffnungszeiten: Register und Texte im Ticketsystem

Funktionen-Reiter kennt "Öffnungszeiten live" (zeiten) hinter dem Terminplaner:
Bestätigungstexte, Site-Key, Aktionen je Zustand (Abnahme nur ohne Hindernis
"zeiten_fehlen"). Neues Modul zeitenView.js: Statustext (Einbau läuft / wartet
auf die Zeiten des Kunden / Abo-Ende mit Frist), navSelektorFehler (Spiegel
der Portal-Regel) und teamBody für PATCH .../zeiten/team. Protokoll-Label
für zeiten_gespeichert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 07:02:30 +00:00
1 parent 72eedeb59c
commit 994347408d
6 files changed
+326 -13

No files matched your search

+65 -1
View File
@@ -25,7 +25,7 @@ const {
featureBody,
} = await loadModule('src/lib/funktionenView.js')
test('FUNKTIONEN: News und Terminplaner mit den Bestätigungstexten', () => {
test('FUNKTIONEN: News, Terminplaner und Öffnungszeiten live (in dieser Reihenfolge) mit den Bestätigungstexten', () => {
assert.deepEqual(FUNKTIONEN, [
{
key: 'news',
@@ -45,9 +45,28 @@ test('FUNKTIONEN: News und Terminplaner mit den Bestätigungstexten', () => {
ticket: 'Fehlendes Einrichtungs-Ticket neu anlegen?',
},
},
{
key: 'zeiten',
label: 'Öffnungszeiten live',
bestaetigen: {
activate: 'Öffnungszeiten live ohne Zahlung aktivieren? Es startet der Einbau: Das Einbau-Ticket wird angelegt und die Seite, wenn möglich, neu gebaut. Freigeschaltet wird, sobald das Ticket geschlossen ist und der Kunde seine Zeiten eingetragen hat.',
disable: 'Öffnungszeiten live abschalten? Leisten und Live-Anzeige verschwinden von der Website, die feste Ersatz-Tabelle bleibt stehen. Die Angaben des Kunden bleiben gespeichert. Weicht der Wochenplan von der Ersatz-Tabelle ab, wird ein Ticket „Ersatz-Tabelle aktualisieren“ angelegt.',
abnahme: 'Öffnungszeiten live freischalten? Der Kunde bekommt die Mail „bereit“ und der Einbau gilt als abgenommen.',
ticket: 'Fehlendes Einbau-Ticket neu anlegen?',
},
},
])
})
test('FUNKTIONEN: Schlüssel sind eindeutig und jede Funktion hat Aktivieren und Abschalten bestätigt', () => {
assert.deepEqual(FUNKTIONEN.map((f) => f.key), ['news', 'termine', 'zeiten'])
for (const f of FUNKTIONEN) {
assert.ok(f.bestaetigen.activate && f.bestaetigen.disable, f.key)
}
const zeiten = FUNKTIONEN.find((f) => f.key === 'zeiten').bestaetigen
for (const text of Object.values(zeiten)) assert.doesNotMatch(text, /24 Uhr/, 'nie "24 Uhr"')
})
test('W1: der Abschalten-Dialog des Terminplaners nennt Buchungsstopp, Löschung nach 30 Tagen und die neue Bestellung (149 €)', () => {
const text = FUNKTIONEN.find((f) => f.key === 'termine').bestaetigen.disable
assert.match(text, /^Terminplaner abschalten\?/)
@@ -120,6 +139,40 @@ test('aktionen: Terminplaner mit fehlendem Ticket bietet in der Einrichtung zuer
}
})
test('aktionen: Öffnungszeiten live – aus nur Aktivieren, bestellt nur Abschalten, Einrichtung mit Abnahme, aktiv nur Abschalten, abgeschaltet nur Aktivieren', () => {
assert.deepEqual(aktionen('off', 'zeiten'), ['activate'])
assert.deepEqual(aktionen('ordered', 'zeiten'), ['disable'], 'wie beim Terminplaner: Aktivieren würde eine spätere Zahlung verschlucken')
assert.deepEqual(aktionen('setup', 'zeiten'), ['abnahme', 'disable'])
assert.deepEqual(aktionen('active', 'zeiten'), ['disable'])
assert.deepEqual(aktionen('disabled', 'zeiten'), ['activate'])
assert.deepEqual(aktionen(undefined, 'zeiten'), ['activate'])
})
test('aktionen: Öffnungszeiten live bietet die Abnahme nur ohne Hindernis an (wartet auf die Zeiten des Kunden: nur Abschalten)', () => {
assert.deepEqual(aktionen('setup', 'zeiten', { hindernis: 'zeiten_fehlen' }), ['disable'])
assert.deepEqual(aktionen('setup', 'zeiten', { hindernis: null }), ['abnahme', 'disable'])
assert.deepEqual(aktionen('setup', 'zeiten', { hindernis: undefined }), ['abnahme', 'disable'])
assert.deepEqual(aktionen('setup', 'zeiten', { ticketMissing: true, hindernis: 'zeiten_fehlen' }), ['ticket', 'disable'])
for (const state of ['off', 'ordered', 'active', 'disabled', undefined]) {
assert.deepEqual(aktionen(state, 'zeiten', { hindernis: 'zeiten_fehlen' }), aktionen(state, 'zeiten'), `${String(state)}: hindernis nur in setup`)
}
})
test('aktionen: Öffnungszeiten live mit fehlendem Ticket bietet in der Einrichtung zuerst "ticket" an (wie der Terminplaner)', () => {
assert.deepEqual(aktionen('setup', 'zeiten', { ticketMissing: true }), ['ticket', 'abnahme', 'disable'])
assert.deepEqual(aktionen('setup', 'zeiten', { ticketMissing: false }), ['abnahme', 'disable'])
for (const state of ['off', 'ordered', 'active', 'disabled', undefined]) {
assert.deepEqual(aktionen(state, 'zeiten', { ticketMissing: true }), aktionen(state, 'zeiten'), `${String(state)}: ticketMissing nur in setup`)
}
})
test('aktionen: Terminplaner und News ignorieren hindernis (der Terminplaner zeigt die Abnahme weiter, das Portal sperrt)', () => {
for (const hindernis of ['kein_abo', 'keine_einstellung', 'abo_unbekannt', 'zeiten_fehlen', null]) {
assert.deepEqual(aktionen('setup', 'termine', { hindernis }), ['abnahme', 'disable'], String(hindernis))
assert.deepEqual(aktionen('setup', 'news', { hindernis }), ['activate', 'disable'], String(hindernis))
}
})
test('AKTION_LABEL: Beschriftung je Aktion', () => {
assert.deepEqual(AKTION_LABEL, {
activate: 'Aktivieren (ohne Zahlung)',
@@ -312,6 +365,17 @@ test('siteKeyOf: nur der Terminplaner zeigt seinen Site-Key, nur wenn das Portal
}
})
test('siteKeyOf liefert für zeiten den Schlüssel, für news weiter ""', () => {
assert.equal(siteKeyOf({ state: 'setup', siteKey: 'abcdefghijklmnop' }, 'zeiten'), 'abcdefghijklmnop')
assert.equal(siteKeyOf({ state: 'setup', siteKey: ' abcdefghijklmnop ' }, 'zeiten'), 'abcdefghijklmnop', 'getrimmt')
assert.equal(siteKeyOf({ state: 'active', siteKey: 'abcdefghijklmnop' }, 'news'), '')
assert.equal(siteKeyOf({ state: 'active', siteKey: 'abcdefghijklmnop' }, undefined), '')
assert.equal(siteKeyOf({ state: 'active', siteKey: 'abcdefghijklmnop' }, 'unbekannt'), '')
for (const feature of [{ state: 'off' }, { state: 'setup', siteKey: null }, { state: 'setup', siteKey: '' }, { state: 'setup', siteKey: 5 }, null, undefined]) {
assert.equal(siteKeyOf(feature, 'zeiten'), '', JSON.stringify(feature))
}
})
test('abgeschaltetText: Grund und Löschdatum im Zustand "disabled"', () => {
const text = (disabledReason, loeschungAm) => abgeschaltetText({ state: 'disabled', disabledReason, loeschungAm })
assert.equal(text('abo_ende', '2026-11-04'), 'Abgeschaltet (Abo beendet), Löschung am 04.11.2026')