# Discounter-Preisdatenbank — Frontend & API ## Übersicht | Komponente | Technologie | Port | |------------|-------------|------| | REST-API | FastAPI + uvicorn | 8000 | | Frontend | HTML + Bootstrap 5 + Chart.js | — | | Aufruf | http://192.168.2.181:8000 | — | --- ## Dateistruktur ``` /opt/preisdb/ ├── api.py ← FastAPI Backend ├── static/ │ ├── index.html ← Hauptseite │ ├── vergleich.html ← Preisvergleich │ ├── verlauf.html ← Preisverlauf │ └── bestpreise.html ← Bestpreise /var/log/preisdb/ ├── api.log ← API-Log └── import.log ← Import-Log /etc/systemd/system/ ├── preisdb-api.service ← uvicorn Dienst └── preisdb-import.service ← Import-Dienst ``` --- ## systemd Service — API ### Datei: `/etc/systemd/system/preisdb-api.service` ```ini [Unit] Description=Discounter Preisdatenbank API After=network.target [Service] Type=simple WorkingDirectory=/opt/preisdb ExecStart=/opt/preisdb/venv/bin/uvicorn api:app --host 0.0.0.0 --port 8000 Restart=always RestartSec=5 User=root StandardOutput=append:/var/log/preisdb/api.log StandardError=append:/var/log/preisdb/api.log [Install] WantedBy=multi-user.target ``` ### Befehle ```bash systemctl start preisdb-api.service systemctl stop preisdb-api.service systemctl restart preisdb-api.service systemctl status preisdb-api.service # Log live verfolgen tail -f /var/log/preisdb/api.log journalctl -u preisdb-api.service -f ``` --- ## REST-API Endpunkte | Methode | Pfad | Beschreibung | |---------|------|-------------| | GET | `/` | Hauptseite (index.html) | | GET | `/vergleich.html` | Preisvergleich-Seite | | GET | `/verlauf.html` | Preisverlauf-Seite | | GET | `/bestpreise.html` | Bestpreise-Seite | | GET | `/api/stats` | DB-Statistiken | | GET | `/api/haendler` | Alle Händler | | GET | `/api/kategorien` | Kategorien mit Anzahl | | GET | `/api/vergleich` | Preisvergleich (Filter: kategorie_id, suchbegriff) | | GET | `/api/preisverlauf/{produkt_id}` | Preisverlauf eines Produkts | | GET | `/api/bestpreise` | Produkte unter Durchschnitt (Filter: min_eintraege) | ### Beispielaufrufe ```bash # Statistiken curl http://192.168.2.181:8000/api/stats # Preisvergleich Milch curl "http://192.168.2.181:8000/api/vergleich?suchbegriff=milch" # Preisvergleich nach Kategorie curl "http://192.168.2.181:8000/api/vergleich?kategorie_id=162" # Preisverlauf Produkt ID 1 curl http://192.168.2.181:8000/api/preisverlauf/1 # Bestpreise (mind. 3 Historieneinträge) curl "http://192.168.2.181:8000/api/bestpreise?min_eintraege=3" ``` --- ## Frontend-Seiten ### Hauptseite (index.html) - Statistiken: Angebote, Produkte, Händler, Historieneinträge - Letzter Import-Zeitstempel - 3 Cards mit Links zu den Auswertungen ### Preisvergleich (vergleich.html) - Suche nach Produktname - Filter nach Kategorie - Sortierung: Normpreis / Angebotspreis / Produktname - Tabelle mit Produktbild, Händler, Preis, Normpreis, Gültigkeit - Günstigstes Angebot pro Produkt grün markiert - Link zu Preisverlauf pro Zeile ### Preisverlauf (verlauf.html) - Produktsuche mit Autocomplete-Liste - Chart.js Liniendiagramm (Preis über Zeit, pro Händler eine Linie) - Tabelle mit allen Historieneinträgen - Direktaufruf via URL-Parameter: `verlauf.html?produkt_id=123` ### Bestpreise (bestpreise.html) - Zeigt Produkte deren aktueller Preis > 10% unter Durchschnitt liegt - Slider für Mindestanzahl Historieneinträge (2–20) - Filter nach Kategorie - Ampel-Bewertung: 🟢 > 20% unter Schnitt, 🟡 10–20%, 🔴 < 10% - ⭐ Allzeit-Tief Markierung wenn aktueller Preis = historisches Minimum > **Hinweis:** Bestpreise werden erst nach mehreren Wochen Historiedaten aussagekräftig. --- ## Produktbilder Bilder kommen direkt von marktguru — kein lokaler Speicher nötig: ``` https://img.marktguru.de/api/v1/offers/<mg_offer_id>/images/0?width=100 ``` **Einschränkung:** Bilder sind nur für aktuelle Angebote verfügbar. Abgelaufene Angebote haben möglicherweise keine Bilder mehr. --- ## Preisbewertungs-Strategie ### Aktueller Vergleich - Normpreis (`referenz_preis` in €/kg oder €/l) für fairen Vergleich - Günstigstes Angebot pro Produkt wird grün markiert ### Historienauswertung Erst nach mehreren Wochen Daten belastbar: ``` Durchschnittspreis = AVG(Preishistorie.preis) Abweichung = (aktueller_preis - avg) / avg × 100 > +10% → teuer 🔴 ± 10% → normal 🟡 < -10% → günstig 🟢 = min → Bestpreis ⭐ ``` ### Produktmatching - `mg_product_id` = marktguru-interne Produkt-ID - Gleiche `mg_product_id` bei verschiedenen Händlern = identisches Produkt - Eigenmarken haben meist unterschiedliche IDs → Vergleich via Kategorie + Normpreis --- ## Bekannte Einschränkungen | Problem | Status | |---------|--------| | `retailerId`-Filter der API ignoriert | Händlerfilter in DB | | Bilder nur für aktuelle Angebote | onerror-Handler im HTML | | Bestpreise erst nach Wochen sinnvoll | Hinweis in der UI | | EDEKA wenig Angebote bei marktguru | bekannt, keine Lösung | --- ## Nächste Schritte - [ ] Produktbilder lokal cachen (optional) - [ ] E-Mail-Benachrichtigung bei Bestpreis - [ ] Einkaufslisten-Funktion - [ ] Auswertungs-Queries dokumentieren (separate Note) --- [[Impressum|Impressum]] | [[Datenschutzerklärung|Datenschutz]]