M19 – Anhänge und Fotos an Schritten #52

Closed
opened 2026-10-04 16:19:17 +00:00 by florian.wilde · 0 comments
Owner

Ziel

„Seriennummer fotografiert“, „Typenschild“, „Zustand bei Übergabe“, „Rechnung abgelegt“ — manches
lässt sich nicht abhaken, es muss gezeigt werden. Ein Schritt soll Dateien und Fotos aufnehmen
können, am Handy direkt aus der Kamera.

Zu entscheiden

  • Dateien im Dateisystem, Metadaten in der Datenbank — Empfehlung. Ein Pfad aus der
    Umgebung (ANHAENGE_PFAD), darunter nach Kunde und Lauf gegliedert. Gegen bytea in Postgres
    spricht die Sicherung: ein pg_dump mit Fotos ist nach einem Jahr kein pg_dump mehr, das
    jemand einspielt. Gegen S3 spricht, dass diese Anwendung selbst gehostet läuft und keinen
    Objektspeicher voraussetzen soll.
    Folge, die mitgeplant werden muss: der Compose-Stand und die native Installation brauchen
    ein Volume, und docs/betrieb/sicherung.md muss beides nennen. Eine Sicherung, die nur die
    Datenbank mitnimmt, verliert ab hier Daten — das ist genau die Art Zusage, die dieses Projekt
    sonst teuer bezahlt hat.
  • Keine Verkleinerung auf dem Server im ersten Schritt. Ein Handyfoto hat heute 3–6 MB; eine
    Obergrenze (etwa 10 MB je Datei, 20 Dateien je Lauf) ist ehrlicher als eine Umwandlung, die
    Metadaten verliert und eine Bildbibliothek ins Projekt zieht.

Aufgaben

  • Modell Anhang: schrittergebnisId, kundeId, Dateiname, Medientyp, Größe, Prüfsumme,
    erstelltVonId, erstelltAm; Datei daneben im Dateisystem
  • Hochladen über einen Route Handler mit rechtErforderlich — kein Weg daran vorbei, und
    jeder Abruf prüft Recht und Mandant, auch der des Bildes selbst
  • Grenzen: Medientypen auf Bilder und PDF, Größe je Datei und Anzahl je Lauf, beides in der
    Umgebung einstellbar; eine abgewiesene Datei nennt den Grund
  • Am Handy direkt aus der Kamera (capture="environment"), am Rechner aus dem Dateiwähler
  • Der Archiv-Schreibschutz gilt auch hier: an einem archivierten Lauf kommt kein Anhang mehr
    dazu und keiner weg. laufMussVeraenderbarSein sitzt an genau einer Stelle — dort anschließen
  • Druckansicht: Bilder als Miniaturen mit Dateinamen, PDF nur als Zeile
  • docs/betrieb/sicherung.md, docker-compose.yml, deploy/install.sh: Volume, Rechte,
    Sicherung und Rückspielung
  • Anleitung Kapitel 02 und 08

Akzeptanzkriterien

  • Test: Anhang an einem Schritt hochladen, in der Abarbeitung und im Druck sichtbar
  • Test: an einem archivierten Lauf wird das Hochladen abgewiesen
  • Test: ein Anhang eines fremden Kunden ist über seine Adresse nicht abrufbar
  • Test: eine zu große Datei und ein falscher Medientyp werden mit Grund abgewiesen
  • Test: docker-compose.yml hat ein Volume für die Anhänge, und sicherung.md nennt es (wie
    tests/betriebsstand.test.ts es für die Datenbank schon prüft)
  • Sicherung und Rückspielung einmal wirklich gefahren, nicht nur beschrieben

Quelle im Repo: docs/issues/032-anhaenge.md

## Ziel „Seriennummer fotografiert“, „Typenschild“, „Zustand bei Übergabe“, „Rechnung abgelegt“ — manches lässt sich nicht abhaken, es muss gezeigt werden. Ein Schritt soll Dateien und Fotos aufnehmen können, am Handy direkt aus der Kamera. ## Zu entscheiden - [ ] **Dateien im Dateisystem, Metadaten in der Datenbank** — Empfehlung. Ein Pfad aus der Umgebung (`ANHAENGE_PFAD`), darunter nach Kunde und Lauf gegliedert. Gegen `bytea` in Postgres spricht die Sicherung: ein `pg_dump` mit Fotos ist nach einem Jahr kein `pg_dump` mehr, das jemand einspielt. Gegen S3 spricht, dass diese Anwendung selbst gehostet läuft und keinen Objektspeicher voraussetzen soll. **Folge, die mitgeplant werden muss:** der Compose-Stand und die native Installation brauchen ein Volume, und `docs/betrieb/sicherung.md` muss beides nennen. Eine Sicherung, die nur die Datenbank mitnimmt, verliert ab hier Daten — das ist genau die Art Zusage, die dieses Projekt sonst teuer bezahlt hat. - [ ] **Keine Verkleinerung auf dem Server im ersten Schritt.** Ein Handyfoto hat heute 3–6 MB; eine Obergrenze (etwa 10 MB je Datei, 20 Dateien je Lauf) ist ehrlicher als eine Umwandlung, die Metadaten verliert und eine Bildbibliothek ins Projekt zieht. ## Aufgaben - [ ] Modell `Anhang`: `schrittergebnisId`, `kundeId`, Dateiname, Medientyp, Größe, Prüfsumme, `erstelltVonId`, `erstelltAm`; Datei daneben im Dateisystem - [ ] Hochladen über einen Route Handler mit `rechtErforderlich` — kein Weg daran vorbei, und **jeder** Abruf prüft Recht und Mandant, auch der des Bildes selbst - [ ] Grenzen: Medientypen auf Bilder und PDF, Größe je Datei und Anzahl je Lauf, beides in der Umgebung einstellbar; eine abgewiesene Datei nennt den Grund - [ ] Am Handy direkt aus der Kamera (`capture="environment"`), am Rechner aus dem Dateiwähler - [ ] **Der Archiv-Schreibschutz gilt auch hier**: an einem archivierten Lauf kommt kein Anhang mehr dazu und keiner weg. `laufMussVeraenderbarSein` sitzt an genau einer Stelle — dort anschließen - [ ] Druckansicht: Bilder als Miniaturen mit Dateinamen, PDF nur als Zeile - [ ] `docs/betrieb/sicherung.md`, `docker-compose.yml`, `deploy/install.sh`: Volume, Rechte, Sicherung **und** Rückspielung - [ ] Anleitung Kapitel 02 und 08 ## Akzeptanzkriterien - [ ] Test: Anhang an einem Schritt hochladen, in der Abarbeitung und im Druck sichtbar - [ ] Test: an einem archivierten Lauf wird das Hochladen abgewiesen - [ ] Test: ein Anhang eines fremden Kunden ist über seine Adresse **nicht** abrufbar - [ ] Test: eine zu große Datei und ein falscher Medientyp werden mit Grund abgewiesen - [ ] Test: `docker-compose.yml` hat ein Volume für die Anhänge, und `sicherung.md` nennt es (wie `tests/betriebsstand.test.ts` es für die Datenbank schon prüft) - [ ] Sicherung und **Rückspielung** einmal wirklich gefahren, nicht nur beschrieben --- Quelle im Repo: `docs/issues/032-anhaenge.md`
florian.wilde added this to the v0.2.0 milestone 2026-10-04 16:19:17 +00:00
florian.wilde added the phase-2backendfrontendinfra labels 2026-10-04 16:19:17 +00:00
Sign in to join this conversation.