Files
Vorrania/backend/tests/test_warranty.py
Scarriffle c8c1686395 Amazon-Kaufdatum erkennen; Preis-Vorschlaege beim Anlegen; Lagerort-Dropdowns mit Pfad
1) Beleganalyse erkennt Datumsangaben mit Monatsnamen (DE+EN, z.B. Amazon 'Bestelldatum 29 April 2026'), nicht nur 29.04.2026 - so wird das Kaufdatum solcher Rechnungen gefunden. 2) Beim direkten Anlegen eines Einzelstuecks mit Beleg werden jetzt alle erkannten Preise als Vorschlag angeboten (Dropdown), statt stillschweigend nur den wahrscheinlichsten zu nehmen. 3) Alle Lagerort-Dropdowns zeigen den vollen Pfad (Hedingen -> Keller -> Schublade 1) statt nur den Namen, damit gleichnamige Orte unterscheidbar sind.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 13:24:08 +02:00

169 lines
5.5 KiB
Python

"""Lokale Garantieende-Schätzung aus Belegtext (ohne echtes PDF)."""
from datetime import date
from app.services.warranty import (
guess_acquired_on,
guess_price_candidates,
guess_price_cents,
guess_shop,
guess_warranty_until,
)
def test_zeitraum_plus_kaufdatum_vom_stueck():
# Beleg nennt nur den Zeitraum; das Kaufdatum kommt vom Einzelstück.
text = "Vielen Dank für Ihren Einkauf. 24 Monate Garantie auf dieses Gerät."
assert guess_warranty_until(text, acquired_on=date(2024, 3, 31)) == date(2026, 3, 31)
def test_jahre_werden_verstanden():
text = "2 Jahre Gewährleistung"
assert guess_warranty_until(text, acquired_on=date(2023, 1, 15)) == date(2025, 1, 15)
def test_zeitraum_plus_rechnungsdatum_aus_dem_beleg():
text = "Rechnungsdatum: 05.06.2024\nGarantie: 12 Monate"
assert guess_warranty_until(text) == date(2025, 6, 5)
def test_warranty_keyword_before_period_english():
text = "Warranty period is 36 months from purchase."
assert guess_warranty_until(text, acquired_on=date(2022, 2, 1)) == date(2025, 2, 1)
def test_explizites_datum_neben_stichwort():
text = "Garantie gültig bis 31.12.2027."
assert guess_warranty_until(text) == date(2027, 12, 31)
def test_ohne_hinweise_kein_vorschlag():
assert guess_warranty_until("Nur ein Kassenbon ohne alles.") is None
def test_leerer_text_ist_none():
assert guess_warranty_until("", acquired_on=date(2024, 1, 1)) is None
# ---- Preis ----
def test_preis_nahe_total_stichwort():
text = "Artikel 49.00\nVersand 5.90\nGesamtbetrag: 54.90 CHF"
assert guess_price_cents(text) == 5490
def test_preis_mit_tausendertrenner_apostroph():
text = "Total CHF 1'299.00"
assert guess_price_cents(text) == 129900
def test_preis_deutsches_format():
text = "Rechnungsbetrag 1.299,00 EUR"
assert guess_price_cents(text) == 129900
def test_preis_ohne_waehrung_und_ohne_stichwort_ist_none():
# Reine Zahlen ohne Waehrung/Summen-Stichwort werden NICHT als Preis geraten.
assert guess_price_cents("Position A 12,90\nPosition B 199,00\nDanke.") is None
def test_preis_mit_waehrung_ohne_stichwort_nimmt_groessten():
text = "Kabel 12.90 CHF\nGeraet 199.00 CHF"
assert guess_price_cents(text) == 19900
def test_datum_wird_nicht_als_preis_gelesen():
assert guess_price_cents("Garantie gültig bis 31.12.2027.") is None
assert guess_price_candidates("Kaufdatum 05.06.2024, Garantie bis 31.12.2027") == []
def test_preis_ohne_betrag_ist_none():
assert guess_price_cents("Kein Preis hier.") is None
assert guess_price_cents("") is None
def test_preis_kandidaten_bester_zuerst_ohne_dubletten():
text = "Artikel 49.00 CHF\nVersand 5.90 CHF\nGesamtbetrag: 54.90 CHF\nnochmal 49.00 CHF"
kandidaten = guess_price_candidates(text)
assert kandidaten[0] == 5490 # bester Tipp (Summe) vorne
assert set(kandidaten) == {5490, 4900, 590} # ohne Dubletten
assert guess_price_candidates("") == []
# ---- Kaufdatum & Shop ----
def test_kaufdatum_aus_beleg():
assert guess_acquired_on("Rechnungsdatum: 05.06.2024") == date(2024, 6, 5)
assert guess_acquired_on("nichts hier") is None
def test_kaufdatum_amazon_monatsname():
# Amazon nennt das Kaufdatum als "29 April 2026" (Monatsname statt 29.04.).
text = "Bestelldatum 29 April 2026\nBestellnummer 028-6796274-2062709"
assert guess_acquired_on(text) == date(2026, 4, 29)
def test_kaufdatum_englischer_monatsname():
assert guess_acquired_on("Invoice date: April 29, 2026") == date(2026, 4, 29)
def test_shop_erkennt_bekannten_namen():
shops = [(1, "Digitec"), (2, "Galaxus")]
assert guess_shop("Rechnung von Digitec AG, Zürich", shops) == (1, "Digitec")
def test_shop_schlaegt_neuen_namen_vor():
sid, name = guess_shop("ACME Electronics GmbH\nRechnung\nDatum 01.01.2024", [(1, "Galaxus")])
assert sid is None
assert name == "ACME Electronics GmbH"
def test_shop_ohne_text_leer():
assert guess_shop("", [(1, "Digitec")]) == (None, None)
# ---- Realer Galaxus-Beleg (vereinfacht) ----
GALAXUS = """Kaufbeleg / Rechnung Auftrag 161498087
Bestell- / Rechnungsdatum 05.10.2025
Fälligkeitsdatum 26.10.2025
Währung CHF
Delock USB2.0-Ladekabel 10079671 2 8.10% 16.56 17.90 33.12 35.80
24 Monate Garantie (06.10.2025 - 06.10.2027)
Logitech G Pro X 13489068 1 8.10% 102.68 111.00 102.68 111.00
24 Monate Garantie (06.10.2025 - 06.10.2027)
Gesamtbetrag 135.80 146.80
Gesamtbetrag enthält folgende Mehrwertsteuer:
MwSt. 8.10% 11.00
Total aller Lieferungen und Leistungen CHF 146.80
03.11.2025 Zahlung geleistet -146.80
Offener Betrag 0.00
"""
def test_galaxus_kaufdatum_nicht_faelligkeit():
assert guess_acquired_on(GALAXUS) == date(2025, 10, 5)
def test_galaxus_preis_ist_gesamt_inkl():
assert guess_price_cents(GALAXUS) == 14680
def test_galaxus_mwst_satz_ist_kein_preis():
kandidaten = guess_price_candidates(GALAXUS)
assert 810 not in kandidaten # 8.10 % ist der Steuersatz, kein Preis
assert kandidaten[0] == 14680 # bester Tipp: Gesamt inkl.
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