test: Duplikaterkennung ueber Monatsgrenzen abgesichert
Der uebliche Ablauf ist, Mitte Monat einzulesen und Ende Monat den ganzen Monat noch einmal. Die Tests halten fest, dass bereits gebuchte Zeilen nicht erneut in den Saldo laufen, neue ankommen – und dass zwei bzw. drei echte gleich aussehende Buchungen desselben Tages erhalten bleiben. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -622,3 +622,72 @@ def test_verlauf_merkt_sich_die_bank_vorlage(admin):
|
||||
verlauf = admin.get("/api/imports/batches").json()
|
||||
meins = [b for b in verlauf if b["account_id"] == konto["id"]]
|
||||
assert meins[0]["preset"] == "Raiffeisen (CH)"
|
||||
|
||||
|
||||
def _csv(*zeilen):
|
||||
return "Datum;Betrag;Empfaenger;Zweck;GegenIBAN\n" + "".join(z + "\n" for z in zeilen)
|
||||
|
||||
|
||||
def _lies(admin, konto_id, text):
|
||||
return admin.post(
|
||||
"/api/imports/preview",
|
||||
files={"file": ("a.csv", io.BytesIO(text.encode("utf-8")), "text/csv")},
|
||||
data={"account_id": str(konto_id), "delimiter": ";", "decimal_sep": ",",
|
||||
"date_format": "%d.%m.%Y", "encoding": "utf-8", "has_header": "true",
|
||||
"skip_rows": "0", "amount_mode": "signed", "column_map": COLMAP},
|
||||
).json()
|
||||
|
||||
|
||||
def test_monatsauszug_ueber_bereits_gebuchte_zeilen_hinweg(admin):
|
||||
"""Der übliche Ablauf: Mitte Monat einlesen, Ende Monat den ganzen Monat.
|
||||
|
||||
Die bereits gebuchten Zeilen dürfen nicht erneut in den Saldo laufen, die
|
||||
neuen müssen ankommen. Zwei echte, gleich aussehende Buchungen desselben
|
||||
Tages bleiben dabei beide erhalten – sie sind kein Duplikat.
|
||||
"""
|
||||
konto = _account(admin, name="Monatskonto", currency="CHF")
|
||||
bis_18 = _csv(
|
||||
"05.08.2026;-20,00;Coop;Einkauf;",
|
||||
"12.08.2026;-7,50;Kiosk;Snack;",
|
||||
"12.08.2026;-7,50;Kiosk;Snack;", # echte zweite Buchung, kein Duplikat
|
||||
"18.08.2026;3.000,00;Arbeitgeber;Lohn;",
|
||||
)
|
||||
v = _lies(admin, konto["id"], bis_18)
|
||||
assert sum(1 for r in v["rows"] if r["include"]) == 4
|
||||
admin.post("/api/imports/commit", json={
|
||||
"account_id": konto["id"], "filename": "aug-teil.csv",
|
||||
"rows": [r for r in v["rows"] if r["include"]],
|
||||
})
|
||||
stand = lambda: admin.get(f"/api/accounts/{konto['id']}").json()["balance_cents"]
|
||||
assert stand() == 296500 # -2000 -750 -750 +300000
|
||||
|
||||
ganzer_august = bis_18 + "".join(z + "\n" for z in (
|
||||
"22.08.2026;-45,00;Migros;Einkauf;",
|
||||
"29.08.2026;-12,00;SBB;Billett;",
|
||||
))
|
||||
v2 = _lies(admin, konto["id"], ganzer_august)
|
||||
dubletten = [r for r in v2["rows"] if r["is_duplicate"]]
|
||||
neue = [r for r in v2["rows"] if r["include"]]
|
||||
assert len(dubletten) == 4, [r["payee"] for r in dubletten]
|
||||
assert [r["payee"] for r in neue] == ["Migros", "SBB"]
|
||||
|
||||
admin.post("/api/imports/commit", json={
|
||||
"account_id": konto["id"], "filename": "aug-ganz.csv",
|
||||
"rows": neue,
|
||||
})
|
||||
assert stand() == 296500 - 4500 - 1200
|
||||
|
||||
|
||||
def test_dritte_gleiche_buchung_gilt_nicht_als_dublette(admin):
|
||||
"""Kommt am selben Tag eine DRITTE gleiche Buchung dazu, ist sie echt."""
|
||||
konto = _account(admin, name="Dreimal", currency="CHF")
|
||||
zwei = _csv("03.08.2026;-5,00;Bäckerei;Brot;", "03.08.2026;-5,00;Bäckerei;Brot;")
|
||||
v = _lies(admin, konto["id"], zwei)
|
||||
admin.post("/api/imports/commit", json={
|
||||
"account_id": konto["id"], "filename": "zwei.csv",
|
||||
"rows": [r for r in v["rows"] if r["include"]]})
|
||||
|
||||
drei = zwei + "03.08.2026;-5,00;Bäckerei;Brot;\n"
|
||||
v2 = _lies(admin, konto["id"], drei)
|
||||
assert sum(1 for r in v2["rows"] if r["is_duplicate"]) == 2
|
||||
assert sum(1 for r in v2["rows"] if r["include"]) == 1
|
||||
|
||||
Reference in New Issue
Block a user