Öffnungszeiten: Fixrunde Server (Schema-Kopplung, K27, Wertersatz, Widerruf, Ticket nachlegen)

- activate() schreibt die Zeiten-Felder (aboEndeAt, behaltenSessionId) nur noch über extra
  (nur Abo-Rückkehr und Team-Aktivierung der Zeiten); News und Terminplaner laufen auch vor zeiten-setup.mjs
- Abo-Abgleich: K27 gilt als offen, solange der Marker vor disabledAt liegt (kein Zurücksetzen nach disable() nötig);
  K27 geht erst nach dem Ersatz-Ticket raus (scheitert es, wiederholt der nächste Lauf beides);
  Löschung setzt auch activatedAt zurück
- Zustimmung "beginn" (bezahlt) mit Wertersatz-Satz (§ 357a Abs. 2 BGB) wie bei News und Terminplaner, Fassung 2026-10-05
- Widerruf: Bestellung "zeiten" in ORDERS, FEATURE_OF_ORDER, orderLabel und widerrufen.html
- Team "Ticket nachlegen" der Zeiten ohne Kauf geht über holeZeitenNach statt über den Zahlungsweg
- Einschalten-Route nimmt nur { zustimmung }, nicht die Altform { consent: true }
- Team-Aktivierung behält kauf/unlockedByPurchase bei einem bisher gekauften Dokument

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-05 09:04:05 +00:00
1 parent c10e50d0b3
commit ecf67d6978
13 files changed
+337 -48

No files matched your search

+8 -4
View File
@@ -48,7 +48,7 @@ function notizDesTeams(staff, bisherige, now) {
* @param {{ customerId: string, projectId: string, by?: 'kunde'|'team', staff?: { name?: string, adminNote?: string }|null,
* nachweis?: (() => Promise<unknown>)|null, now?: Date }} p
* by 'kunde': Abo frisch pruefen (kein_abo/gekuendigt/nicht_aktiv 409, Lesefehler 503), unlockedBy 'abo', K24 geht an den Kunden.
* by 'team': keine Abo-Pruefung, unlockedBy 'team', keine K24; staff ergibt die Notiz am Dokument.
* by 'team': keine Abo-Pruefung, unlockedBy 'team' (ein bisher gekauftes Dokument bleibt kauf), keine K24; staff ergibt die Notiz am Dokument.
* nachweis: speichert den Zustimmungsnachweis (Schritt 3, nur wenn wirklich eingeschaltet wird); wirft er, bleibt der Zustand unveraendert.
* @returns {Promise<{ doc: object, changed: boolean }>} doc: das Dokument nach dem Nachholen; changed: false bei idempotentem Aufruf
* @throws {Error} 409 (Abo, anderer Zustand), 503 (Abo nicht lesbar; oder Zustand gespeichert, aber Neubau/Ticket nicht fertig: erneut aufrufen)
@@ -77,12 +77,16 @@ export async function einschaltenZeiten({ customerId, projectId, by = 'kunde', s
// einbau beginnt leer, der Neubau (holeZeitenNach) setzt es neu.
const vorhanden = bisher ?? (await ensureFeatureDoc(customerId, projectId, KEY))
const notiz = by === 'team' ? notizDesTeams(staff, vorhanden.adminNote, now) : null
// Ein gekauftes Dokument (bisher kauf), das das Team wieder einschaltet, bleibt gekauft: unlockedBy/unlockedByPurchase ordnen den
// Widerruf zu (paidFeatureOrders). Neubau und Ticket kennt dort markPaid, nicht das Nachholen (holeZeitenNach laesst kauf aus): einbau
// bleibt darum stehen, statt auf leer gesetzt zu werden, ohne dass es je neu gefuellt wuerde.
const gekauft = by === 'team' && unlockedByVon(bisher) === 'kauf'
const gespeichert = await updateDocument(config.collections.portalFeatures, vorhanden.$id, {
...stateFields('setup'),
featureKey: KEY,
unlockedBy: by === 'kunde' ? 'abo' : 'team',
unlockedByPurchase: false,
einbau: '',
unlockedBy: gekauft ? 'kauf' : by === 'kunde' ? 'abo' : 'team',
unlockedByPurchase: gekauft,
...(gekauft ? {} : { einbau: '' }),
aboEndeAt: null,
behaltenSessionId: '',
disabledAt: null,