Buchungsstrecke: Buchungsdialog, Stripe Checkout, Kapazität und Reservierungen #5

Closed
opened 2026-10-16 05:54:39 +00:00 by Nick.Rosenloecher · 0 comments
Owner

Ziel

Direkte Buchungsstrecke ohne Warenkorb: Daten erfassen, Gutschein prüfen, Zahlungsweise wählen, Erklärungen einholen, Platz serverseitig reservieren und über Stripe Checkout bezahlen. Keine Überbuchung, auch bei parallelen Checkouts.

Umgesetzt

  • Buchungsdialog lazy geladen mit Fokusführung und Escape (src/components/booking/BookingDialog.tsx), mobile Buchungsleiste
  • /api/booking/checkout legt Buchung, Preis-Snapshot (per DB-Trigger unveränderlich), Ratenplan und Reservierung in einer Transaktion an und startet eine Stripe-Checkout-Session (src/lib/booking-service.ts, src/lib/checkout.ts)
  • Preisbindung: Session läuft 30 Minuten (expires_at = priceLockedUntil), Platz bleibt 10 Minuten länger reserviert (ADR-2)
  • Kapazität: Sperre der Camp-Zeile SELECT … FOR UPDATE, dann der Gutscheinzeile; Test- und Livebuchungen getrennt gezählt; keine öffentliche Platzzahl (ADR-4)
  • Idempotenz bei Doppelklick, Same-Origin- und JSON-Pflicht für schreibende Endpunkte, Rate Limits
  • Preis erst unter der gewählten Zahlungsweise anzeigen (7a3e37f, 06.10.2026)
  • Erklärung „Ich bin volljährig“ und Zustimmung zum Rateneinzug mit Zeitstempel

Offene Entscheidungen

Teilnahme Minderjähriger: Die Buchung verlangt derzeit Volljährigkeit; Bestätigung oder andere Regel durch den Inhaber steht aus (gesammelt in #32).

Grundlage

docs/ARCHITEKTUR.md (ADR-1, ADR-2, ADR-4), docs/TESTS.md (8 parallele Buchungen auf 2 Plätze). Webhooks: #6, Freigabe: #10.

Status

Code: ja · Geprüft: ja (Integrationstests gegen PostgreSQL, Stripe-Attrappe) · Gemergt: ja · Produktiv: ja (im Cluster belegt ausgerollt sha-5a88f3d am 13.10.2026); Live-Verkauf gesperrt, siehe #22
Stand: 2026-10-16 (Quelle: git origin/main 9785eb2, Gitea-CI-Läufe und Registry, Memory der Sessions)

## Ziel Direkte Buchungsstrecke ohne Warenkorb: Daten erfassen, Gutschein prüfen, Zahlungsweise wählen, Erklärungen einholen, Platz serverseitig reservieren und über Stripe Checkout bezahlen. Keine Überbuchung, auch bei parallelen Checkouts. ## Umgesetzt - [x] Buchungsdialog lazy geladen mit Fokusführung und Escape (`src/components/booking/BookingDialog.tsx`), mobile Buchungsleiste - [x] `/api/booking/checkout` legt Buchung, Preis-Snapshot (per DB-Trigger unveränderlich), Ratenplan und Reservierung in einer Transaktion an und startet eine Stripe-Checkout-Session (`src/lib/booking-service.ts`, `src/lib/checkout.ts`) - [x] Preisbindung: Session läuft 30 Minuten (`expires_at` = `priceLockedUntil`), Platz bleibt 10 Minuten länger reserviert (ADR-2) - [x] Kapazität: Sperre der Camp-Zeile `SELECT … FOR UPDATE`, dann der Gutscheinzeile; Test- und Livebuchungen getrennt gezählt; keine öffentliche Platzzahl (ADR-4) - [x] Idempotenz bei Doppelklick, Same-Origin- und JSON-Pflicht für schreibende Endpunkte, Rate Limits - [x] Preis erst unter der gewählten Zahlungsweise anzeigen (`7a3e37f`, 06.10.2026) - [x] Erklärung „Ich bin volljährig“ und Zustimmung zum Rateneinzug mit Zeitstempel ## Offene Entscheidungen Teilnahme Minderjähriger: Die Buchung verlangt derzeit Volljährigkeit; Bestätigung oder andere Regel durch den Inhaber steht aus (gesammelt in #32). ## Grundlage `docs/ARCHITEKTUR.md` (ADR-1, ADR-2, ADR-4), `docs/TESTS.md` (8 parallele Buchungen auf 2 Plätze). Webhooks: #6, Freigabe: #10. ## Status Code: ja · Geprüft: ja (Integrationstests gegen PostgreSQL, Stripe-Attrappe) · Gemergt: ja · Produktiv: ja (im Cluster belegt ausgerollt sha-5a88f3d am 13.10.2026); Live-Verkauf gesperrt, siehe #22 Stand: 2026-10-16 (Quelle: git origin/main 9785eb2, Gitea-CI-Läufe und Registry, Memory der Sessions)
Nick.Rosenloecher added the status/erledigtart/featureprio/hoch labels 2026-10-16 05:54:39 +00:00
Sign in to join this conversation.