# 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]]