Files
svc-essensplanung/Doku/plan.md
T
jens 1589088379 M1: CRUD-Slice 'Mahlzeit' Schritt 1 – Logik + Daten + Tests
Rich-Model Mahlzeit (MahlzeitStatus, Wochentag) mit Invarianten und
Zustandsübergängen; DTOs + MahlzeitFactory (reine Mapping-Funktionen);
Manager (create hängt an Ende an: maxSortOrder+1, find → 404) und
Create/Update/Delete-UseCases mit Transaktion + Events nach Commit.

Data-Layer: MahlzeitEntity (Tabelle essens_mahlzeiten, wochentage als
CSV), Mapper (CSV/Enum/null), Provider (find/list/maxSortOrder),
Processor (create/save/delete). DI-Bindings in services.yaml.
ClockInterface (Logic) + SystemClock (Data).

Tests: Model/Factory/UseCase-Unit + Provider/Processor/Mapper-Integration
(In-Mem-SQLite). composer test grün (53 Tests, 161 Assertions).
2026-09-19 08:55:54 +02:00

4.4 KiB
Raw Blame History

Implementierungsplan

Status: final (2026-09-13, abgestimmt) · Basis: anforderungen.md, architektur.md, ADR 001–007

Prinzipien

  • Vertikal geschnitten: Jedes Milestone ist ein vollständiger UI→Logic→Data-Slice und am Ende lauffähig/testbar (kein Layer-Reihenbau).
  • Ein Milestone = ein Review-Pausenpunkt. Jeder MS wird einzeln abgenommen, bevor der nächste startet.
  • Kein CI – PHPUnit läuft manuell (composer test).
  • Auth: Web-UI über Keycloak-OIDC (realm family, eigener Client essens), Auto-Provision des lokalen Users (wie svc-webui). HA bezieht die Tagesansicht über GET /api/today mit statischem API-Token (X-Api-Token aus .env, kein Keycloak-Refresh für HA). Damit wird ADR-003 in M0 entsprechend überarbeitet.
  • Deploy (M5) erst nach expliziter Freigabe.

Milestones

M0 – Skelett + Auth-Grundgerüst

  • Symfony 7.4 LTS, PHP 8.4, FrankenPHP: composer.json, config/ (framework, doctrine/SQLite, twig, routing), public/index.php
  • Struktur laut architektur.md leergelegt (src/UI, src/Logic, src/Data)
  • Keycloak-OIDC: manueller OidcClient (kein league/oauth2-client, kein Security-Bundle; vgl. ADR-003), Login/Callback/Logout im UI-Layer, sub/email-Claim → lokale User-Zeile (Auto-Provision)
  • Docker: Dockerfile (php:8.4-frankenphp), compose.yaml (Volume data/ für SQLite, .env), Network infra-traefik_traefik-net (external), Traefik-Labels → essen.ljh31.de + ACME + redirect-to-https
  • phpunit.xml, tests/, htmx + SortableJS in public/js/
  • ADR-003 überarbeitet (Keycloak statt „kein Login")
  • DoD: Container läuft, GET / → Keycloak-Login, danach Hello-World-Seite

M1 – CRUD-Slice (Model: Mahlzeit – Namenskonszept: Domäne DE, Tech-EN, s. architektur.md §0.1)

  • Schritt 1 (Logik+Daten): src/Logic/Essen – Mahlzeit-Model (+MahlzeitStatus, Wochentag), Mahlzeit{Create,Update}Request/Response-DTOs, MahlzeitFactory, Mahlzeit{Provider,Processor}Interface, MahlzeitManager, Mahlzeit{Create,Update,Delete}UseCase, MahlzeitListQuery, MahlzeitNotFoundException (→404), Events; src/Data/Essen – MahlzeitEntity (Tabelle essens_mahlzeiten, wochentage als CSV), MahlzeitMapper/Provider/Processor, Migration. Tests: UseCase/Model-Unit + Provider/Processor-Integration (in-mem SQLite). DoD 1: composer test grün, CRUD vollständig über Logic-API testbar.
  • Schritt 2 (UI): MahlzeitController + templates/mahlzeiten/ + Routen /mahlzeiten[/{id}] (POST/Redirect/Flash, Wochentage als Checkboxes) + Controller-Feature-Test (eingeloggte Session).
  • DoD: Gericht anlegen/bearbeiten/löschen im Browser (als eingeloggte/r Nutzer)

M2 – Status & Wochentage

  • CheckOffDish/UncheckDish (Status aktiv/gecheckt), ArchiveDish
  • Wochentag-Tags (Mo–So) setzen/ändern, Liste nach Tag gruppier-/filterbar
  • DoD: Check-Off via htmx-Toggle, Tagesansicht, Archiv-Tab

M3 – Reorder + Inspiration

  • ReorderDishes (SortableJS-change → Position-Ints, persistiert)
  • SuggestDishes-Query: Slow 0.5 / Rarität 0.3 / Hotness 0.2 (ADR-006), 5 Vorschläge + „Weitere 5", 1-Klick-Adopt → CreateDish mit Referenz
  • DoD: Reorder bleibt nach Reload bestehen; Inspiration klickbar adoptierend

M4 – Härtung & API

  • X-Api-Token-Guard (optional, .env) für GET /api/today (HA-ready)
  • Fehlerseiten, Logging, Backup-Hinweis (SQLite-Datei data/)
  • DoD: curl -H "X-Api-Token: …" /api/today liefert Tagesgericht-JSON; DoD-Punkte aus anforderungen.md abgehakt

M5 – Deploy (erst nach Freigabe)

  • Stack auf docker1:/root/stacks/svc-essensplanung, git pull && docker compose up -d
  • Traefik: essen.ljh31.de, Let's-Encrypt
  • Keycloak: Client essens in realm family anlegen (Redirect-URI https://essen.ljh31.de)
  • DoD: Gesamt-DoD aus anforderungen.md erfüllt, erreichbar ohne LAN-IP

Test-Strategie (quer)

  • PHPUnit je Milestone: UseCase-Unit (in-mem SQLite, Logic-Dependencies als Fakes) + Feature-Tests (HTTP gegen Test-DB)
  • Manuell: docker compose run app composer test bzw. vendor/bin/phpunit
  • Kein CI (bewusst, s. Prinzipien)

Abnahme-Historie

MS Datum Status
M0 offen
M1 offen
M2 offen
M3 offen
M4 offen
M5 offen