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]:
"""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
hinter einem Summen-Stichwort. Beliebige Zahlen (Mengen, Artikelnummern,
Datumsteile) fliegen raus. So bleibt die Auswahl kurz und brauchbar.
Bei einer Rechnung mit mehreren Artikeln soll man auch den Zeilenpreis des
passenden Produkts wählen können deshalb kommen hier alle Beträge rein
(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:
return []
plausibel = {
c for pos, c, cur in _price_hits(text) if cur or _near_total(text, pos)
}
if not plausibel:
werte = {c for _pos, c, _cur in _price_hits(text)}
werte.discard(0)
if not werte:
return []
kandidaten = sorted(plausibel, reverse=True)
kandidaten = sorted(werte, reverse=True)
best = guess_price_cents(text)
if best is not None and best in kandidaten:
kandidaten.remove(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():
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