# TODO – Zentrale Aufgabenliste



**Konvention:** Offene Punkte unter „Offen", erledigte nach „Erledigt" verschieben (mit Datum

`(YYYY-MM-DD)`). Zu Beginn einer Aufgabe **lesen**, am Ende **fortschreiben**. Chronologie/Details

siehe `docs/journal/`. Projektwissen für Agenten: `AGENTS.md`.



## Offen

- [ ] (2026-09-08) **Wartelisten-E-Mails: Templates fehlen in der Datenbank.** Für BZ-Kursbuchungen
      existiert kein Template vom Typ `course_booking_waitlist_offer` und keins vom Typ
      `course_booking_waitlist` — beide Mails kommen deshalb aus dem System-Fallback
      (`SystemFallbackEmailCatalog`). Zusätzlich ist „Buchungseingang mit Zahlungsinformationen"
      (`course_booking_payment_info`, ID 45) nur den Ferienspielen und Athletikcamps zugeordnet; bei
      „Eltern-Kind-Turnen" und den übrigen Kursen greift daher der Fallback „Ihre Buchung wurde
      erfasst". Templates unter `/admin/event-center/email-templates/` anlegen bzw. den restlichen
      Kursen zuordnen (Zahlungsinfo wirkt bewusst **nur** mit Kurszuordnung). Nebenbefund: Template
      ID 48 (`course_booking_payment_info`) ist aktiv, hat aber leeren Betreff und keine
      Kurszuordnung — prüfen und löschen.
- [x] (2026-09-10) **Git-Deploy auf dem Server:** `main` ist live (Magallanes). Fisch Phase 5 +
      BZ-Warteliste. Migration `Version20260910150000` war auf der Live-DB schon angewandt.
      Offen bleiben Absenderadresse und Cronjobs (siehe unten).
- [ ] (2026-09-04) **SEO Blocker 1 — Frameset auf der Domain-Wurzel:** `https://dp-smartsolutions.de/`
      liefert ein `<frameset>` mit leerem `<title>`, das `…/ksbdueren/public/dpohl` einbettet. Google
      indexiert dadurch eine leere Startseite, `/robots.txt` und `/sitemap.xml` sind auf der Wurzel 404.
      vHost umstellen (Vorlage: `config/apache/dp-smartsolutions-root.conf.example`, enthält den
      kompletten Ablauf), Frameset-Datei entfernen, danach `APP_URL` in `.env.local` anpassen und
      `cache:clear`. **Achtung:** Microsoft-OAuth-Redirect-URIs und iframes der KSB-Seite enthalten den
      alten Pfad — der Alias in der Vorlage hält beides am Leben.
      Entschieden (2026-09-04): Die Wurzel zeigt weiterhin die Willkommen-/Login-Seite, die Firmenseite
      bleibt `/dpohl`. Die Willkommenseite ist deshalb auf `noindex` gesetzt.
- [ ] (2026-09-04) **Neuen Stand der Firmenseite deployen:** Live liegt unter
      `/ksbdueren/public/dpohl` noch die alte Seite, und `/ksbdueren/public/impressum` zeigt die
      Login-Seite (die `security.yaml`-Freigabe ist noch nicht auf dem Server). Deployen, danach
      `cache:clear` und Impressum/Datenschutz ohne Anmeldung gegenprüfen.

      **Neu hochladen:**
      - `templates/home/base_dpohl.html.twig`
      - `src/Controller/SeoController.php`, `templates/seo/sitemap.xml.twig`
      - `public/css/dpohl-landing.css`, `public/js/dpohl-landing.js`
      - `public/images/firmenlogo-{240,480,960}.{webp,png}` (6 Dateien)
      - `public/vendor/` komplett (Font Awesome + Schriftarten) — **binär** übertragen, sonst sind
        die `.woff2`-Dateien beim Upload kaputt

      **Überschreiben:**
      - `templates/home/index.html.twig`, `impressum.html.twig`, `datenschutz.html.twig`
      - `templates/default/index.html.twig` (noindex)
      - `src/Controller/HomeController.php`
      - `config/packages/security.yaml`

      **Auf dem Server löschbar:** `templates/home/mobile.html.twig`, `impressum_mobile.html.twig`,
      `datenschutz_mobile.html.twig` (werden nicht mehr eingebunden).

      Nicht deployen: `config/apache/*.example` und `docs/` sind reine Doku.
