Terminplaner TP2: Entwurf schreiben, PATCH mit fehlt, nie oeffentlich

PATCH /api/termine/einstellungen schreibt den Entwurf nach eigenen Regeln
(withTermine({ schreiben, entwurf }) in routes/termine.js): off und active
ja, ordered und setup nur in der Kundenansicht (sonst 409 gesperrt), disabled
409 abgeschaltet wie bisher. In off zusaetzlich laeuft(customerId): ohne
Wartungs-Abo 409 kein_abo (Text aus aboMeldung), bei Lesefehler 503
abo_pruefung; eine Kuendigung oder offene Zahlung sperrt nur die Bestellung,
nicht das Speichern des Entwurfs. Das Funktionsdokument legt erst der Handler
an (ensureFeatureDoc), nach der Eingabepruefung. PATCH normalisiert mit
entwurf: state !== 'active' und antwortet mit fehlt. Tests: Zustandsmatrix,
Mandanten, Pflichtangaben, Abo, und die Gegenprobe an der oeffentlichen
Schnittstelle (Entwurf und Einbauwuensche nie oeffentlich).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 19:48:57 +00:00
1 parent 42a3befc5f
commit 1cd74226cb
3 files changed
+495 -29

No files matched your search

+5 -5
View File
@@ -246,7 +246,7 @@ test('ohne Pilot (Kunde nicht in der Liste, Modus off) 409 "noch nicht verfuegba
assert.equal((await send('GET', einstellungenUrl(), { cookie })).status, 409)
})
test('Funktion aus, noch nicht bestellt oder ohne Dokument: Einstellungen lesen geht (Entwurf), alles andere bleibt 409 "nicht aktiv"', async () => {
test('Funktion aus, noch nicht bestellt oder ohne Dokument: Einstellungen lesen geht (Entwurf), Vorlage, Feed-Link, Buchungen und Zeiten bleiben 409 "nicht aktiv"', async () => {
// Lesen der Einstellungen: in jedem Zustand und auch ohne Dokument (Zustandsmatrix: test/termineFragebogenRoutes.test.js)
for (const projectId of ['p2', 'p5']) {
const lesen = await send('GET', einstellungenUrl(projectId), { cookie })
@@ -254,13 +254,12 @@ test('Funktion aus, noch nicht bestellt oder ohne Dokument: Einstellungen lesen
assert.equal(lesen.body.state, 'off', projectId)
assert.equal(lesen.body.einstellung, null, projectId)
assert.equal(lesen.body.version, 0, projectId)
// alles andere, auch das Schreiben der Einstellungen (Schreibregeln des Entwurfs folgen in C4b)
// alles andere (PATCH der Einstellungen im Entwurf: Schreibregeln in test/termineFragebogenRoutes.test.js, Teil 1b)
for (const [method, pfad, body] of [
['GET', `/api/termine/buchungen?projectId=${projectId}&von=2026-10-01&bis=2026-10-31`],
['GET', `/api/termine/zeiten?projectId=${projectId}`],
['GET', `/api/termine/export.csv?projectId=${projectId}`],
['POST', '/api/termine/einstellungen/vorlage', { projectId, vorlage: 'salon' }],
['PATCH', '/api/termine/einstellungen', { projectId, version: 0, einstellung: {} }],
['POST', `/api/termine/ressourcen/${R1}/feed`, { projectId }],
['POST', '/api/termine/buchungen', { projectId, art: 'sperre' }],
]) {
@@ -415,7 +414,7 @@ test('R55: Betrieb nur mit Anfrage-Leistungen (Privatpersonen) braucht die Ansch
const komplett = { ...nurTelefon, betrieb: { ...nurTelefon.betrieb, adresse: 'Weg 1, 12345 Ort' } }
const ok = await send('PATCH', '/api/termine/einstellungen', { cookie: c2, body: { projectId: 'p6', version: 1, einstellung: komplett } })
assert.equal(ok.status, 200, JSON.stringify(ok.body))
assert.deepEqual(ok.body.fehlt ?? [], [])
assert.deepEqual(ok.body.fehlt, [])
const config = await oeffentlich(SCHLUESSEL)
assert.equal(config.aktiv, true)
assert.equal(config.widerruf, true)
@@ -460,7 +459,8 @@ test('PATCH einstellungen: speichert, Version zaehlt hoch, Feed-Token bleiben (a
neu.ressourcen.push({ name: 'Clara', typ: 'person', plan: { 2: [['09:00', '12:00']] } })
const res = await send('PATCH', '/api/termine/einstellungen', { cookie, body: { projectId: P, version: vorher.version, einstellung: neu } })
assert.equal(res.status, 200, JSON.stringify(res.body))
assert.deepEqual(Object.keys(res.body).sort(), ['einstellung', 'version'])
assert.deepEqual(Object.keys(res.body).sort(), ['einstellung', 'fehlt', 'version'])
assert.deepEqual(res.body.fehlt, [])
assert.equal(res.body.version, 2)
assert.equal(res.body.einstellung.betrieb.name, 'Salon Neu')
assert.ok(res.body.einstellung.ressourcen.every((r) => !('feedToken' in r)))