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
co-authored by Claude Opus 4.8
parent 88b9bdcbea
commit 4a950acd85
2 changed files with 20 additions and 10 deletions
+11 -10
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]
+9
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