- [ ] (2026-09-04) **DNS: DMARC-Record steht am falschen Ort.** Der Eintrag
      `v=DMARC1; p=quarantine; rua=mailto:support@dp-smartsolutions.de` liegt als TXT auf `@`; DMARC wird
      aber nur unter `_dmarc.dp-smartsolutions.de` ausgewertet. Aktuell greift also keine Richtlinie.
      Neuen TXT-Record mit Name `_dmarc` und diesem Wert anlegen, den falschen auf `@` löschen —
      der SPF-Eintrag `v=spf1 include:netcup.net -all` muss auf `@` bleiben.
- [ ] (2026-09-04) **E-Mail-Zustellung prüfen:** SPF steht auf `-all` und erlaubt nur netcup als
      Absender. Falls die Anwendung (Kontaktformular-Bestätigungen, Buchungsmails) direkt vom Server
      142.132.206.12 versendet statt über netcup-SMTP, scheitert SPF und die Mails landen im Spam.
      `MAILER_DSN` gegenprüfen; falls nötig SPF um den Server ergänzen oder Versand auf netcup umstellen.
- [ ] (2026-09-04) **SEO Blocker 2 — Sitemap einreichen:** nach der vHost-Umstellung
      `https://dp-smartsolutions.de/sitemap.xml` in der Google Search Console anmelden und Domain
      verifizieren (auch Bing Webmaster Tools).
- [x] (2026-09-04) **Externe CDNs ersetzt:** Die Firmenpräsenz lädt nichts mehr von fremden Servern.
      Font Awesome 6.5.2 (solid + brands) liegt unter `public/vendor/fontawesome/`, die Schriften Inter
      und Barlow Condensed unter `public/vendor/fonts/`; Bootstrap kommt aus dem vorhandenen
      `public/css/bootstrap.min.css` bzw. `public/js/bootstrap.bundle.min.js`. Datenschutzerklärung
      Abschnitt 6 entsprechend angepasst.
- [ ] (2026-09-04) **Rechtstexte: Dienstleister namentlich ergänzen.** In `templates/home/datenschutz.html.twig`
      sind Hoster und E-Mail-Versanddienstleister bewusst allgemein beschrieben (Abschnitte 3 und 4,
      Twig-Kommentar im Template). Namen und Sitz eintragen, sobald geklärt — und prüfen, ob für beide
      ein AV-Vertrag nach Art. 28 DSGVO vorliegt. Danach das „Stand“-Datum oben auf der Seite anpassen.
      Empfehlung: Texte vor dem Livegang einmal juristisch prüfen lassen.
- [ ] (2026-09-04) **Firmenseite `/dpohl` — Nachträge:** `templates/home/mobile.html.twig`,
      `impressum_mobile.html.twig` und `datenschutz_mobile.html.twig` werden nicht mehr eingebunden
      (alle drei Seiten sind responsiv) und können gelöscht werden. Offen außerdem:
      Kundenstimme des Kreissportbunds schriftlich freigeben lassen und dann als Zitat einbauen;
      echte Projektbilder/Screenshots statt reiner Icon-Karten.
- [ ] (2026-09-04) **ksb - schwimm:** Einwilligung für die Öffentlichkeitsarbeit von Mobi / Kreissportbund Düren e. V. Ich bin damit einverstanden, dass Foto- und Videoaufnahmen meines Kindes, die im Rahmen des Tags der Maus bei Mobi entstehen, für die Öffentlichkeitsarbeit von Mobi und dem Kreissportbund Düren e. V. verwendet und auf der Mobi-Website sowie den Social-Media-Kanälen (z. B. Instagram und Facebook) veröffentlicht werden dürfen. grundsätzlich optionen im formular bild videoaufnahmen checkbox, einwiliigung für die öff…
- [ ] (2026-09-03) **Geschwisterpreise nachpflegen (blockiert Geschwisterbuchungen!):** `kids_abo`-Kurse
      (Moving/Ninja/Power Kids, Power Minis, Fun4Kids, Bewegungsforscher, PRAMA Teens, Die Entdecker,
      Sportzwerge), Athletikcamps I/II, „Türen auf mit der Maus" und Sommer-Ferienspiele Woche 6 haben
      `allowSiblings = true`, aber `sibling_prices = []` → **im Buchungsformular erscheint keine
      Geschwister-Eingabe mehr**. Preise unter `/admin/bz/courses` (Kurs bearbeiten → Geschwisterpreise)
      eintragen; ein Eintrag pro buchbarem Geschwisterkind, 0,00 € = kostenlos aber buchbar.

