# Journal 2026-11-04

## Mini-3D-Modelle auf der Übersichtskarte

Auf `/api-data` sollten die Standortpunkte das jeweilige Container-Modell zeigen. Die erste Fassung schnitt das GLB als winzigen Block in einem Kreis. Jetzt steht dasselbe Design wie auf `/container/3` (Gebäude, Folie, Wasser) als kleines, stehendes Objekt auf der Karte, ohne Messwerte und ohne Drehung. Danach kleiner (128×88), Kamera auf das ganze Objekt samt Schatten eingepasst, weicher Schattenwurf auf den Kartenboden. Jedes Design (GLB plus `kind` aus `ContainerSceneCatalog`) bekommt eine eigene Szene; Folie, Zonenränder und Wasser nur bei `schwimmcontainer`, andere Designs zeigen ihr GLB pur. Dritte Runde (Modell zu klein, schwebte über dem Punkt): orthografische Kamera, die die Ecken des Modells exakt ins Bild einpasst, Fuß fest auf Bildzeile 66 = `iconAnchor`, Statuspunkt am Fuß, weißer Rand per `drop-shadow`, Blick mehr von der Längsseite, Beschriftung rechts neben dem Modell. Danach auf Wunsch größer: 160×110, Fuß auf Zeile 82. Dateien: `src/Controller/ApiController.php`, `public/js/swimmonitor.js`, `public/js/pages/api-map-models.js`, `public/css/swimmonitor.css`, `templates/api/show.html.twig`, `templates/swimmonitor/base.html.twig`, `docs/SWIMMONITOR-STYLE.md`, `config/swimmonitor/changelog.yaml`. Kein Deploy.

## Fehlerfinder: Buchungskonflikte und gespeichertes HTML

Drei schwere Fehler mit konkretem Auslöser in den vorgegebenen Dateien gefunden und klein korrigiert:

- Event-Center: Zwei Kunden wählen denselben freien Termin; nach Abschluss der ersten Buchung konnte das noch offene zweite Formular denselben Termin erneut speichern. Vor dem Speichern werden lokale Buchungen, Sperrzeiten und gegebenenfalls Outlook erneut geprüft (HTTP 409 bei Konflikt). Das erste Stundenfenster behält dabei beide Viertelstundenstarts 09:30/09:45 beziehungsweise 13:30/13:45.
- Paketverwaltung: Öffentlich eingegebene Kinder-/Elternnamen mit HTML und Ereignisbehandlung wurden in den Paket- und Dauer-Buchungsdialogen per innerHTML ausgeführt. Die Textzellen werden jetzt über textContent maskiert.
- Öffentliche Umbuchung: Ein vorhandener Buchungstoken erlaubte den Wechsel in einen vollen limited_course/holiday_course, weil dort die Kapazitätsprüfung fehlte. Der Zweig zählt jetzt belegte Plätze einschließlich verified und aktiver Wartelistenreservierungen, ohne die aktuelle Buchung doppelt zu zählen.

Dateien: src/Controller/EventCenterBookingController.php, src/Controller/AppointmentController.php, templates/admin/event_center/packages/index.html.twig, tests/Controller/EventCenterBookingTest.php, tests/Controller/AppointmentRescheduleTest.php, docs/TODO.md und dieses Journal.

Prüfung: python3 agents/helfer tests test_projekt erfolgreich (17 Tests, 62 Assertions). Vier neue Event-Center-Tests und zwei Umbuchungstests. Keine Browserabnahme der HTML-Maskierung. Die erneuten Belegungsprüfungen sind keine atomare Reservierung gegen exakt zeitgleich laufende Requests. Kein Git, Deploy oder Gerätezugriff; die fünf ausgeschlossenen Befunde nicht erneut untersucht.
