Files
hms-licht-ton/docs/requirements.md
T

651 lines
34 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.
# Requirements Specification HMS Licht & Ton Homepage
> **Projekt:** hms-licht-ton (ID 30)
> **Datum:** 2026-07-08
> **Status:** Draft Ready for UI Design
> **Autor:** Requirements Analyst (A0 Orchestrator)
---
## 1. Projektüberblick
### 1.1 Ziel
Neuaufbau der Website für **HMS Licht & Ton GbR** (Hammerschmidt u. Mössle GbR), Veranstaltungstechnik aus Leipheim/Ellzee. Die bestehende WordPress-Website wird durch eine moderne, mobile-first Web-Anwendung ersetzt. Kern-Neuheit ist ein **Online-Mietkatalog** mit Rentman-Integration (Equipment-Import + Mietanfragen an Rentman).
### 1.2 Unternehmen
- **Firma:** Hammerschmidt u. Mössle GbR
- **Erfahrung:** 20+ Jahre Veranstaltungstechnik
- **Leistungen:** Vermietung, Verkauf, Personal, Transport, Lagerung, Werkstatt, Installation, Booking
- **Ansprechpartner:** Leopold Hammerschmidt, Andreas Mössle
- **Büro:** Grockelhofen 10, 89340 Leipheim
- **Lager:** Zur Schönhalde 8, 89352 Ellzee
- **Telefon:** +49 8221 204433 / 204434
- **E-Mail:** info@hms-licht-ton.de
- **Social:** Facebook, Instagram
### 1.3 Domain Knowledge
- **Veranstaltungstechnik:** Licht-, Ton-, Bühnentechnik, Rigging, Traversen, Mischpulte (z.B. Grandma3 Command Wing)
- **Rentman:** Projektzentrisches ERP für Equipment-Rental. Equipment-Katalog, Projektanfragen, Angebotserstellung.
- **Mietworkflow:** Kunde sieht Equipment → fragt an → HMS prüft in Rentman → erstellt Angebot → bestätigt
- **Branche:** B2B/B2C Hybrid sowohl Firmenveranstaltungen als auch private Feiern
---
## 2. User-Anforderungen (direkt vom User)
1. Inhalte der bestehenden Website übernehmen, **AUSSER** 'Neu in der Vermietung' (entfällt)
2. Online-Mietkatalog **NEU** aufbauen: Artikel-Import von Rentman, Mietanfragen an Rentman senden
3. **Kein Shop**, Mietanfragen statt Shop-Funktion
4. **Kein CMS/News-System**
5. Modernes Frontend + eigenes Backend (kein WordPress), kein konkretes Framework vorgegeben
6. **Mobile extrem wichtig** → Mobile-First Design
7. Design: **Grautöne als Hauptfarbschema** + oranges Logo (SVG von bestehender Website übernehmen)
---
## 3. Funktionale Anforderungen
### [F-HMS-01] Home / Startseite
**Anforderung:** Startseite mit Hero-Bereich, Unternehmensbeschreibung (20 Jahre Erfahrung, Full Service, Alles aus einer Hand), Leistungsübersicht (Vermietung, Verkauf, Personal, Transport, Lagerung, Werkstatt, Installation, Booking), Vermietungs-Info-Bereich (großer Materialbestand, Selbstabholung/Lieferung/DryHire, Verweis auf Online-Mietkatalog), Adress-/Kontaktdaten im Footer-Bereich.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User navigiert zu '/'. Erwartet: Hero-Bereich mit Headline 'Ihr professioneller Partner für Veranstaltungstechnik' sichtbar, 'Über uns'-Sektion mit 20 Jahre Erfahrung, Full Service, Alles aus einer Hand sichtbar, Leistungsübersicht mit allen 8 Leistungen sichtbar, Link zum Mietkatalog sichtbar und klickbar.
2. **Edge Case:** User lädt Seite mit langsamer Verbindung. Erwartet: Text-Inhalte erscheinen sofort (SSR/SSG), Bilder laden lazy mit Placeholder, keine Layout-Shifts (CLS < 0.1).
3. **Mobile:** Seite auf 375px Breite (iPhone SE). Erwartet: Alle Sektionen untereinander, Hero-Text lesbar, Leistungs-Icons/Texte nicht abgeschnitten, Touch-Targets min 44x44px.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Manuelle Verifikation: Alle Inhalte der alten Home-Seite (außer 'Neu in der Vermietung') sind vorhanden
- Lighthouse Mobile Score >= 90
---
### [F-HMS-02] Referenzen / Bildergalerie
**Anforderung:** Bildergalerie-Seite mit Überschrift 'Bilder / Referenzen', 'Machen Sie sich ein Bild von unserer Arbeit', 'Impressionen vorangegangener Events'. Bilder in Grid-Anordnung, Klick öffnet Lightbox/Vollbildansicht. Bilder sind statisch (kein CMS), werden vom Backend verwaltet.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User navigiert zu '/referenzen'. Erwartet: Galerie lädt mit mindestens 8 Bildern, Grid-Layout sichtbar, Klick auf ein Bild öffnet Lightbox mit Navigation (prev/next/close).
2. **Edge Case:** Bild kann nicht geladen werden (defekte URL). Erwartet: Fallback-Placeholder wird angezeigt, keine weiße Lücke, keine JS-Fehler.
3. **Mobile:** Galerie auf 375px. Erwartet: 1-2 Spalten Grid, Bilder quadratisch oder aspect-ratio konsistent, Lightbox funktionsfähig mit Swipe-Gesten.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Lightbox öffnet/schließt korrekt
- Bilder laden mit lazy-loading
---
### [F-HMS-03] Kontaktseite mit Formular
**Anforderung:** Kontaktseite mit: Überschrift 'Planen Sie eine Veranstaltung?', Anschrift (Büro: Grockelhofen 10, 89340 Leipheim; Lager: Zur Schönhalde 8, 89352 Ellzee), Öffnungszeiten (MonFr: 10:0018:00), Google Maps Link 'Route planen', Kontaktdaten (Telefon, E-Mail), Ansprechpartner (Leopold Hammerschmidt +49 172 6264796, Andreas Mössle +49 173 9014604), Social Links (Facebook, Instagram), Kontaktformular (Name, E-Mail, Telefon, Nachricht, DSGVO-Einwilligung).
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User füllt Kontaktformular aus (Name='Test User', E-Mail='test@example.com', Nachricht='Test anfrage') und sendet ab. Erwartet: Form wird validiert, Success-Message erscheint, E-Mail wird an info@hms-licht-ton.de gesendet.
2. **Edge Case:** User sendet Formular ohne E-Mail-Adresse. Erwartet: Validierung zeigt Fehlermeldung, keine E-Mail wird gesendet, Form bleibt ausgefüllt.
3. **Edge Case:** User sendet Formular ohne DSGVO-Häkchen. Erwartet: Validierung blockiert Submit, Fehlermeldung 'Bitte akzeptieren Sie die Datenschutzerklärung'.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- E-Mail-Empfang manuell verifiziert
- DSGVO-Einwilligung Pflichtfeld
- Form-Validation serverseitig UND clientseitig
---
### [F-HMS-04] Mietkatalog Equipment-Liste
**Anforderung:** Katalog-Seite '/mietkatalog' mit allen Equipment-Artikeln aus Rentman. Darstellung als Grid- oder Listen-Ansicht mit: Artikelname, Artikelnummer, Kategorie, Thumbnail-Bild (falls vorhanden), Kurzbeschreibung. Pagination oder Infinite-Scroll bei vielen Artikeln. Jeder Artikel ist klickbar → Detailansicht.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User navigiert zu '/mietkatalog'. Erwartet: Liste lädt mit >=10 Artikeln, jeder Artikel zeigt Name + Kategorie, Klick auf Artikel öffnet Detailseite.
2. **Edge Case:** Rentman API nicht erreichbar beim Laden. Erwartet: Cached/zwischengespeicherte Daten werden angezeigt, Warnhinweis 'Katalog wird aktuell aktualisiert' sichtbar, keine leere Seite.
3. **Performance:** Katalog mit 500+ Artikeln. Erwartet: Erste 20 Artikel in <2s geladen, Pagination/Infinite-Scroll funktional, keine Browser-Freezes.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Equipment-Daten aus Rentman importiert
- Pagination funktional
- Mobile: Grid passt sich an (1-2 Spalten)
---
### [F-HMS-05] Mietkatalog Equipment-Detailansicht
**Anforderung:** Detailseite '/mietkatalog/{id}' mit: Vollständige Artikelinfo (Name, Artikelnummer, Kategorie, Beschreibung, Spezifikationen, Bilder), Mietpreis (falls verfügbar), Verfügbarkeit (falls abrufbar), 'Mietanfrage'-Button der Artikel zum Anfrage-Warenkorb hinzufügt. Breadcrumb-Navigation.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User klickt auf Artikel in Katalog. Erwartet: Detailseite lädt mit Name, Beschreibung, Bild, 'Mietanfrage'-Button sichtbar und klickbar.
2. **Edge Case:** Artikel-ID existiert nicht. Erwartet: 404-Seite mit 'Artikel nicht gefunden' + Link zurück zum Katalog.
3. **Integration:** User klickt 'Mietanfrage'. Erwartet: Artikel wird zum Anfrage-Warenkorb hinzugefügt, Toast-Bestätigung sichtbar, Warenkorb-Counter aktualisiert.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Detail-Daten korrekt aus Backend/CACHE
- Mobile: Alle Informationen lesbar
---
### [F-HMS-06] Mietkatalog Search & Filter
**Anforderung:** Such- und Filterfunktion im Mietkatalog: Freitext-Suche (Artikelname, -nummer), Kategorie-Filter (Dropdown/Tags), Sortierung (Name A-Z, Name Z-A). Filter kombinierbar. Resultat-Anzahl sichtbar. Filter-Reset-Button.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User gibt 'Lautsprecher' in Suchfeld ein. Erwartet: Liste filtert in Echtzeit auf Artikel mit 'Lautsprecher' im Namen, Resultat-Anzahl aktualisiert.
2. **Edge Case:** Suche ohne Treffer. Erwartet: Empty-State 'Keine Artikel gefunden' + Vorschlag Filter zurückzusetzen.
3. **Integration:** User kombiniert Suche 'PA' + Kategorie-Filter 'Ton'. Erwartet: Nur Artikel der Kategorie 'Ton' mit 'PA' im Namen werden angezeigt.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Filter kombinierbar
- Mobile: Filter in Collapse/Drawer erreichbar
- Suchergebnis <500ms
---
### [F-HMS-07] Mietkatalog Mietanfrage-Formular
**Anforderung:** Mietanfrage-Formular '/mietanfrage' mit: ausgewählte Artikel (aus Warenkorb) mit Menge, Veranstaltungsdaten (Name, Datum von/bis, Ort, Anzahl Personen), Kontaktdaten (Name, Firma, E-Mail, Telefon, Adresse), Nachricht. Submit sendet Anfrage an Rentman via POST /projectrequests + POST /projectrequests/{id}/projectrequestequipment.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User hat 3 Artikel im Warenkorb, füllt Veranstaltungsdaten + Kontaktdaten aus, sendet ab. Erwartet: POST /projectrequests wird gesendet, Equipment wird via POST /projectrequests/{id}/projectrequestequipment hinzugefügt, Success-Page mit Anfrage-Referenz, Bestätigungs-E-Mail an User.
2. **Edge Case:** Warenkorb ist leer, User navigiert zu '/mietanfrage'. Erwartet: Hinweis 'Keine Artikel ausgewählt' + Link zum Mietkatalog.
3. **Edge Case:** Rentman API nicht erreichbar beim Submit. Erwartet: Anfrage wird lokal gespeichert (Retry-Queue), User sieht 'Anfrage eingegangen, wird verarbeitet', Admin-Benachrichtigung.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Rentman projectrequest erfolgreich erstellt (in Rentman UI sichtbar)
- Bestätigungs-E-Mail versendet
- Form-Validation vollständig
---
### [F-HMS-08] Rentman Equipment-Import (Backend)
**Anforderung:** Backend-Service der periodisch (Cron/Interval) oder manuell (Admin-Trigger) Equipment-Daten von Rentman via GET /equipment (paginiert, limit=100, offset-Iteration bis data leer) abruft und in lokaler Datenbank zwischenspeichert. Felder: id, name, number, category, description, images, specifications, rental_price. Bilder werden lokal gecacht/optimiert.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** Admin triggert manuellen Import. Erwartet: GET /equipment wird paginiert aufgerufen, alle Seiten werden iteriert, Daten in DB gespeichert, Erfolgsmeldung mit Anzahl importierter Artikel.
2. **Edge Case:** Rentman API gibt leere Liste zurück. Erwartet: Bestehende Daten bleiben erhalten, Warnung 'Keine neuen Daten erhalten'.
3. **Edge Case:** Partial-Failure (Seite 3 von 10 schlägt fehl). Erwartet: Bereits importierte Seiten 1-2 bleiben erhalten, Fehler wird geloggt, Retry-Mechanismus für fehlgeschlagene Seite.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Equipment in lokaler DB sichtbar
- Pagination korrekt implementiert (alle Seiten)
- Cron-Job funktional
---
### [F-HMS-09] Rentman Mietanfrage-Übermittlung (Backend)
**Anforderung:** Backend-Service der Mietanfragen aus dem Frontend entgegennimmt und an Rentman sendet. Workflow: 1) POST /projectrequests mit Veranstaltungs- + Kontaktdaten, 2) POST /projectrequests/{id}/projectrequestequipment für jeden Artikel. Retry-Queue bei API-Fehlern. Admin-Notification bei fehlgeschlagenen Übermittlungen.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** Frontend sendet Anfrage mit 3 Artikeln. Erwartet: POST /projectrequests -> id erhalten -> 3x POST /projectrequests/{id}/projectrequestequipment -> alle erfolgreich -> Response 200 an Frontend.
2. **Edge Case:** POST /projectrequests erfolgreich, aber Equipment-POST schlägt fehl bei Artikel 2. Erwartet: Artikel 1 erfolgreich, Artikel 2 in Retry-Queue, Artikel 3 wird trotzdem versucht, Admin wird benachrichtigt.
3. **Integration:** Rentman UI zeigt erstellte Project Request mit korrekten Daten (Name, Datum, Ort, Equipment-Liste).
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Project Request in Rentman sichtbar
- Retry-Queue funktional
- Admin-Notification bei Fehlern
---
### [F-HMS-10] Navigation / Header
**Anforderung:** Sticky Header mit: Logo (SVG, orange), Hauptnavigation (Home, Mietkatalog, Referenzen, Kontakt), Social-Icons (Facebook, Instagram), Telefon-Link (0172 / 6264796). Auf Mobile: Burger-Menu mit Slide-in/Overlay. Header-Background in Grautönen.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User klickt 'Mietkatalog' im Header. Erwartet: Navigation zu '/mietkatalog', Header bleibt sichtbar (sticky), aktiver Nav-Punkt hervorgehoben.
2. **Mobile:** User auf 375px Breite, klickt Burger-Icon. Erwartet: Menu öffnet sich als Overlay, alle Nav-Punkte sichtbar und klickbar, Touch-Targets min 44px Höhe, Menu schließt bei Klick außerhalb.
3. **Edge Case:** User scrollt nach unten. Erwartet: Header bleibt sticky, ggf. kompaktere Höhe, Inhalt wird nicht verdeckt.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Sticky Header funktional
- Mobile Burger-Menu funktional
- Logo als SVG eingebettet
---
### [F-HMS-11] Footer
**Anforderung:** Footer mit: Firmenanschrift (Zur Schönhalde 8, 89352 Ellzee), Telefon (+49 8221 204433/204434), E-Mail (info@hms-licht-ton.de), Social Links (Facebook, Instagram, Google), Rechts-Links (Impressum, DSGVO, AGB Vermietung), Copyright '© Hammerschmidt u. Mössle GbR'. KEIN 'Neu in der Vermietung' / KEIN 'AGB Shop' (entfällt).
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User scrollt zum Seitenende. Erwartet: Footer sichtbar mit Adresse, Telefon, E-Mail, Links zu Impressum/DSGVO/AGB.
2. **Edge Case:** User klickt 'Impressum' im Footer. Erwartet: Navigation zu '/impressum', Footer bleibt sichtbar.
3. **Verification:** Footer enthält NICHT 'Neu in der Vermietung' und NICHT 'AGB Shop'. Erwartet: Diese Elemente sind nicht im DOM.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Alle Links funktional
- 'Neu in der Vermietung' und 'AGB Shop' NICHT vorhanden
---
### [F-HMS-12] Impressum Seite
**Anforderung:** Statische Impressum-Seite '/impressum' mit rechtlichen Angaben gemäß §5 TMG: Firmenname (Hammerschmidt u. Mössle GbR), Vertretungsberechtigte (Leopold Hammerschmidt, Andreas Mössle), Anschrift, Kontakt (Telefon, E-Mail), USt-IdNr. (falls vorhanden), Verantwortlich für Inhalte.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User navigiert zu '/impressum'. Erwartet: Seite lädt mit allen Pflichtangaben, lesbar auf Desktop + Mobile.
2. **Edge Case:** Direktzugriff via URL. Erwartet: Seite ist öffentlich zugänglich, kein Login erforderlich.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 2 Tests grün
- Rechtliche Angaben vollständig
---
### [F-HMS-13] DSGVO Seite
**Anforderung:** Statische Datenschutz-Seite '/datenschutz' mit: Datenschutzerklärung gemäß DSGVO, Informationen zu: Server-Logfiles, Cookies, Kontaktformular-Datenverarbeitung, Rentman-Datenverarbeitung, Analyse-Tools (falls vorhanden), Nutzerrechte (Auskunft, Löschung, Berichtigung).
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User navigiert zu '/datenschutz'. Erwartet: Seite lädt mit allen DSGVO-Pflichtinformationen, lesbar auf Desktop + Mobile.
2. **Edge Case:** Direktzugriff via URL. Erwartet: Seite ist öffentlich zugänglich.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 2 Tests grün
- DSGVO-konform (Rechtsabfrage empfohlen)
---
### [F-HMS-14] AGB Vermietung Seite
**Anforderung:** Statische AGB-Seite '/agb-vermietung' mit Allgemeinen Geschäftsbedingungen für Vermietung. Inhalt wird vom User bereitgestellt (bestehende AGB Vermietung übernehmen).
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User navigiert zu '/agb-vermietung'. Erwartet: Seite lädt mit AGB-Text, lesbar auf Desktop + Mobile.
2. **Edge Case:** Direktzugriff via URL. Erwartet: Seite ist öffentlich zugänglich.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 2 Tests grün
- AGB-Text korrekt übernommen
---
### [F-HMS-15] Logo & Branding Integration
**Anforderung:** Das bestehende SVG-Logo von hms-licht-ton.de wird übernommen (orange Logo auf Grau-Basis). Farbschema: Primär Grautöne (#1a1a1a bis #f5f5f5), Akzentfarbe Orange (wie im bestehenden Logo). Design-Tokens: CSS-Variablen für Farben, Typography, Spacing. Schriften: Modern, gut lesbar (z.B. Inter, Roboto oder ähnlich).
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** Seite lädt. Erwartet: Logo als SVG sichtbar im Header, orange Akzentfarbe bei Buttons/Links, Grau-Abstufungen als Background.
2. **Edge Case:** Logo-SVG kann nicht geladen werden. Erwartet: Fallback-Text 'HMS Licht & Ton' sichtbar, kein broken-image.
3. **Verification:** Alle Seiten nutzen dasselbe Farbschema. Erwartet: CSS-Variablen konsistent, keine hardcoded Farben abweichend vom Design-System.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- SVG-Logo von alter Website übernommen
- Design-Tokens (CSS Custom Properties) definiert
---
### [F-HMS-16] Anfrage-Warenkorb (Mietkatalog)
**Anforderung:** Session-basierter Warenkorb für Mietanfragen (keine Auth erforderlich). Artikel hinzufügen/entfernen, Menge anpassen. Warenkorb-Icon im Header mit Counter. Warenkorb-Inhalt persistiert in localStorage (Client-side). Persistenz auch über Page-Reloads.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User fügt 2 Artikel hinzu, ändert Menge auf 3 bei einem. Erwartet: Counter zeigt 5 (2+3), Warenkorb-Seite zeigt beide Artikel mit korrekten Mengen.
2. **Edge Case:** User lädt Seite neu. Erwartet: Warenkorb-Inhalt erhalten (localStorage), Counter korrekt.
3. **Edge Case:** User entfernt alle Artikel. Erwartet: Counter=0, Warenkorb-Seite zeigt Empty-State 'Keine Artikel ausgewählt' + Link zum Katalog.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- localStorage-Persistenz funktional
- Mobile: Warenkorb als Drawer/Bottom-Sheet erreichbar
---
### [F-HMS-17] Admin-Login & Equipment-Sync-Trigger
**Anforderung:** Einfacher Admin-Login (Username/Passwort, JWT-Session) für HMS-Mitarbeiter. Nach Login: Dashboard mit 'Equipment-Sync starten'-Button, Sync-Status (last sync, anzahl artikel), Sync-Log. Kein öffentlicher Zugriff auf Admin-Funktionen.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** Admin loggt sich ein, klickt 'Equipment-Sync starten'. Erwartet: Sync läuft, Progress-Indicator sichtbar, nach Abschluss: Status aktualisiert mit Datum + Anzahl.
2. **Edge Case:** Nicht-Admin versucht '/admin' aufzurufen. Erwartet: Redirect zu Login-Seite, keine Admin-Funktionen sichtbar.
3. **Edge Case:** Falsches Passwort. Erwartet: Fehlermeldung 'Ungültige Anmeldedaten', keine Session erstellt.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- JWT-Auth funktional
- Admin-Routen geschützt
---
### [F-HMS-18] 404 / Error Pages
**Anforderung:** Custom 404-Seite mit freundlicher Nachricht + Link zur Home-Seite. 500-Error-Page mit allgemeiner Fehlermeldung. Keine raw Stack-Traces im Production-Modus.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** User navigiert zu '/nicht-existent'. Erwartet: 404-Seite mit 'Seite nicht gefunden' + Link zu Home.
2. **Edge Case:** Server-Fehler tritt auf. Erwartet: 500-Seite mit 'Etwas ist schiefgelaufen', keine Stack-Traces sichtbar.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 2 Tests grün
- Error-Pages im Branding-Design
---
### [F-HMS-19] SEO & Meta-Tags
**Anforderung:** Jede Seite hat: Title-Tag, Meta-Description, OpenGraph-Tags, Canonical-URL. Sitemap.xml generiert. robots.txt vorhanden. Structured Data (JSON-LD) für LocalBusiness auf Home-Seite. SSR/SSG für Crawler-Indexierung.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** Crawler ruft '/' auf. Erwartet: Vollständiger HTML mit Title, Meta-Description, OpenGraph-Tags, JSON-LD LocalBusiness.
2. **Edge Case:** Crawler ruft '/mietkatalog' auf. Erwartet: Server-side gerendert mit Equipment-Liste im HTML (nicht nur client-side JS).
3. **Verification:** '/sitemap.xml' liefert gültige XML mit allen Seiten-URLs. '/robots.txt' existiert und erlaubt Indexierung.
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- Lighthouse SEO Score >= 95
- Sitemap + robots.txt vorhanden
---
### [F-HMS-20] E-Mail-Service (Kontaktformular + Mietanfrage-Bestätigung)
**Anforderung:** Backend-E-Mail-Service der zwei Typen versendet: 1) Kontaktformular-E-Mail an info@hms-licht-ton.de, 2) Bestätigungs-E-Mail an Kunde nach Mietanfrage. SMTP-Konfiguration via Environment-Variablen. E-Mail-Templates in HTML + Text.
**Test Scenarios (Pflicht, mind. 2):**
1. **Happy Path:** Kontaktformular wird abgeschickt. Erwartet: E-Mail an info@hms-licht-ton.de mit Formulardaten, Absender ist Formular-E-Mail (Reply-To).
2. **Happy Path:** Mietanfrage erfolgreich an Rentman gesendet. Erwartet: Bestätigungs-E-Mail an Kunde mit Referenz-Nummer und Artikel-Liste.
3. **Edge Case:** SMTP-Server nicht erreichbar. Erwartet: E-Mail in Retry-Queue, Admin-Benachrichtigung, keine Fehlermeldung an User (smooth fallback).
**Akzeptanzkriterium:**
- Build erfolgreich
- Alle 3 Tests grün
- E-Mail-Empfang manuell verifiziert
- SMTP via Env-Vars konfiguriert
---
## 4. Rentman-Integration-Spezifikation
### 4.1 Equipment-Import (Lese-Richtung)
| Parameter | Wert |
|-----------|-------|
| **Endpoint** | `GET /equipment` |
| **Auth** | Bearer Token (JWT) |
| **Pagination** | `limit=100`, `offset` iterieren bis `data` leer |
| **Frequenz** | Cron alle 6h + manueller Admin-Trigger |
| **Speicherung** | Lokale PostgreSQL-Tabelle `equipment_cache` |
**Datenfluss:**
```
Rentman API -> Backend (GET /equipment paginated) -> PostgreSQL (equipment_cache) -> Backend API -> Frontend
```
**Relevante Felder (zu ermitteln via GET /equipment/{id}):**
- `id`, `name`, `number`
- Kategorie/Gruppe (Feldname in Rentman API)
- Beschreibung/Specs
- Bilder/Bild-URLs
- Mietpreis/Tagessatz
### 4.2 Mietanfrage-Übermittlung (Schreib-Richtung)
| Schritt | Endpoint | Zweck |
|----------|----------|-------|
| 1 | `POST /projectrequests` | Anfrage mit Event- + Kontaktdaten erstellen |
| 2 | `POST /projectrequests/{id}/projectrequestequipment` | Equipment pro Artikel hinzufügen |
**POST /projectrequests Body (gemappt aus Frontend-Formular):**
```json
{
"name": "{veranstaltungsname}",
"planperiod_start": "{datum_von}T08:00:00+02:00",
"planperiod_end": "{datum_bis}T02:00:00+02:00",
"usageperiod_start": "{datum_von}T18:00:00+02:00",
"usageperiod_end": "{datum_bis}T23:59:00+02:00",
"contact_name": "{firma_oder_name}",
"contact_person_first_name": "{vorname}",
"contact_person_lastname": "{nachname}",
"contact_person_email": "{email}",
"location_name": "{veranstaltungsort}",
"location_mailing_street": "{strasse}",
"location_mailing_number": "{hausnummer}",
"location_mailing_postalcode": "{plz}",
"location_mailing_city": "{ort}",
"location_mailing_country": "Deutschland",
"remark": "{nachricht}"
}
```
**POST /projectrequests/{id}/projectrequestequipment Body (pro Artikel):**
```json
{
"name": "{equipment_name}",
"quantity": {menge},
"quantity_total": {menge},
"unit_price": {mietpreis_oder_0},
"linked_equipment": "/equipment/{equipment_id}"
}
```
### 4.3 Fehlerbehandlung
- Rentman API nicht erreichbar -> Retry-Queue (exponential backoff, max 5 retries)
- Partial-Failure (projectrequests OK, equipment failed) -> Retry nur für fehlgeschlagene Equipment-POSTs
- Admin-E-Mail-Notification bei permanentem Failure
- User bekommt keine Fehlermeldung (smooth fallback: 'Anfrage eingegangen, wird bearbeitet')
---
## 5. Nicht-funktionale Anforderungen
### 5.1 Performance
- Page-Load < 2s auf 3G (Lighthouse Mobile Score >= 90)
- API-Response < 500ms für Equipment-Liste (gecached)
- Bilder: WebP/AVIF Format, lazy-loading, responsive sizes
- Backend: Redis-Cache für Equipment-Liste (TTL 1h)
### 5.2 Mobile-First
- Alle Seiten für 375px Breite optimiert
- Touch-Targets min 44x44px
- Keine horizontal-scrolls auf Mobile
- Burger-Menu mit Slide-in Animation
- Galerie: 1-2 Spalten auf Mobile
### 5.3 Accessibility
- WCAG 2.1 Level AA angestrebt
- Keyboard-Navigation funktional auf allen Seiten
- Alt-Texte für alle Bilder
- Kontrast min 4.5:1 (Grau-Schema muss geprüft werden)
- ARIA-Labels für interaktive Elemente
### 5.4 SEO
- SSR/SSG (Server-Side Rendering oder Static Generation)
- Semantic HTML (header, nav, main, section, footer)
- Meta-Tags pro Seite
- Sitemap.xml + robots.txt
- JSON-LD LocalBusiness
### 5.5 Security
- HTTPS-only (TLS via Coolify/Traefik)
- CSRF-Schutz für alle Formulare
- Input-Validation serverseitig (Pydantic/Zod)
- Rentman-API-Token in Environment-Variablen (nie im Frontend)
- Rate-Limiting für Kontaktformular + Mietanfrage (max 5/min)
- Admin-Login: JWT mit HttpOnly-Cookie, 24h Expiry
- Keine sensiblen Daten im localStorage (nur Warenkorb-IDs)
---
## 6. Technologie-Empfehlungen
### 6.1 Frontend
- **Framework:** Nuxt 3 (Vue 3, SSR/SSG, SEO-friendly, Mobile-First)
- **Styling:** Tailwind CSS (Utility-First, Mobile-First Breakpoints)
- **State:** Pinia (Vue Store) für Warenkorb + UI-State
- **Icons:** Lucide Icons oder Heroicons
- **Bildergalerie:** Eigene Lightbox-Komponente oder PhotoSwipe
**Begründung Nuxt 3:** SSR für SEO, Vue 3 für reaktive UI, eingebauter Router, SSG-Mode für statische Seiten (Home, Referenzen, Impressum, DSGVO, AGB), SSR für dynamische Seiten (Mietkatalog).
### 6.2 Backend
- **Framework:** FastAPI (Python, async, OpenAPI auto-docs)
- **ORM:** SQLAlchemy + Alembic (Migrations)
- **Database:** PostgreSQL (Equipment-Cache, Sync-Log)
- **Cache:** Redis (Equipment-Liste, Rate-Limiting)
- **Task Queue:** Celery oder arq (Equipment-Sync, E-Mail-Versand, Rentman-Retry)
- **Auth:** JWT (python-jose) für Admin-Login
- **E-Mail:** FastAPI-Mail oder smtplib + Jinja2-Templates
**Begründung FastAPI:** Rentman Python-Client bereits vorhanden, async für API-Calls, automatische OpenAPI-Doku, Pydantic für Validation.
### 6.3 Deployment
- **Platform:** Coolify (Docker) auf coolify-01 (46.225.91.159)
- **Container:** Frontend (Nuxt), Backend (FastAPI), PostgreSQL, Redis
- **TLS:** Let's Encrypt via Traefik
- **Domain:** hms-licht-ton.de (bestehende Domain übernehmen)
- **Environments:** dev, staging, prod
### 6.4 Rentman-Integration
- **Client:** RentmanAPI Python-Client aus Plugin
- **Token:** Environment-Variable `RENTMAN_API_TOKEN`
- **Base URL:** `https://api.rentman.net/`
---
## 7. Discovery-Checkliste (20 Kategorien)
| # | Kategorie | Status | Entscheidung |
|---|-----------|--------|--------------|
| 1 | **Auth** | ja | Admin-Login (JWT) für Equipment-Sync. Kein User-Login für öffentliche Seiten. |
| 2 | **Daten** | ja | Equipment-Cache in PostgreSQL, Validierung via Pydantic, Pagination (limit=100), Search/Filter im Frontend. |
| 3 | **Fehler** | ja | Custom 404/500 Pages, Toast-Notifications, Error-Logging im Backend, Retry-Queue für Rentman. |
| 4 | **Skalierung** | später | Kleinunternehmen, moderater Traffic. Redis-Cache reicht. Horizontal Scaling post-MVP. |
| 5 | **Sicherheit** | ja | CSRF-Schutz, Input-Validation, Rentman-Token in Env-Vars, Rate-Limiting, HTTPS-only. |
| 6 | **UX** | ja | Loading-States (Skeletons), Empty-States (keine Artikel), Toast-Notifications, Warenkorb-Feedback. |
| 7 | **Infrastruktur** | ja | Health-Checks (/health endpoint), Structured Logging, Backup via Coolify, Monitoring später. |
| 8 | **Multi-User** | nein | Single-Tenant, keine gleichzeitigen Edit-Operationen. Nur Admin-Sync ist singular. |
| 9 | **Migration** | ja | Content von alter Website manuell übernehmen. Equipment aus Rentman importieren. Bilder von alter Website sichern. |
| 10 | **Mobile** | ja | Mobile-First Design, 375px Baseline, Touch-Targets 44px, Burger-Menu, Responsive Galerie. |
| 11 | **Integration** | ja | Rentman API (Equipment-Import + Project Requests), SMTP (E-Mail), Social Links (Facebook, Instagram). |
| 12 | **Compliance** | ja | DSGVO: Datenschutzerklärung, DSGVO-Einwilligung bei Formularen, Impressum, AGB Vermietung. |
| 13 | **Performance** | ja | Lighthouse >= 90, Redis-Cache, WebP-Bilder, SSR/SSG, Lazy-Loading. |
| 14 | **i18n** | nein | Deutsch only. Keine Mehrsprachigkeit geplant. |
| 15 | **Accessibility** | ja | WCAG 2.1 AA angestrebt, Keyboard-Nav, Alt-Texte, Kontrast 4.5:1, ARIA-Labels. |
| 16 | **Analytics** | später | Post-MVP. Google Analytics oder Plausible können später hinzugefügt werden. |
| 17 | **Environments** | ja | Dev/Staging/Prod. Env-Vars für: RENTMAN_API_TOKEN, SMTP_CREDENTIALS, DATABASE_URL, JWT_SECRET. |
| 18 | **Dokumentation** | ja | README.md, API-Docs (FastAPI OpenAPI auto), Admin-Docs (Sync-Workflow), Deploy-Docs (Coolify). |
| 19 | **Testing** | ja | Frontend: Vitest (Unit), Playwright (E2E). Backend: Pytest (Unit + Integration). Coverage-Target: 80%. |
| 20 | **Naming/Branding** | ja | 'HMS Licht & Ton', Domain hms-licht-ton.de, Grautöne + Orange, SVG-Logo übernommen. |
---
## 8. Constraints
| Constraint | Wert |
|-----------|------|
| **Frontend Framework** | Nuxt 3 (Vue 3 + Tailwind CSS) |
| **Backend Framework** | FastAPI (Python) |
| **Database** | PostgreSQL |
| **Cache** | Redis |
| **Task Queue** | Celery oder arq |
| **Deployment** | Coolify (Docker) auf coolify-01 |
| **Domain** | hms-licht-ton.de |
| **Rentman API** | https://api.rentman.net/ (Bearer Token) |
| **SMTP** | via Env-Vars konfiguriert |
| **TLS** | Let's Encrypt via Traefik |
| **Environments** | Dev, Staging, Prod |
| **Coding Style** | Frontend: Vue 3 Composition API, script setup, TypeScript. Backend: PEP 8, async/await, Pydantic models. |
| **Testing** | Vitest + Playwright (Frontend), Pytest (Backend), Coverage >= 80% |
| **CI/CD** | Forgejo Actions (Build, Test, Deploy via Coolify) |
---
## 9. Annahmen
1. Die bestehende SVG-Logo-Datei von hms-licht-ton.de ist verfügbar und kann übernommen werden
2. Rentman-API-Token wird vom User bereitgestellt und in Env-Vars konfiguriert
3. SMTP-Zugangsdaten werden vom User bereitgestellt
4. Die AGB-Vermietung-Texte werden vom User als Text/Markdown bereitgestellt
5. Die Referenz-Bilder werden vom User als Dateien bereitgestellt (nicht von alter Website gecrawlt)
6. Die Domain hms-licht-ton.de kann auf den neuen Server umgezogen werden (DNS)
7. Rentman API unterstützt die dokumentierten Endpunkte (projectrequests, equipment)
8. Equipment-Artikel in Rentman haben Bilder und Beschreibungen (falls nicht, Fallback-Placeholder)
9. Das alte WordPress kann nach Go-Live abgeschaltet werden
10. Google Maps Einbindung via Link (keine API-Key benötigt für 'Route planen')
---
## 10. Non-Goals
1. **Kein Online-Shop** keine Kauf-Funktion, keine Zahlungsverarbeitung, keine Warenkorb-Checkout-Funktion
2. **Kein CMS/News-System** keine Redaktionsoberfläche, kein Blog, keine News-Artikel
3. **Keine 'Neu in der Vermietung' Sektion** entfällt explizit
4. **Keine 'AGB Shop' Seite** entfällt (nur AGB Vermietung)
5. **Keine WordPress-Weiterentwicklung** vollständiger Neuaufbau
6. **Keine Benutzerregistrierung** keine Kunden-Accounts, keine Login-Pflicht für öffentliche Seiten
7. **Keine Echtzeit-Verfügbarkeit** keine Live-Abfrage von Equipment-Verfügbarkeit (post-MVP)
8. **Keine Preisberechnung** keine automatische Kostenkalkulation im Frontend (HMS erstellt Angebot in Rentman)
9. **Keine Mehrsprachigkeit (i18n)** Deutsch only
10. **Keine Mobile App** responsive Web-App reicht
11. **Keine Analytics/Tracking** post-MVP
12. **Keine komplexe Suche** keine Elasticsearch/Fuzzy-Search (post-MVP)
---
## 11. Offene Fragen
1. **Rentman API-Token:** Wird vom User bereitgestellt? Welche Berechtigungen (read equipment, write projectrequests)?
2. **Equipment-Felder:** Welche Felder sind im Rentman equipment-Objekt verfügbar (Kategorie, Bilder, Specs)? Ggf. GET /equipment/{id} testen.
3. **AGB-Texte:** Stellt der User die AGB Vermietung als Text/Markdown bereit?
4. **Referenz-Bilder:** Stellt der User die Bilder als Dateien bereit? Wie viele Bilder?
5. **SMTP:** Welcher SMTP-Server? Zugangsdaten?
6. **Logo-SVG:** Ist das SVG von der alten Website direkt verfügbar? URL: /wp-content/uploads/2020/06/Logo-Transparent.svg
7. **USt-IdNr:** Für Impressum benötigt wird vom User bereitgestellt?
8. **Domain-Umzug:** Wann wird DNS auf neuen Server umgeleitet?
9. **Rentman Equipment-Kategorien:** Wie sind Kategorien strukturiert? Eigene Felder oder nested objects?
10. **Mietpreise:** Soll der Mietpreis im Katalog angezeigt werden? Oder nur auf Anfrage?
---
## 12. Test-Coverage Summary
| Feature ID | Feature Name | Test Scenarios | Status |
|------------|-------------|----------------|--------|
| F-HMS-01 | Home / Startseite | 3 | OK |
| F-HMS-02 | Referenzen / Bildergalerie | 3 | OK |
| F-HMS-03 | Kontaktseite mit Formular | 3 | OK |
| F-HMS-04 | Mietkatalog Equipment-Liste | 3 | OK |
| F-HMS-05 | Mietkatalog Equipment-Detailansicht | 3 | OK |
| F-HMS-06 | Mietkatalog Search & Filter | 3 | OK |
| F-HMS-07 | Mietkatalog Mietanfrage-Formular | 3 | OK |
| F-HMS-08 | Rentman Equipment-Import | 3 | OK |
| F-HMS-09 | Rentman Mietanfrage-Übermittlung | 3 | OK |
| F-HMS-10 | Navigation / Header | 3 | OK |
| F-HMS-11 | Footer | 3 | OK |
| F-HMS-12 | Impressum Seite | 2 | OK |
| F-HMS-13 | DSGVO Seite | 2 | OK |
| F-HMS-14 | AGB Vermietung Seite | 2 | OK |
| F-HMS-15 | Logo & Branding Integration | 3 | OK |
| F-HMS-16 | Anfrage-Warenkorb | 3 | OK |
| F-HMS-17 | Admin-Login & Equipment-Sync | 3 | OK |
| F-HMS-18 | 404 / Error Pages | 2 | OK |
| F-HMS-19 | SEO & Meta-Tags | 3 | OK |
| F-HMS-20 | E-Mail-Service | 3 | OK |
**Total: 20/20 Features mit Test-Szenarien**
---
## 13. Handoff Summary
DISCOVERY_CHECK: categories=20/20, features_with_ids=20/20, test_scenarios=20/20, constraints=Y, non_goals=Y, domain=Y, ready_for_ui=Y
- **requirements status:** COMPLETE 20 Features, 20/20 mit Test-Szenarien, 20/20 Kategorien beantwortet
- **test coverage:** 20/20 Features haben Test-Szenarien
- **missing_test_scenarios:** keine
- **open questions:** 10 (siehe §11)
- **assumptions:** 10 (siehe §9)
- **non-goals:** 12 (siehe §10)
- **ready_for_ui:** YES
- **ready_for_architecture:** NO (erst nach UI Design Approval)