trihub-ernaehrung-backseatDevs/docs/booking.md

8.5 KiB

Paketbuchung

Ablauf

Die Angebotsübersicht führt zur Detailseite eines Pakets. Der Buchungsbutton übergibt die Paket-ID und gegebenenfalls die gewählte Variante als URL-Parameter an booking.html. Bestehende Links mit #/buchen/:packageId funktionieren weiterhin.

Booking lädt die Bestellübersicht vom Server. Sie enthält Paket und Variante, Laufzeit, Leistungen, Abrechnung, Nettopreis, MwSt. und Gesamtbetrag. Die Preise stammen aus src/shared/packagesdetails.js; Preisangaben des Browsers werden nicht übernommen. Ohne Varianten-ID wird die erste Variante des Pakets gewählt.

Beim Absenden speichert der Server Kundendaten und den vollständigen Bestellstand in der CSV. Anschließend sendet er eine Bestätigung als Text und HTML mit Buchungsnummer, Datum, gebuchten Leistungen und Preisen. Änderungen am Katalog verändern bereits gespeicherte Bestellungen nicht.

Der Zahlungsvorgang ist weiterhin simuliert. Es erfolgt keine Abbuchung und keine verbindliche Beratungsbuchung. Darauf weisen Formular und E-Mail hin.

Lokal starten

Voraussetzung ist Node.js 24. Abhängigkeiten mit npm ci installieren und die Werte aus .env.example in eine lokale .env übernehmen. Eine vorhandene Konfiguration dabei erhalten.

In separaten Terminals starten:

  • npm run dev:mail: Mailpit mit SMTP auf Port 1025 und Weboberfläche auf 8025.
  • npm run dev:server: Buchungs-API auf Port 3000.
  • npm run dev: Frontend auf Port 5173; /api wird an Node weitergeleitet.

Die Angebotsübersicht liegt unter http://localhost:5173/angebotsuebersicht.html, der Mailfänger unter http://localhost:8025. Mailpit ist im Dev Container enthalten.

npm run build erzeugt die Seiten in dist/, einschließlich der Paketdetailseite. Für ein Deployment muss der Webserver /api an den Node-Server weiterleiten. npm run start:server startet die API ohne automatischen Neustart.

Konfiguration

Variable Standardwert Bedeutung
HOST 127.0.0.1 Bind-Adresse der API
PORT 3000 API-Port; bei Änderung auch den Vite-Proxy anpassen
SMTP_HOST 127.0.0.1 SMTP-Server
SMTP_PORT 1025 lokal, sonst 587 SMTP-Port
SMTP_SECURE false Direktes TLS aktivieren
SMTP_USER, SMTP_PASS leer SMTP-Zugangsdaten; beide gemeinsam setzen
SMTP_FROM Tri-Hub <buchung@example.test> Absender
SMTP_ALLOW_EXTERNAL false Versand über externe SMTP-Server aktivieren

Externe SMTP-Verbindungen erfordern TLS. Zugangsdaten gehören ausschließlich in die Serverkonfiguration und dürfen kein VITE_-Präfix erhalten.

API

Der vollständige Vertrag steht in src/server/swagger.json.

Endpunkt Funktion
GET /api/angebote Bestehende Kurzübersicht mit id, name und summary
GET /api/packages Kurzübersicht im Swagger-Format
GET /api/packages/{id} Paketdetails einschließlich Varianten und Leistungen
POST /api/bookings/preview Bestellübersicht für packageId und optionale variantId; speichert keine Buchung
POST /api/bookings Buchung speichern und Bestätigung versenden

POST-Anfragen benötigen Content-Type: application/json. Beim Buchen ist zusätzlich ein Idempotency-Key als UUID v4 erforderlich. Das Formular sendet packageId, gegebenenfalls variantId, name und email.

Alternativ akzeptiert die API das Swagger-Objekt customer mit firstName, lastName, email sowie optional phone, ageGroup und notes. Dabei muss acceptedTerms den Wert true haben. Diese Angaben werden ebenfalls gespeichert.