- [ ] (2026-09-03) **Altbuchungen mit 0,00 €:** 10 Abo-Buchungen vom 24.08.–01.09. wurden mit 0,00 €
      statt Monatsbeitrag gespeichert (Ursache behoben). Bewusst nicht korrigiert — bei Bedarf im Admin nachziehen.

- [ ] (2026-09-03) **Geschlecht für Geschwisterkinder?** Beim Hauptkind wird `childGender` erfasst,
      bei Geschwisterkindern nicht. Klären, ob das Feld im Buchungsformular ergänzt werden soll.

- [ ] (2026-09-03) **Gesundheitsfelder Hauptkind vs. Geschwisterkind:** Beim Geschwisterkind sind
      Vorerkrankungen/Allergien/Ernährung/Foto-Video jetzt Pflicht, beim Hauptkind nur bei
      Ferienspielen (Ernährung nie). Klären, ob das Hauptkind gleich streng behandelt werden soll.

- [ ] (2026-09-03) **Fehlende Geschwister-Angaben nachfragen:** Buchungen mit leeren
      Gesundheitsfeldern beim Geschwisterkind (u. a. 435 `CRS-575B1B9D0C29`, 488, 503) —
      bei Bedarf bei den Eltern erfragen und im Admin nachtragen.

- [x] (2026-09-10) **Fit wie ein Fisch: Flows live testen.** Code steht, Migration
      `Version20260910150000` ist angewandt, Mailtexte greifen bisher auf die Fallback-Texte zurück
      (noch keine Vorlage in der DB). Getestet mit `MAILER_DSN=null://null php bin/console
      app:fisch:e2e-test`: Anmeldung→Validierung, Warteliste Angebot/Claim, Sammelanmeldung
      Schule→Elternlink. Anmeldephase startet planmäßig am 17.09. — bis dahin im Admin geschlossen.

- [ ] (2026-09-10) **Fit wie ein Fisch: Domain `fit-fisch.de`.** Agenten-Auftrag inkl. Befehlen:
      **`docs/FIT_FISCH_DOMAIN_CUTOVER.md`**. Kurz: DNS A `@`/`www` → `142.132.206.12` (Mensch/Hetzner),
      dann Server: Deploy `main`, `FISCH_PUBLIC_URL=https://fit-fisch.de` in shared-Env, Apache-vHost
      + Certbot, `cache:clear`, Abnahme. Admin bleibt unter `APP_URL`.

- [x] (2026-09-10) **Niklas-Feedback Fit wie ein Fisch umgesetzt:** Landing-Texte (Seepferdchen
      entschärft, 10 Tage, Eltern-Hinweis oben + keine Begleitung ins Bad), Flaggen DE/EN/TR/UK/AR
      (SVG statt Emoji, da Windows sonst nur „DE/GB“ zeigt), Anmeldemaske nicht mehr auf der
      Startseite bei geschlossener Phase (Testbuchungen: Token/Link in
      `/admin/fisch/grundeinstellungen`, optional Env-Fallback), Handynummer-Spalte + Aktionsmenü
      (Umbuchen/Mail erneut/Storno), Warteliste in beliebige Kurse mit Altersausnahme,
      Altersregler-Erklärung, E-Mail-Vorlagen geseedet (`app:fisch:seed-email-templates`).
      Übungsleiter/Anwesenheit bewusst hinten. Migration Test-Token: `Version20260910220000`.

- [ ] (2026-09-10) **Fit wie ein Fisch: Absenderadresse nachtragen.** Bis die Zugangsdaten für das
      eigene Fisch-Postfach vorliegen, versenden alle Fisch-Mails über `ADMIN_EMAIL`. In
      `/admin/fisch/email-templates` steht dazu ein Hinweisbanner. Danach je Vorlage (oder global)
      `fromEmail`/`fromName` setzen und einen Testversand machen.

