mitai-jinkendo/.claude/docs/technical/BLS_FOOD_REFERENCE.md
Lars fa542e0fb9
All checks were successful
Deploy Development / deploy (push) Successful in 1m7s
Build Test / pytest-backend (push) Successful in 5s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 22s
feat: Listen-Dialog mit Mengen/Einheiten, Mitai ohne Kochrezepte
Roh-Kombinationen statt Rezept-Sprache; Zutaten suchen, EL/TL/Prise auf Gramm. Gekochte Gerichte und Ausbeute bleiben Tandoor.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-12 18:23:01 +02:00

3.5 KiB
Raw Blame History

BLS Food Reference technische Spec

Stand: 2026-09-12 · Migration 062 + 063

Tabellen

  • food_attributes — dynamischer Stoff-/Merkmalskatalog (attr_key, data_type, origin)
  • food_catalog — Lebensmittel (bls_code UNIQUE bei official_bls; manuell ohne BLS-Code)
  • food_attribute_values — typisiertes EAV
  • food_name_mappings — FDDB-Name → food_id (User / global)
  • nutrition_items — Tagebuchzeilen inkl. logged_at
  • nutrition_daily_nutrients — Tages-Rollup numerischer Attribute
  • nutrition_day_marksfasting | incomplete
  • food_recipes / food_recipe_ingredients — Mitai-Listen/Kombinationen (Rohmischung, kein Kochschwund); nutrition_items.recipe_id. Kein Tabellen-Rename. Gekochte Gerichte später Tandoor + cooked_yield_g, nicht hier.

Layer 1

  • data_layer/food_mapping.py — Normalisierung, Lookup, Learn, Apply, Delete
  • data_layer/nutrition_items.py — Ingest, drei Makro-Summen, Policy, resolve_*_attributes
  • data_layer/food_recipes.py — Listen-Upsert, Link auf Tagebuchzeilen, Listen-Makros (Skala: gegessen_g / Summe Zutaten, sonst 1/Portionen). Diese Skala gilt nur für Roh-Kombinationen, nicht für gekochte Gerichte.
  • bls/recipe_parser.pyprodukte-Feld: Split nur vor nächstem \d+ (g|kg|ml|l) (Kommas im Namen bleiben)

Import

BLS: Admin-Upload Components + Daten-XLSX (backend/bls/parser.py). Upsert über bls_code / attr_key, nie Delete+Insert offizieller Zeilen.

FDDB: Items persistieren; nutrition_log nur bei leerem Tag oder laut Policy / Bestätigung.

Router

  • /api/bls/* — Suche, Attribute-Suche, eigene Foods (attributes + serving_g), eigene Mappings
  • Migration 065 — Extension-Keys EPA/DHA/DPA/ALA/OMEGA3/OMEGA6 falls BLS sie nicht unter diesem Key hat
  • /api/admin/bls/* — Import, Katalog, Attribute
  • /api/admin/food-mappings — Admin-CRUD
  • /api/nutrition/* — Items, Unmapped, Bulk-Map, Marken, Konflikt-Resolve
  • GET/POST /api/nutrition/recipes, PUT/DELETE /api/nutrition/recipes/{id}, POST …/import-fddb-lists, POST …/{id}/apply
  • PUT /api/admin/food-mappings/{id} — Ziel-Lebensmittel einer bestehenden Zuordnung wechseln
  • Unmapped = Tagebuchzeilen ohne food_id/recipe_id plus Listenzutaten ohne Mapping
  • Frontend: Inline-Vorschläge auf Zuordnen (food_suggest.py: Collapse-Key ohne Leerzeichen, Index 5 Min. Cache, Fett-%-Zahlen 9,5/10), FoodSearchModal nur noch Zusatzsuche (Abort + Debounce). Listen-UI: FoodRecipeDialog (Suche gelernt + Katalog; Katalogpick upsertet Mapping). Offene Zutaten: kind=recipe_ingredient (API-Wert unverändert, UI: Listenzutat). Tandoor-Import und cooked_yield_g später, kein Connector in Phase 1.
  • Migration 066food_recipe_ingredients.quantity_amount + source_unit; quantity_g = Umrechnung (resolve_quantity in food_mapping.py). GET /bls/units = Einheitenkatalog (EL/TL/Prise/Stück, default_g).
  • GET /nutrition/unmapped?since_days=28 — nur Namen mit last_date im Fenster; count_only liefert {count, total, since_days}; POST /bls/foods/suggest-batch für sichtbare Zeilen (max. 80)
  • Mapping-Schreiben und Nährwert-Rebuild sind getrennte Transaktionen; Rebuild läuft nach der API-Antwort im Hintergrund (UI bleibt bedienbar)
  • food_name_mappings.grams_per_unit / source_unit (Migration 064)
  • GET/POST /api/nutrition/food-knowledge — portable JSON (mitai-food-knowledge v1): manuelle Foods, Mappings (über bls_code / Name, keine UUIDs), Listen. Import löst Katalog auf dem Zielsystem auf (BLS muss dort importiert sein).