Zuletzt aktualisiert:

HANDOFF – Lidl/HelloFresh → Grocy Tracking-System

Übergabe aus einer Cowork-Session an Claude Code. Dieses Dokument enthält den kompletten Kontext, alle technischen Fakten und den nächsten Schritt, damit nahtlos weitergearbeitet werden kann. Lies es zuerst vollständig.


1. Ziel des Projekts

Ein selbstgehostetes System (auf einem VPS mit Docker), das:

  1. Lidl-Plus-Einkäufe automatisch abruft – inkl. echter EAN pro Position.
  2. Produkte über OpenFoodFacts anreichert (Klarname, Kategorie, kcal + Makros).
  3. Alles in Grocy schreibt: Bestand, Preise, Nährwerte.
  4. Alle historischen Bons rückwirkend importiert (Preis-/Kaufhistorie).
  5. Später HelloFresh-Rezepte einbindet.
  6. Über die Grocy-API als Datenquelle für YNAB und Makro-Tracking dient.

Nutzer: Dennis. Sprache der Doku/Skripte: Deutsch. Land/Sprache Lidl: DE / de.


2. Getroffene Entscheidungen (nicht erneut hinterfragen)


3. Phasenplan & Status

Phase Inhalt Status
1 Grocy auf VPS (docker-compose, Makro-Userfields, API-Key) fertig (05.06.2026): Grocy 4.6.0 läuft, API-Key + 4 Userfields per DB angelegt & per API verifiziert. Port nur auf 127.0.0.1 + WireGuard (192.168.3.8) gebunden. Offen: Dennis ändert das admin-Passwort
2 Eigene Lidl-Integration (OAuth + Ticket-API) fertig & live verifiziert (05.06.2026): Login ok, refresh_token in .env, 467 Bons abrufbar. KEINE EAN mehr (s. Abschnitt 2) → HTML-Parser gebaut, 40/40 Bons rechnen auf den Cent (inkl. Gewichtsartikel, Rabatte, Pfandrückgabe)
3 Sync-Skript: Bon → OpenFoodFacts (Namenssuche) → Grocy gebaut & an 2 echten Bons verifiziert (05.06.2026): sync.py mit import/enrich/status, --dry-run, idempotent. Produkte mit LIDL:{artId}-Barcode, sichere OFF-Treffer mit EAN+Makros, Kategorien-Mapping per Mehrheits-Score. Offen: Mapping/Schwelle (0.75) mit Dennis feinjustieren
4 Historische Bons rückwirkend importieren fertig (05.06.2026): alle 467 Bons (Okt 2024 – Mai 2026) im „sofort verbrauchen"-Modus importiert. 1020 Produkte, 405 (40 %) automatisch sicher mit EAN+Makros, Restbestand 0, Preishistorie vollständig (z. B. Apfel grün: 77 Preispunkte)
5 HelloFresh-Anbindung Recherche ✅ (05.06.2026, s. RECHERCHE-HELLOFRESH.md + Abschnitt 9), Umsetzung offen

Unmittelbar nächster Schritt: HelloFresh-Sync bauen (Phase 5, Bauplan in RECHERCHE-HELLOFRESH.md; Dennis muss dafür einmalig das JWT aus dem Web-Login ziehen). Laufend: täglicher Cron 07:30 bucht neue Bons mit echtem Bestand; Dennis scannt unsichere Produkte nach (sync.py status listet sie) → sync.py enrich.


4. Dateien in diesem Paket

lidl-grocy/
├── HANDOFF.md            # dieses Dokument
├── README-PHASE2.md      # Anleitung zur Lidl-Integration
├── RECHERCHE-HELLOFRESH.md # Phase-5-Recherche (Endpoints, Bauplan, Risiken)
├── lidl.py               # eigene Lidl-Plus-Integration (login/tickets/fetch+Parser)
├── sync.py               # Phase 3: Bons -> OFF-Namenssuche -> Grocy (import/enrich/status)
├── sync-state.json       # lokaler Zustand (importierte Bons, artId-Mapping) – gitignored
├── .env                  # LIDL_REFRESH_TOKEN, GROCY_URL, GROCY_API_KEY – gitignored!
├── .venv/                # python3 -m venv, curl_cffi installiert
└── requirements.txt      # curl_cffi
docker-compose.yml        # (übergeordneter Ordner) Grocy, Port nur localhost+WireGuard
RUNBOOK.md                # Phase-1-Anleitung (Grocy aufsetzen) + Gesamt-Roadmap
lidl-kassenbon-2026-05-30.json  # Beispiel-Bon (aus Web-Session, OHNE EAN) als Referenz