- [x] (2026-09-10) **Fit wie ein Fisch: Standortinfos befüllen.** Adresse, Anfahrt, Parkplatz,
      Google-Maps-Link und Embed-URL für alle 6 Bäder vorausgefüllt (Rurbad Nippesstraße;
      Lehrschwimmbecken Goethestraße / Birkesdorf / Merken / Derichsweiler / Arnoldsweiler an den
      jeweiligen Grundschulen). Bitte in `/admin/fisch/standorte` einmal gegenprüfen — Parkhinweise
      sind allgemein gehalten.

- [ ] (2026-09-10) **Fit wie ein Fisch: Cronjobs einrichten** —
      `app:fisch:waitlist-expire` und `app:fisch:expire-pending` (siehe `docs/CRONJOBS.md`).

- [ ] (2026-08-26) **Fit wie ein Fisch Phase 5 – Rest:** Übungsleiter, Anwesenheit, Elternbriefe
      (Sammelanmeldung und E-Mail-Vorlagen sind erledigt, siehe unten).

- [ ] (2026-07-16) **E-Mail-Postfach:** Klassifikation nach Deploy prüfen (Kunden vs. Buchungsbestätigungen).

- [ ] (2026-07-16) **Migration ausführen:** `php bin/console doctrine:migrations:migrate` (Version20260716120000 – workshop_group).



- [ ] (2026-07-16) **Root-Dokumentation konsolidieren** — viele `.md`-Dateien liegen noch im

      Projektroot; schrittweise in `docs/` einordnen oder in `AGENTS.md` verlinken (ohne Inhalte

      zu verlieren).

- [ ] (2026-07-16) **`.env.example` anlegen** — Env-Variablen aus `config/services.yaml` / `.env`

      (ohne Secrets) für Onboarding.

- [ ] (2026-07-16) **SSL Auto-Renewal prüfen** auf Server: `sudo certbot renew --dry-run`

      (Zertifikate zuletzt manuell am 2026-07-11 erneuert, gültig bis 2026-10-11).

- [ ] (2026-07-16) **Bayrol HTTPS-Block prüfen** — nach Certbot ggf. `ProxyPass` +

      `X-Forwarded-Proto`/`Port` in `bayrol-proxy-le-ssl.conf` (analog Dulcopool, siehe

      `SSL_CERTBOT_ERNEUERUNG.md`).



## Erledigt

- [x] (2026-09-10) **Fit wie ein Fisch — Mails, Sammelanmeldung, Warteliste, Listen.** Bewusst
      ohne Wiederverwendung der BZ-/Schwimm-Bausteine (Wartbarkeit): eigene Vorlagen-Entity
      `FischEmailTemplate` + Admin unter `/admin/fisch/email-templates` mit Fallback-Katalog und
      Absender-Hinweis; `FischMailService` mit 32 Platzhaltern inklusive Standortinfos;
      Buchungsflow Anmeldung → Validierungslink (72 h) → Bestätigungsmail, offene Anmeldungen
      belegen den Platz mit; Warteliste mit Platzangebot (24 h), Detailansicht, händischem
      Nachrücken und FIFO-Automatik; Formularbuilder für Einzel-, Schul- und Elternformular
      (`/admin/fisch/formulare`); Sammelanmeldung mit kurz codierten Links (Schule 8, Eltern 10
      Zeichen, `/booking/fisch/e/{code}`); Standort-Zusatzinfos (Adresse, Anfahrt, Parkplatz, Maps);
      Kontaktdaten und CSV-Export in Kurs-/Teilnehmerlisten. Neue Commands
      `app:fisch:waitlist-expire` und `app:fisch:expire-pending`, Migration `Version20260910150000`.

