Backend: Zeilenpreise als Kaufpreis-Kandidaten anbieten

Bei einer Rechnung mit mehreren Artikeln soll man den Zeilenpreis des passenden
Produkts wählen können. Die Kandidatenliste enthaelt daher wieder alle
geldartigen Betraege (Zeilen- und Summenbetraege), nur ohne MwSt-Satz und
Nicht-Geld-Zahlen; der Auto-Tipp bleibt die Gesamtsumme und steht vorne.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-27 10:45:08 +02:00
parent 88b9bdcbea
commit 4a950acd85
2 changed files with 20 additions and 10 deletions

View File

@@ -309,22 +309,23 @@ def guess_price_cents(text: str) -> int | None:
def guess_price_candidates(text: str) -> list[int]: def guess_price_candidates(text: str) -> list[int]:
"""Plausible Beträge (Rappen/Cent), bester zuerst, ohne Dubletten. """Alle geldartigen Beträge (Rappen/Cent) zur Auswahl, bester Tipp zuerst.
Nur Beträge, die nach Preis aussehen d.h. mit Währung in der Nähe oder kurz Bei einer Rechnung mit mehreren Artikeln soll man auch den Zeilenpreis des
hinter einem Summen-Stichwort. Beliebige Zahlen (Mengen, Artikelnummern, passenden Produkts wählen können deshalb kommen hier alle Beträge rein
Datumsteile) fliegen raus. So bleibt die Auswahl kurz und brauchbar. (Zeilen- und Summenbeträge). Mengen, Artikelnummern und Prozentsätze fallen
schon in :func:`_price_hits` weg. Der automatische Tipp (Gesamtsumme) steht
vorne.
""" """
if not text: if not text:
return [] return []
plausibel = { werte = {c for _pos, c, _cur in _price_hits(text)}
c for pos, c, cur in _price_hits(text) if cur or _near_total(text, pos) werte.discard(0)
} if not werte:
if not plausibel:
return [] return []
kandidaten = sorted(plausibel, reverse=True) kandidaten = sorted(werte, reverse=True)
best = guess_price_cents(text) best = guess_price_cents(text)
if best is not None and best in kandidaten: if best is not None and best in kandidaten:
kandidaten.remove(best) kandidaten.remove(best)
kandidaten.insert(0, best) kandidaten.insert(0, best)
return kandidaten[:8] return kandidaten[:12]

View File

@@ -147,3 +147,12 @@ def test_galaxus_mwst_satz_ist_kein_preis():
def test_galaxus_garantieende_aus_zeitraum(): def test_galaxus_garantieende_aus_zeitraum():
assert guess_warranty_until(GALAXUS, acquired_on=date(2025, 10, 5)) == date(2027, 10, 6) assert guess_warranty_until(GALAXUS, acquired_on=date(2025, 10, 5)) == date(2027, 10, 6)
def test_galaxus_zeilenpreise_sind_kandidaten():
# Bei mehreren Artikeln soll man den Zeilenpreis wählen können.
kandidaten = guess_price_candidates(GALAXUS)
assert 14680 in kandidaten # Gesamt inkl.
assert 11100 in kandidaten # Logitech, Betrag/Preis inkl.
assert 3580 in kandidaten # Kabel, Betrag inkl.
assert 810 not in kandidaten # MwSt-Satz weiterhin draußen