iOS: Kassenzettel scannen -> Lebensmittel erkennen & einlagern

Neuer Flow (Kachel im Listen-Tab): Foto aufnehmen/waehlen, Artikelbereich per
Rechteck markieren, on-device OCR (Vision, deutsch; Bild bleibt auf dem Geraet),
Zeilen an /products/match schicken. Pruefen-Liste je Zeile: Artikel-Picker
(Auto-Treffer ueber Schwellwert + eigene Lebensmittel-Suche), Menge (aus Zeile
geparst, korrigierbar), Lagerort-Dropdown + QR-Scan. Einlagern per checkInBatch,
unbekannte Zeilen werden uebersprungen; keine Neuanlage.

Backend: MatchCandidate traegt package_size/base_unit mit, damit die App die
Einheit ohne Extra-Abruf kennt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-30 18:40:10 +02:00
parent 9cc3e325bb
commit 648b8294b8
6 changed files with 488 additions and 1 deletions

View File

@@ -114,7 +114,10 @@ def match_receipt(
ergebnis.append(MatchLine(
text=text,
candidates=[
MatchCandidate(product_id=p.id, name=p.name, brand=p.brand, score=s)
MatchCandidate(
product_id=p.id, name=p.name, brand=p.brand, score=s,
package_size=p.package_size, base_unit=p.base_unit.value,
)
for p, s in treffer[:5]
],
))

View File

@@ -499,6 +499,10 @@ class MatchCandidate(BaseModel):
name: str
brand: str | None = None
score: int # 0100, Ähnlichkeit zur Kassenzeile
# Für die Einheit beim Einlagern (ganze Gebinde bzw. Basiseinheit) so muss
# die App den Artikel nicht noch einmal einzeln laden.
package_size: float | None = None
base_unit: str
class MatchLine(BaseModel):