- [x] (2026-09-08) **BZ-Warteliste: Haken verschickte die falsche E-Mail.** Der grüne Haken in
      `/admin/bz/courses/waitlist` setzte die Buchung direkt auf `pending`; dadurch ging die
      Zahlungsinfo-Mail raus (ohne Kurs-Template der Fallback „Ihre Buchung wurde erfasst") statt des
      Platzangebots. Neu: `CourseWaitlistService::offerPlaceToBooking()` und
      `POST /admin/course-bookings/api/{id}/waitlist-offer`. Der Dialog bietet jetzt „Platz anbieten"
      (Platzangebot-Mail mit 24-Stunden-Annahme-Link, Zahlungsinfo folgt erst nach der Annahme) und
      „Direkt umwandeln" für telefonische Zusagen; bei zu wenig freien Plätzen warnt er, blockiert
      aber nicht. Getestet mit `app:waitlist:e2e-test --system=bz --admin-offer`.



- [x] (2026-09-03) **BZ-Geschwisterkinder Kapazität & Anzeige:** Eingabe für Geschwisterkinder erscheint
      wieder bei allen Kursen mit `allowSiblings` (vorher nur mit konfigurierten `siblingPrices` —
      Regression seit „Kind-Formular für alle BZ-Kurse"); Geschwister begrenzen im Formular die
      zubuchbaren Plätze, BZ-Dashboard zählt Teilnehmer statt Buchungen; CSV-Export und
      Buchungsdetails zeigen belegte Plätze sowie alle Formularangaben je Geschwisterkind
      (Detail-Modal: eigene Karte pro Kind; CSV: 6 Spalten pro Kind statt Sammelspalte);
      Bestätigungsmails listen Geschwister unter „übermittelte Daten"; `priceMonthly` wird im
      Kind-Formular wieder berücksichtigt (Abo-Buchungen wurden mit 0,00 € gespeichert).

- [x] (2026-08-27) **Booking Schritt 3:** „Weiter zur Buchung“ erscheint neben dem ausgewählten Kurs

      (kein Scroll nach unten nötig); Footer-Button bleibt zusätzlich.

- [x] (2026-08-26) **Fit wie ein Fisch Admin-Kernfunktionen:** Standorte-CRUD, Kurs anlegen/Kapazität/

      aktivieren, CSV-Exports, Teilnehmer stornieren/verschieben, Warteliste übernehmen/entfernen,

      Altersgruppen (Standortkategorien) editierbar.

- [x] (2026-08-26) **Fit wie ein Fisch Kursübersicht UX:** Gruppierung nach Schwimmbad, Stats, Filter

      (Suche / Altersgruppe / voll/frei); Kapazitäts-Placeholder und Excel-Dummy entfernt.

- [x] (2026-08-26) **Fisch-Admin UI:** Layout/Styles an BZ + Schwimmcontainer angeglichen

      (Breadcrumb-Header, Stats-Karten, table-fisch, Quick-Actions).

- [x] (2026-08-26) **Event anlegen Datum-Fehler:** Admin-UI mappt `eventStartDate` → API-`startDate`

      (Create/Update + Backend-Fallback); Ursache seit Event-Datumspflicht 24.08.

- [x] (2026-08-25) **Fit wie ein Fisch Startseite Admin:** `/admin/fisch/startseite` (Texte, Sponsoren,

      Kennzahlen); öffentliche Seite mit Karten/Stats modernisiert.

- [x] (2026-08-25) **Fit wie ein Fisch öffentliche Seite:** Layout/Grafiken von fit-fisch.de (Hero, Logos,

      Footer, Begrüßungstext); Assets unter `public/images/fisch/`.

- [x] (2026-08-25) **Fit wie ein Fisch Admin-Sidebar + Grundeinstellungen:** Menü in 3 Abschnitten

      (Kursverwaltung, Standortverwaltung, Einstellungen); `/admin/fisch/grundeinstellungen` mit Key-Value-UI;

      Migration `Version20260825230000` (Alter, Kurszeitraum in `fisch_season_config`).

- [x] (2026-08-25) **Fit wie ein Fisch Altsystem-Screenshots:** UI-Referenz (9 Admin-Seiten) in

      `docs/FIT_WIE_EIN_FISCH.md` → „Admin-Oberflächen — Altes System“ dokumentiert.

- [x] (2026-08-25) **Fit wie ein Fisch Anmeldung:** Speichern mit Kapazitäts-Lock, Slot-API,

      Wartelisten-Formular; `FischRegistrationService`, `FischBookingApiController`.

- [x] (2026-08-25) **Fit wie ein Fisch DB-Grundlage:** Entities `Fisch*`, Migration

      `Version20260825120000` (6 Pools, 96 Kurse, Beispiel-Anmeldungen/Warteliste); Admin-Listen aus DB.

- [x] (2026-08-25) **Mobi-Buchung Asset-Pfade:** CSS/JS via `asset()` statt `/css/` (404 unter

      `/ksbdueren/public` behoben).

- [x] (2026-08-24) **Admin Event-Bearbeitung:** Startdatum wird beim Laden befüllt (API-Fallback aus

      Namen + korrekte Reihenfolge im Formular).

- [x] (2026-08-24) **Events einmalig:** `type=event` nur am Event-Datum (start/end bzw. Datum

      im Namen); Slot-APIs begrenzt; Admin verlangt Event-Datum; bestehende Events nachgezogen

      (Migration Version20260824110000).

- [x] (2026-08-24) **Schwimm-mit-Mobi Buchungsflow Design:** Schritte 2–5 + Landingpage

      einheitlich über `booking-mobi-theme.css` (helles Layout, rote Akzente, iFrame-tauglich).

- [x] (2026-08-24) **Schwimm-mit-Mobi Landingpage `/booking`:** nur freigeschaltete Mobi-Standorte

      (`showOnSchwimmMitMobi`); kundenfreundliches Design in KSB-Rot; Admin-Toggle analog Narwali

      unter `/appointments/admin/locations`.

- [x] (2026-08-22) **Step 3 Weiter-Button:** bei Kursen über Monatsgrenzen (Aug→Sep)

      Auswahl der sichtbaren Karte; Klick auf Termin zeigt „Weiter“.

- [x] (2026-08-22) **Buchung Step 3 keine Termine:** falsche API-URL (`/public/appointments/…`)

      + fehlender/ineffizienter Kursfilter; jetzt `path(public_appointments_…)` und schnelle

      Slot-Berechnung nur für gewählte Kurse (September-Kurse Buchheim sichtbar).

- [x] (2026-08-22) **Fallback-Mails + Warteliste E2E:** System-Fallbacks (exakter HTML-Inhalt)

      in Swim- und BZ-Template-Admin; Wartelisten-Flow beider Systeme getestet/geflickt

      (Familien-Bewegungszeit Warteliste, Sync-Mails, SMTP-Fehler bricht Angebot nicht mehr ab,

      Zahlungsbestätigung-Fallback BZ). Command: `app:waitlist:e2e-test`.

- [x] (2026-08-22) **BZ-Dashboard 1:1:** eigenes Dashboard unter `/admin/bz/dashboard`

      (Stats, Schnellaktionen, Kursarten, freie Plätze, Buchungsliste); Startseite beim

      Systemwechsel auf Bewegungszentrum.

- [x] (2026-08-22) **Admin-Dashboard Ladezeit:** keine Voll-Ladung aller Buchungen mehr;

      Counts statt Entity-Listen, Joins für Listen, Buchungstabelle auf neueste 50 begrenzt.

- [x] (2026-08-22) **KSB 2026-08-21 – Fallback-E-Mail neutral:** Zahlungsinfo ohne Kurszuordnung

      kein globaler Fallback mehr; System-Fallback in der Template-Admin-UI sichtbar.

- [x] (2026-08-22) **KSB 2026-08-21 – Workshops getrennt:** eigene Cards für Workshop-Gruppen

      außerhalb des Menüs (Event-Center Step 1).

- [x] (2026-08-22) **KSB 2026-08-21 – Alte Kurse aus Filter:** nur aktive, nicht abgelaufene Kurse

      im Kursbuchungs-Filter.

- [x] (2026-08-22) **KSB 2026-08-21 – Warteliste Nachrutschen:** BZ-Umwandlung mit confirmation-Mail;

      Schwimmen-Umwandlung legt Termin an + Validierungs-Mail.

- [x] (2026-08-22) **KSB 2026-08-21 – Wartelisten-Layout:** BZ-Warteliste an Schwimmen angeglichen.

- [x] (2026-08-22) **KSB 2026-08-21 – Warteliste manuelles Löschen:** BZ-Löschen + Hinweistext;

      bei Angebot Nachrücken.

- [x] (2026-08-22) **KSB 2026-08-21 – BZ-Warteliste Detail-Link:** Detail-Modal statt Kursbuchungs-Liste.

- [x] (2026-08-22) **KSB 2026-08-21 – Manuelle Buchung E-Mails:** Auto-Versand (abschaltbar).

- [x] (2026-08-22) **KSB 2026-08-21 – BZ-Warteliste bezahlt:** Zahlung erst nach Umwandlung.

- [x] (2026-08-22) **KSB 2026-08-21 – Pflichtfelder BZ:** Kind-Formular analog Ferienspiele für **alle**
      Bewegungszentrum-Kurse (Familien-Bewegungszeit eigenes Formular; Gesundheit nur dort Pflicht).

- [x] (2026-08-22) **KSB 2026-08-21 – JS-Fehler selectCourse:** Null-Check für `continueBtn`.

- [x] (2026-08-22) **KSB 2026-08-21 – Systeme optisch trennen:** Dashboard bleibt; Menü nach
      System (Swim/BZ/Fisch/KSB) mit Farben + Switcher; öffentlicher Hub `/buchung`.

- [x] (2026-07-20) **Arbeitspaket 3 – automatisierte Wartelistenangebote:** gemeinsame Migration

      für Angebots-/Reservierungsfelder und Indizes, getrennte Ablauf-Commands mit sicherem

      `--dry-run`, FIFO-Weitergabe, Claim-Kapazitätsprüfung und fehlender BZ-Storno-Trigger;

      Cron- und manuelle Testdokumentation ergänzt.

- [x] (2026-07-20) **`docs/CRONJOBS.md`:** neue Wartelisten-Ablaufjobs inklusive Zweck,

      `--dry-run`, Exit-Codes und empfohlenem 5-Minuten-Intervall dokumentiert; bestehende

      Betriebsdokumentation verlinkt.

- [x] (2026-07-20) **BZ-Kurswarteliste:** automatische Eingangsbestätigung erhält einen neutralen

      Fallback, falls kein aktives Wartelisten-Template vorhanden ist; isolierter Versandtest

      an `pohl@dpohl-engineering.de` erfolgreich.

- [x] (2026-07-20) **Event-Center-Kursleiter in Buchungsübersicht:** aktive Personalzuordnungen

      werden konsistent gezählt, angezeigt und in der Übersichtsabfrage mitgeladen.

- [x] (2026-07-16) **E-Mail-Postfach getrennt:** Ordner „Kunden & Antworten“ vs. „Buchungsbestätigungen“; Kunden zuerst bei „Alle E-Mails“.

- [x] (2026-07-16) **BZ/Event-Center:** neutrale Fallback-E-Mails, Template-Fallback nur ohne Kurszuordnung, Postfach-Standortfilter, CSV-Export erweitert, E-Mail erneut senden + Export mit Filter, Workshop-Gruppen, Ferienspiele-Geschwister mit Gesundheitsfeldern.

- [x] (2026-07-16) **Agenten-Doku wie Datalogger-Projekt:** `AGENTS.md`, `docs/TODO.md`,

      `docs/journal/`, `.cursor/rules/projekt-konventionen.mdc` angelegt.

- [x] (2026-07-11) **SSL-Zertifikate erneuert** (`dulcopool.dp-smartsolutions.de`,

      `dp-smartsolutions.de`) — Runbook: `SSL_CERTBOT_ERNEUERUNG.md`.

- [x] (2026-06-26) **Bewegung am Ehrentag — Wording:** kein „Kindergeburtstag"/„Geburtstagskind" in

      Event-Center-Buchungssteps; „Wünsche des Kindes", „Bewegter Ehrentag".

- [x] (2026-06-26) **Workshop-Zeitslots:** `bookableTimeSlots` im Admin + Auswahl in Step 3 +

      Kapazitätsprüfung bei Buchung; gebuchte Uhrzeit in `/admin/course-bookings`.

- [x] (2026-06-26) **E-Mail-Templates getrennt:** Termin-Admin nur `APPOINTMENT_TYPES`; Event Center

      + Kursbuchung unter `/admin/event-center/email-templates/`; Event-Center-Template-UI

      gruppiert/einklappbar.

- [x] (2026-06-26) **Outlook Token-Refresh + Einzel-Sync** für Event-Center-Buchungen; fehlende

      Termine bei Statuswechsel nachholen.

- [x] (2026-06-26) **Kursleiter-Portal:** vergangene Event-Termine (einklappbar) für Abrechnungs-Check.