Git-Repo liegt in /home/dennis/silverscale (branch main). Täglicher Sync: Crontab-Eintrag 07:30 (sync.py import --all, neue Bons mit echtem Bestand).


5. Technische Referenz Lidl (verifiziert)

5.1 OAuth (accounts.lidl.com)

Quelle: Quellcode von lidl-plus + OIDC-Discovery, beides geprüft.

5.2 Daten-API (Bearer-Token) – Stand Juni 2026, live verifiziert

5.3 Akamai-Schutz

accounts.lidl.com blockt python-requests (HTTP 403, TLS-Fingerprinting). Lösung: curl_cffi mit impersonate="chrome" für alle Lidl-Calls. Bereits umgesetzt.

5.4 Web- vs. App-API (wichtige Erkenntnis)


6. Technische Referenz Grocy


7. Technische Referenz OpenFoodFacts (für Phase 3)


8. Phase 3 – Bauplan (noch offen, angepasst an HTML-Realität)

Sync-Skript (sync.py), Ablauf pro Bon-Position (aus lidl.py::parse_receipt()): 1. Schlüssel ist die Lidl-Artikelnummer (artId). Pfand-Artikel („Pfand 0,25") gesondert behandeln/überspringen. 2. Grocy nach Produkt mit Barcode LIDL:{artId} suchen (so bleibt das echte EAN-Feld frei für nachgescannte EANs). - existiert → Bestand buchen (Menge, Preis, Kaufdatum). - existiert nicht → OFF-Namenssuche (search.openfoodfacts.org; die alte cgi/search.pl-API wirft oft 503!) mit Lidl-Eigenmarken-Boost (Milbona, Dulano, Freshona, Solevita, Bon Gelati, Metzgerfrisch, Alesto, Snack Day, Combino, Baresa, Vemondo, Pilos, Crivit, W5, Cien, Lupilu, Parkside …) + Konfidenz-Score. Sicherer Treffer → Name/Kategorie/Makros übernehmen, EAN als zweiten Barcode anlegen. Unsicher → Produkt nur mit Bon-Name anlegen (ohne Makros), Dennis scannt später die echte EAN per Grocy-App → Nachanreicherung (eigener enrich-Lauf, der Produkte mit echter EAN aber ohne Makros per OFF auffüllt). 3. Für historische Bons: Modus „sofort verbrauchen" (Bestand nicht dauerhaft erhöhen, aber Preis-/Kaufhistorie behalten). 4. Idempotenz: bereits importierte Bon-IDs merken (z. B. Grocy-Userfield am „Einkauf" oder lokale State-Datei), damit erneute Läufe nicht doppelt buchen. 5. Als Cron/systemd-Timer auf dem VPS täglich laufen lassen.


9. Phase 5 – HelloFresh (Recherche-Notiz)

Recherche abgeschlossen (05.06.2026) → siehe RECHERCHE-HELLOFRESH.md. Hybrid-Weg: Delivery-Liste über interne /gw/-API (manuelles JWT), Rezept-Inhalte (Zutaten, Mengen, Nährwerte) von den öffentlichen Rezeptseiten (__NEXT_DATA__-Blob, kein Token nötig). Grocy-Ziel: POST /api/objects/recipes + recipes_pos. Fragilster Teil: JWT-Ablauf. Unabhängig von der Lidl-Strecke.


10. Was NICHT mit übergeht (Cowork-spezifisch)

In der Cowork-Session wurde ein geplanter Task „lidl-plus-daily-coupons" (täglich 07:01) angelegt, der Coupons über den Browser aktiviert. Das ist Cowork-spezifisch und läuft in Claude Code nicht. Wenn Coupon-Automatisierung gewünscht ist, in Phase 2+ über die v1-Coupon-API (Abschnitt 5.2) nachbauen.


11. Offene To-dos für Claude Code (Reihenfolge)

  1. Repo anlegen, Dateien einsortieren, .gitignore für .env.
  2. Phase 1: Grocy deployen (RUNBOOK.md), Makro-Userfields + API-Key anlegen.
  3. Phase 2 live: python lidl.py login → Token; python lidl.py fetch --all → echten Bon mit codeInput verifizieren. Bei Fehlern an der Server-Antwort debuggen.
  4. Phase 3: sync.py bauen (Abschnitt 8), an wenigen Bons testen, Kategorien-Mapping mit Dennis abstimmen.
  5. Phase 4: alle Bons rückwirkend importieren (idempotent, „sofort verbrauchen").
  6. Phase 5: HelloFresh recherchieren, dann integrieren.