Terminplaner TP2: Branche und Vorlage im Entwurf, PUT /fragebogen

POST /api/termine/einstellungen/vorlage nimmt jetzt eine Branche (BRANCHEN), optionale
Betriebsfelder (nichtleere Werte ueberschreiben das Konto) und schreibt den Fragebogen mit
der Einstellung in einem Vorgang. Der Gesundheitsbereich ist ausgeschlossen (400
gesundheitsbereich, nichts wird angelegt). Eine bestehende Einstellung ersetzt nur
ersetzen:true mit passender version im Zustand off (neue IDs und Kalender-Token, Fragebogen
neu, Einbauwuensche bleiben). Die Route arbeitet im Entwurf (off, active, ordered/setup nur
in der Kundenansicht, disabled nie).

PUT /api/termine/fragebogen speichert nur den Fragebogen (Version der Einstellung bleibt),
ist in der Kundenansicht gesperrt (Waechter und Router), zaehlt gegen das Schreibbudget und
antwortet mit { fragebogen, offen }.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 20:12:00 +00:00
1 parent 1cd74226cb
commit 29a38a9592
4 files changed
+837 -35

No files matched your search

+14 -7
View File
@@ -146,22 +146,29 @@ test('Erlaubnisliste: genau News, Terminplaner, Analyse-Link, Ende, Logout und L
})
// Spec 2026-10-03, Abschnitt 3: unbekannte Schreib-Pfade unter /api/termine sind in der Kundenansicht gesperrt, bevor der Router
// sie sieht (auch Pfade ohne Route und Gross-/Kleinschreibung); normale Kunden beruehrt der Waechter nicht
// sie sieht (auch Pfade ohne Route und Gross-/Kleinschreibung); normale Kunden beruehrt der Waechter nicht.
// PUT /fragebogen hat seit C5 eine echte Route: in der Kundenansicht sperrt sie der Waechter (403 view_blocked, der Router kommt nie
// dran), ein normaler Kunde mit eigenem Projekt bekommt die Antwort der Route (hier 409 "noch nicht verfuegbar": der Pilot-Schalter
// steht im Test auf off; weder 403 noch 404). Der 403 am Router selbst (ohne Waechter) steht in test/termineFragebogenRoutes.test.js.
test('unbekanntes POST/PUT unter /api/termine in der Kundenansicht -> 403 view_blocked, normale Kunden nicht', async () => {
const faelle = [
['POST', '/api/termine/zukunft'],
['PUT', '/api/termine/fragebogen'],
['PUT', '/api/termine/fragebogen', { projectId: 'p1', fragebogen: {} }],
['POST', '/api/termine/buchungen/abc/aktion/x'],
['POST', '/API/Termine/Zukunft'],
]
for (const [method, p] of faelle) {
const gesperrt = await call(method, p, { ...kv(), body: {} })
for (const [method, p, body = {}] of faelle) {
const gesperrt = await call(method, p, { ...kv(), body })
assert.equal(gesperrt.status, 403, `${method} ${p}`)
assert.equal(gesperrt.body.code, 'view_blocked', `${method} ${p}`)
const kunde = await call(method, p, { cookie: customerCookie('c1'), body: {} })
const kunde = await call(method, p, { cookie: customerCookie('c1'), body })
assert.notEqual(kunde.status, 403, `${method} ${p}: normaler Kunde`)
// PUT /fragebogen bekommt in Block C eine echte Route (dann antwortet sie selbst); die anderen Pfade gibt es nie
if (!p.endsWith('/fragebogen')) assert.equal(kunde.status, 404, `${method} ${p}: der Router kennt den Pfad nicht`)
if (p.endsWith('/fragebogen')) {
assert.equal(kunde.status, 409, `${method} ${p}: die Route antwortet selbst`)
assert.equal(kunde.body.code, 'nicht_verfuegbar', `${method} ${p}`)
} else {
assert.equal(kunde.status, 404, `${method} ${p}: der Router kennt den Pfad nicht`)
}
}
})