Neuer Endpunkt ordnet OCR-Zeilen den aehnlichsten LEBENSMITTELN zu (Score 0-100, difflib + Token-/Praefix-Abgleich fuer abgekuerzte Kassennamen). Gegenstaende inkl. Verbrauchsgegenstaende bleiben aussen vor. Je Zeile die besten Treffer ueber dem Schwellwert (Request oder Einstellung receipt_match_threshold, Default 45). 3 Tests, gesamt 182 gruen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.0 KiB
Python
61 lines
2.0 KiB
Python
"""Kassenzettel-Abgleich: OCR-Zeilen den ähnlichsten Lebensmitteln zuordnen."""
|
|
|
|
import pytest
|
|
|
|
from app.models import BaseUnit, Product, Role, User
|
|
from app.routers.products import match_receipt
|
|
from app.schemas import MatchRequest
|
|
|
|
|
|
@pytest.fixture()
|
|
def user(db):
|
|
person = User(username="tester", password_hash="x", role=Role.admin)
|
|
db.add(person)
|
|
db.commit()
|
|
db.refresh(person)
|
|
return person
|
|
|
|
|
|
def test_abgekuerzte_kassenzeile_trifft_lebensmittel(db, user):
|
|
p = Product(
|
|
name="Vegane Mühlen-Schnitzel auf Basis von Soja",
|
|
base_unit=BaseUnit.gram, package_size=180,
|
|
)
|
|
db.add(p)
|
|
db.commit()
|
|
db.refresh(p)
|
|
|
|
res = match_receipt(
|
|
MatchRequest(lines=["MÜHLEN SCHNITZ", "voelliger unsinn xyz"]),
|
|
db=db, _=user,
|
|
)
|
|
# Abgekürzte Kassenzeile findet den vollen Namen mit hohem Score.
|
|
assert res[0].text == "MÜHLEN SCHNITZ"
|
|
assert res[0].candidates
|
|
assert res[0].candidates[0].product_id == p.id
|
|
assert res[0].candidates[0].score >= 70
|
|
# Unsinnszeile bleibt ohne Treffer über dem Schwellwert.
|
|
assert res[1].candidates == []
|
|
|
|
|
|
def test_nur_lebensmittel_keine_gegenstaende(db, user):
|
|
# Einzelstück-Flag -> tracking "object" -> darf nicht vorgeschlagen werden.
|
|
obj = Product(name="Powerbank Anker", base_unit=BaseUnit.piece, individual=True)
|
|
db.add(obj)
|
|
db.commit()
|
|
|
|
res = match_receipt(MatchRequest(lines=["POWERBANK ANKER"], threshold=10), db=db, _=user)
|
|
assert res[0].candidates == []
|
|
|
|
|
|
def test_schwellwert_filtert(db, user):
|
|
p = Product(name="Basmati Reis", base_unit=BaseUnit.gram, package_size=1)
|
|
db.add(p)
|
|
db.commit()
|
|
|
|
# Nur teilweise passende Zeile: bei sehr hohem Schwellwert kein Treffer.
|
|
hart = match_receipt(MatchRequest(lines=["reis lose"], threshold=99), db=db, _=user)
|
|
weich = match_receipt(MatchRequest(lines=["reis lose"], threshold=20), db=db, _=user)
|
|
assert hart[0].candidates == []
|
|
assert weich[0].candidates and weich[0].candidates[0].product_id == p.id
|