Die Antwort enthält die Buchungsnummer, den Erstellungszeitpunkt, das gebuchte Paket unter bookedPackage und den Versandstatus. Eine neue Buchung mit SMTP-Annahme erhält HTTP 201, eine Wiederholung HTTP 200. Bei ausstehendem, fehlgeschlagenem oder unklarem Versand wird HTTP 202 zurückgegeben.

Ungültige Angaben, Pakete und Varianten ergeben HTTP 400; ein unbekanntes Paket am Detail-Endpunkt HTTP 404. Derselbe Anfrageschlüssel mit anderen Daten ergibt HTTP 409. JSON-Anfragen sind auf 8 KiB begrenzt. Fehlerantworten enthalten error.code, error.message und gegebenenfalls error.fields.

Speicherung und Wiederholungen

Die Buchungen liegen in src/server/data/bookings.csv. Neue Buchungsnummern werden fortlaufend als TH-000001, TH-000002 usw. vergeben. Der höchste vorhandene Wert bestimmt die nächste Nummer. Die CSV muss deshalb vollständig erhalten bleiben; ältere UUID-Buchungsnummern werden weiterhin unterstützt.

bookedPackage speichert den Bestellstand als JSON, customer die optionalen strukturierten Kundendaten und acceptedTerms die zugehörige Zustimmung. CSV-Dateien mit dem früheren Spaltensatz bleiben lesbar und werden beim nächsten Speichern erweitert. Für alte Buchungen ohne Bestellstand liefert die API bookedPackage: null.

Lesen, Schreiben und Versand werden innerhalb einer Warteschlange abgearbeitet. Die Datei wird über eine temporäre Datei atomar ersetzt. Unterstützt wird ein Backend-Prozess auf einem lokalen Dateisystem. Mehrere Serverinstanzen benötigen einen gemeinsam abgesicherten Speicher. CSV-Zellen werden gegen die Auswertung als Tabellenformeln geschützt; Dateien erhalten den Zugriffsmodus 0600.

Wiederholte Anfragen mit demselben Schlüssel und denselben Daten liefern die vorhandene Buchung. Es wird keine zweite Bestellung angelegt. Die Auswahl einer anderen Variante mit demselben Schlüssel wird abgelehnt.

Das Formular merkt sich Anfrage und Bestellübersicht je Paket und Variante im sessionStorage. Nach einem Verbindungsfehler bleiben die Angaben gesperrt, damit dieselbe Anfrage erneut geprüft werden kann. Ein neuer Tab oder gelöschter Sitzungsspeicher liegt außerhalb dieser Absicherung.

Versandstatus

Status Bedeutung
pending Buchung gespeichert; Versand noch nicht gestartet. Dieselbe Anfrage kann den Versand fortsetzen.
sending Versandabsicht gespeichert. Nach einem Prozessabbruch liefert die API unknown.
accepted SMTP hat die Nachricht angenommen; die Zustellung ist noch nicht bestätigt.
failed Versand fehlgeschlagen oder ausdrücklich abgelehnt.
unknown SMTP-Annahme oder anschließende Statusspeicherung blieb unklar.

Bei failed und unknown wird nicht automatisch erneut versendet. Vor einem manuellen Neuversand muss der Mailserver anhand der Buchungsnummer geprüft werden. CSV und SMTP bilden keine gemeinsame Transaktion.

Tests

npm test prüft Validierung, Preisberechnung, Varianten, CSV-Kompatibilität, Wiederholungen und Versandfehler. npm run test:browser prüft den Weg von der Angebotsübersicht über die Paketdetails bis zur Bestätigung, einschließlich Premium-Jahresvariante, Tastaturbedienung und schmalem Bildschirm.

Die Tests verwenden die regulären Paketdaten, temporäre CSV-Dateien und einen simulierten Mailversand. Playwright benötigt Chromium; die Installation erfolgt mit npx playwright install --with-deps chromium. Die Ports 3000 und 5173 müssen für die automatisch gestarteten Testserver frei sein.

Vor einem Commit außerdem npm run format:check, npm run build und git diff --check ausführen. Für eine manuelle Mailprüfung eine Buchung mit einer Adresse unter example.test anlegen und die Bestätigung in Mailpit kontrollieren.