Terminplaner TP2: Ansicht nach Zustand und Rueckkehr von Stripe

Die Ansicht #termine folgt dem Zustand aus GET /api/termine/einstellungen:
off mit laufendem Abo zeigt den Fragebogen samt Bestellseite, ohne Abo den
Hinweis des Servers (termine.hinweis, R111) und bei kein_abo den Link zu
Vertraege aus einer gemeinsamen Quelle (vertraege-link.js); ordered und setup
zeigen die Statuskarte und die Reiter Leistungen, Team & Plaetze und
Einstellungen nur zum Lesen (ohne Reiter Termine); active und disabled
bleiben wie bisher. Rueckkehr von Stripe: #termine?bestellt=1&projekt=<id>
und #termine?projekt=<id> waehlen das Projekt, "Danke!" nur mit bestellt=1,
die Adresse wird einmal gelesen und bereinigt.

R110: GET /einstellungen liefert bestellung und offen auch in ordered (ohne
Abo-Punkt, abo bleibt null); scheitert "Zahlung fortsetzen", zeichnet die
Huelle Liste und Daten neu (bei 409 zustimmung_fehlt mit dem
Bestellformular, sonst nach dem neuen Zustand, die Meldung bleibt am Knopf,
solange die Bestellung offen ist).

Dazu: "null" als Text im lesbaren Reiter Leistungen entfernt, Export und
Status der Einstellungen erst ab der Freischaltung.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 23:10:54 +00:00
1 parent 52456dac76
commit 87d267e51a
13 files changed
+1077 -71

No files matched your search

+51 -5
View File
@@ -322,8 +322,8 @@ test('einbau.snippet und feeds nur in active (feeds) und active/disabled (snippe
}
})
test('abo, offen und bestellung gibt es nur in off; sonst null', async () => {
for (const zustand of ['ordered', 'setup', 'active', 'disabled']) {
test('abo gibt es nur in off; offen und bestellung nur in off und ordered (R110); in setup, active und disabled null', async () => {
for (const zustand of ['setup', 'active', 'disabled']) {
await deleteDocument('portalFeatures', FEATURE).catch(() => {})
await deleteDocument('termineConfig', FEATURE).catch(() => {})
setzeZustand(zustand)
@@ -332,11 +332,57 @@ test('abo, offen und bestellung gibt es nur in off; sonst null', async () => {
assert.equal(body.offen, null, zustand)
assert.equal(body.bestellung, null, zustand)
}
setzeZustand('off')
for (const zustand of ['off', 'ordered']) {
await deleteDocument('portalFeatures', FEATURE).catch(() => {})
await deleteDocument('termineConfig', FEATURE).catch(() => {})
setzeZustand(zustand)
const { body } = await send('GET', einstellungenUrl(), { cookie })
assert.notEqual(body.offen, null, zustand)
assert.notEqual(body.bestellung, null, zustand)
assert.equal(body.abo === null, zustand === 'ordered', `${zustand}: das Abo liest die Route nur in off`)
}
})
// ---------------------------------------------------------------- ordered: bestellung und offen nur lesend (R110)
// "Zahlung fortsetzen" ohne Nachweis (409 zustimmung_fehlt) zeigt im Zustand ordered wieder das Bestellformular; dafuer braucht der
// Client bestellung und offen auch dort. Das Abo gehoert nicht dazu: es wird in ordered nicht gelesen, offen hat keinen Abo-Punkt (h).
test('ordered: bestellung ist die Sicht des Registers wie in off, offen die Bestellprüfung ohne Abo-Punkt, abo null, nichts wird geschrieben', async () => {
const stand = setzeZustand('ordered')
aw.resetListCalls()
const vorher = groessen()
const { status, body } = await send('GET', einstellungenUrl(), { cookie })
assert.equal(status, 200)
assert.equal(body.state, 'ordered')
assert.deepEqual(body.bestellung, JSON.parse(JSON.stringify(await bestellungAnsicht(T))))
assert.equal(body.bestellung.consent.knopf, T.consent.knopf)
assert.deepEqual(body.offen, [], 'bestellbarer Entwurf: keine offenen Punkte, auch ohne Abo-Punkt')
assert.deepEqual(body.offen, bestellpruefung({ einstellung: stand.einstellung, fragebogen: stand.fragebogen, feature: T, mitAbo: false }))
assert.equal(body.abo, null)
assert.deepEqual(aw.listCalls('subscriptions'), [], 'in ordered wird das Abo nicht gelesen')
assert.deepEqual(groessen(), vorher, 'read-only: nichts angelegt, nichts protokolliert')
})
test('ordered: ein unvollständiger Entwurf zeigt seine offenen Punkte (nie den Abo-Punkt), ohne Einstellung den Punkt „Branche“', async () => {
setzeZustand('ordered', { stand: { ...bestellbarerStand({ now: JETZT }), fragebogen: leerFragebogen() } })
const { body } = await send('GET', einstellungenUrl(), { cookie })
assert.notEqual(body.abo, null)
assert.notEqual(body.offen, null)
assert.ok(body.offen.length > 0)
assert.ok(body.offen.some((p) => p.schritt === 'leistungen'))
assert.ok(body.offen.every((p) => p.schritt !== 'bestellen'), 'kein Abo-Punkt (h)')
await deleteDocument('termineConfig', FEATURE)
const ohne = await send('GET', einstellungenUrl(), { cookie })
assert.equal(ohne.status, 200)
assert.deepEqual(ohne.body.offen, [{ schritt: 'branche', text: 'Bitte starte den Fragebogen mit der Wahl deiner Branche.' }])
assert.notEqual(ohne.body.bestellung, null)
})
test('ordered in der Kundenansicht: bestellung und offen ebenfalls da, kundenansicht true', async () => {
setzeZustand('ordered')
const { status, body } = await send('GET', einstellungenUrl(), kv())
assert.equal(status, 200)
assert.equal(body.kundenansicht, true)
assert.notEqual(body.bestellung, null)
assert.deepEqual(body.offen, [])
})
test('E11 bleibt: disabled liefert das Feld abgeschaltet mit Grund, Zeitpunkt und Löschtag; Schreiben ist weiter 409 "abgeschaltet"', async () => {