Öffnungszeiten: nach Abo-Ende für 30 € behalten
Neuer Modus neben Bestellen und Einschalten (Spec 3.3): POST /api/funktionen/zeiten/behalten startet einen Checkout mit zweck 'behalten', ohne den Zustand zu ändern; der Webhook-Zweig bucht vor markPaid/adoptPaidSession unter feature-admin zum Kauf (Frist weg, stripeSessionId = Sitzung), schaltet eine abgeschaltete Funktion wieder ein (Neubau nach der Sperre), ohne neues Ticket, mit K15 im Behalten-Wortlaut. Passt die Sitzung nicht, geht T19 nach der Sperre raus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
97e6971276
commit
53253f0451
6 files changed
+1116
-12
No files matched your search
@@ -20,6 +20,7 @@ import { actingPerson, speichereNachweisAusAnfrage, zustimmungFuerSitzung } from
|
||||
import { termineFuerKunde } from '../services/termine/schalter.js'
|
||||
import { zeitenFuerKunde } from '../services/zeiten/schalter.js'
|
||||
import { einschaltenDeps, einschaltenZeiten, zeitenProjektAnsicht } from '../services/zeiten/einschalten.js'
|
||||
import { starteBehalten } from '../services/zeiten/behalten.js'
|
||||
import { aboMemo } from '../services/aboStatus.js'
|
||||
import { featureConfig, featureHaken, featureKeys, featureSperre, freiweg, oeffentlicheAnsicht } from '../services/featureRegistry.js'
|
||||
import { bestellFehler, istFortsetzen, oeffentlicheConsent, pruefeAbo, pruefeInklusive, pruefeZustimmung } from '../services/featureOrder.js'
|
||||
@@ -374,6 +375,48 @@ router.post('/zeiten/einschalten', requireSession, async (req, res) => {
|
||||
}
|
||||
})
|
||||
|
||||
const BEHALTEN_ERROR = 'Das Behalten konnte gerade nicht gestartet werden. Bitte versuch es später noch einmal oder schreib uns im Chat.'
|
||||
|
||||
// Behalten (Spec 3.3): nach dem Ende des Wartungs-Abos Öffnungszeiten live fuer einmalig 30 € behalten, ohne neuen Einbau. Vorpruefungen wie im
|
||||
// Checkout, jede Stufe ohne Seiteneffekt: 1 Kundenansicht, 2 Zustimmung (die der Bestellung, beide Haken), 3 Projekt (eigen; eine laufende Funktion
|
||||
// zu behalten ist keine Neubestellung, ein archiviertes Projekt bleibt erlaubt), 4 Schalter/Pilot, 5 Unterlagen. Ob behalten werden darf, entscheidet
|
||||
// das Dokument unter der Sperre (starteBehalten: aboEndeAt, sonst 409); den Zustand aendert die Route nicht, erst die bezahlte Sitzung (Webhook).
|
||||
// Die Route steht nicht auf der Erlaubnisliste der Kundenansicht (Mitarbeiter bestellen nicht fuer den Kunden); die Pruefung hier ist die zweite Sicherung.
|
||||
router.post('/zeiten/behalten', requireSession, async (req, res) => {
|
||||
// Zeit des Klicks: Eingang der Anfrage, Anker des Nachweises und der Metadaten (consentAt) und damit der Widerrufsfrist
|
||||
const now = new Date()
|
||||
try {
|
||||
// 1 Kundenansicht
|
||||
if (req.session.viewAs) return res.status(403).json({ error: 'In der Kundenansicht kann nicht bestellt werden.' })
|
||||
const feature = featureConfig('zeiten')
|
||||
const body = req.body || {}
|
||||
// 2 Zustimmung: alle Pflicht-Haken der Bestellung und die aktuelle Fassung
|
||||
pruefeZustimmung(feature, body)
|
||||
// 3 Projekt
|
||||
const { projectId } = body
|
||||
if (typeof projectId !== 'string' || !projectId) return res.status(400).json({ error: 'Bitte wähle ein Projekt.' })
|
||||
const customerId = getSessionCustomerId(req)
|
||||
await assertOwnProject(customerId, projectId)
|
||||
// 4 Schalter (ZEITEN_ENABLED und Pilotliste)
|
||||
const sperre = featureSperre('zeiten', req.session.email)
|
||||
if (sperre) throw bestellFehler(409, sperre, 'nicht_verfuegbar')
|
||||
// 5 Vertragsunterlagen abrufbar
|
||||
const haken = featureHaken('zeiten')
|
||||
await pruefeUnterlagen(haken)
|
||||
|
||||
const customer = await getDocument(config.collections.customers, customerId)
|
||||
const { url } = await starteBehalten({
|
||||
customer,
|
||||
projectId,
|
||||
now,
|
||||
nachweis: (sessionId) => speichereNachweisAusAnfrage(req, { feature, haken, customerId, projectId, sessionId, klickAt: now.toISOString() }),
|
||||
})
|
||||
res.json({ url })
|
||||
} catch (err) {
|
||||
fail(res, err, BEHALTEN_ERROR)
|
||||
}
|
||||
})
|
||||
|
||||
const analyseGuard = [requireSession, requireAnalyseEnabled]
|
||||
|
||||
router.post('/analyse/activate', analyseGuard, async (req, res) => {
|
||||
|
||||
Reference in new issue
Block a user