Files
svc-essensplanung/Doku/anforderungen.md
T

110 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Anforderungen – svc-essensplanung
> Stand: 13.09.2026 · Status: **Agreed Draft** (noch nicht in Code umgesetzt)
Kurzes Mittagessen-Planer-Werkzeug: Gericht anlegen, „fertig/gegessen" abhaken,
Reihenfolge anpassen, Wochentage markieren und bei Bedarf aus dem Archiv
inspirieren lassen. Ein einzelner Nutzer, läuft im eigenen Homelab, mobil via Browser.
## 1. Kern-Entities
### Gericht (Eintrag)
Ein Gericht ist die zentrale Dateneinheit. Felder:
| Feld | Typ | Pflicht | Beschreibung |
|------|-----|---------|--------------|
| `id` | int (PK) | ja | Autogeneriert |
| `name` | text | ja | z. B. „Spaghetti Bolognese" |
| `notiz` | text | nein | Freie Anmerkung, z. B. „mit mehr Soße" |
| `wochentage` | set (Mo–So) | nein | Beliebig viele, optional. **Nur zur Markierung/Gruppierung**, keine Automatik. |
| `sort_order` | int | ja | Position in der Planungsliste (manuell per Drag & Drop) |
| `status` | enum: `geplant` / `gegessen` | ja | `geplant` = aktiv in der Liste, `gegessen` = abgehakt → Archiv |
| `gegessen_am` | date | nein | Setzt sich automatisch, wenn auf `gegessen` gesetzt |
| `erstellt_am` | timestamp | ja | |
| `aktualisiert_am` | timestamp | ja | |
> **Wiederholungen über mehrere Tage** (z. B. Reste Mo+Di) werden **nicht** als
> automische Dauer modelliert. Stattdessen decken die `wochentage`-Markierungen und
> ggf. mehrere Einträge ab. „Erforderlich, dass jeder Tag abgedeckt ist" gilt **nicht** –
> Tage dürfen frei stehen bleiben.
### Archiv
- Das Archiv ist **keine eigene Tabelle**: Es ist die Sicht auf Einträge mit
`status = gegessen`, geordnet nach `gegessen_am` (neueste zuerst).
- Abhaken (`geplant → gegessen`) verschiebt den Eintrag automatisch in die Archivsicht.
- Aufheben / „wieder einplanen" (`gegessen → geplant`) setzt `gegessen_am` zurück und
fügt ihn der Planungsliste wieder hinzu.
## 2. Features (MVP)
### 2.1 Gericht verwalten
- **Anlegen** (name, notiz, wochentage).
- **Bearbeiten** (alle Felder).
- **Löschen** (hart, mit Bestätigung).
- **Reihenfolge ändern**: Drag & Drop in der Planungsliste → persistiert in `sort_order`.
### 2.2 Abhaken / Archiv
- Pro Eintrag ein „Abhaken"-Aktion (Checkbox oder Button).
- Abhaken: `status → gegessen`, `gegessen_am = heute`, Eintrag verschwindet aus der
Planungsliste in die **Archivansicht**.
- In der Archivansicht: Eintrag wieder in die Planung zurückstellen oder Löschen.
### 2.3 Inspiration
- **Inspiration-Panel**, das **jeweils 5 Vorschläge** aus dem Archiv anzeigt.
- Button „Weitere 5" → nächste 5, die noch nicht vorgeschlagen wurden.
- **Auswahlkriterium (gewichteter Mix):**
1. **Lange nicht** gekocht (älteste `gegessen_am`) – primär,
2. **Seltene** (wenigste Auftritte insgesamt) – sekundär,
3. **Häufige** (beliebt) – drittens.
Genauere Gewichtung bei der Implementierung festlegen (siehe ADR-005, offen).
- Jeder Vorschlag hat einen **1-Klick-Button** → übernimmt das Gericht als **neuen
`geplant`-Eintrag** in die Planungsliste (Kopie, `gegessen_am` wird leer).
### 2.4 Ansichten
- **Planung** (Liste der `geplant`-Einträge, sortiert nach `sort_order`).
- **Archiv** (Liste der `gegessen`-Einträge, sortiert nach `gegessen_am` absteigend).
- **Inspiration** (Panel / eigener Bereich, siehe 2.3).
- Wochentage werden je Eintrag **als Markierung** angezeigt (kein Filter nötig, aber
optional als Gruppierung möglich).
## 3. Technische Vorgaben (aus der Diskussion)
- **Backend:** PHP / **Symfony 7**, eigene JSON-Controller (keine ApiPlatform-Magie),
als **API** nutzbar.
- **Frontend:** Serverseitiges Rendering + **htmx** (CRUD + Listen + Formulare).
Sortierbarkeit via **SortableJS** (~20 kB). **Kein Build-Step, kein Node im Runtime.**
- **Datenbank:** **SQLite** (einfach, leicht zu backupn).
- **Mobile:** Responsive + **PWA-Manifest** („Zum Homescreen hinzufügen").
- **Deployment:** Docker-Stack `svc-essensplanung` im Homelab, hängend an das
bestehende Traefik-`infra-traefik_traefik-net`; **Domain:** `essen.ljh31.de`
(ACME `letsencrypt`). Gleiche Deploy-Muster wie die anderen `svc-*`-Stacks.
- **Auth:** Single User → **kein Login**. Optionaler Shared-Token, falls später von
elsewhere (z. B. Home-Assistant) genutzt.
### 3.1 Home-Assistant-Integration (Phase 2, optional)
- HA holt **„Was steht heute an?"** über dieselbe API.
- Ziel: 1 Zeile im HA-Dashboard + ggf. Benachrichtigung „Heute: Bolognese".
- Ist ein z**Add-on**, kein Teil des MVP. Siehe ADR-004 (offen, Phase 2).
## 4. Ausdrücklich NICHT im MVP
- Mehrere Nutzer / Rechte.
- Automatische Wiederholung pro Wochentag (Wochentag ist nur Label).
- Einkaufslisten, Kalorien, Portionen-Logik.
- Offline-First / lokale Sync (htmx braucht die API).
- Export/import (vorerst).
## 5. Offene Punkte (bevor Code)
- [x] `menge`: **weggelassen** im MVP (Name + Notiz + Wochentag reicht).
- [ ] Soll **Löschen** hart sein oder auch auf archiviert? (vorerst: hart)
- [ ] PWA: nur Add-to-Home, oder auch Push (braucht SW + Service-Worker)?
- [ ] HA-Integration: konkret als Sensor (REST-Poll) via `rest`-Integration in HA —
dazu braucht die API einen sauberen `GET /api/today`-Endpunkt.
## 6. Abnahmekriterien (Definition of Done, MVP)
- [ ] Gericht anlegen/bearbeiten/löschen läuft via UI.
- [ ] Reihenfolge per Drag & Drop persisted (übersteht Reload).
- [ ] Abhaken verschiebt Eintrag in Archiv, Wiederherstellen bringt ihn zurück.
- [ ] Inspiration zeigt 5, „Weitere 5" liefert neue 5, 1-Klick übernimmt.
- [ ] Läuft auf `essen.ljh31.de` (https, ACME) und ist mobil + add-to-home.
- [ ] Daten in SQLite, kein Build-Step im Deployment.