fix: Erkennungstext trifft nur noch an Wortgrenzen

Der Erkennungs-Text eines Kontos wurde als blosser Teilstring gesucht.
Am EUR-Konto stand „Euro" – der steckt auch in „PayPal Europe",
„Europa-Park" und „EUROBUS". Jede solche Zahlung wurde dadurch zum
Uebertrag auf dieses Konto, das Geld dort zusaetzlich gutgeschrieben und
der Saldo lief um mehr als tausend Euro daneben.

Gesucht wird jetzt nur an Wortgrenzen; eine Kartenendung wie „6543"
schlaegt damit auch nicht mehr mitten in einer laengeren Kontonummer an.
Das Kontoformular warnt zusaetzlich bei sehr kurzen Erkennungstexten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-08-21 15:31:41 +02:00
co-authored by Claude Opus 5
parent 5dbfd6abc4
commit 1e7c1ec014
5 changed files with 63 additions and 3 deletions
+37
View File
@@ -539,3 +539,40 @@ def test_remove_undone_batch_from_history(admin):
admin.delete(f"/api/imports/batches/{batch['id']}") # rückgängig machen
assert admin.delete(f"/api/imports/batches/{batch['id']}/record").status_code == 204
assert not any(b["id"] == batch["id"] for b in admin.get("/api/imports/batches").json())
KURZ_CSV = (
"Datum;Betrag;Empfaenger;Zweck;GegenIBAN\n"
"05.03.2026;-48,97;PayPal Europe S.a.r.l.;Lastschrift;\n"
"06.03.2026;-30,00;Europa-Park;Eintritt;\n"
"07.03.2026;-24,50;TWINT EUROBUS AG;Einkauf;\n"
"08.03.2026;-200,00;Umbuchung;Uebertrag Euro Konto;\n"
)
def test_kurzer_erkennungstext_trifft_nicht_mitten_im_wort(admin):
"""Ein kurzer Erkennungs-Text darf nicht als blosser Teilstring greifen.
Am EUR-Konto stand als Erkennungs-Text „Euro". Weil er ungeprüft als
Teilstring gesucht wurde, wurden „PayPal Europe", „Europa-Park" und
„EUROBUS" zu Überträgen auf dieses Konto – das Geld landete dort zusätzlich
und der Saldo lief weit daneben. Nur ein eigenständiges Wort zählt.
"""
giro = _account(admin, name="Giro CHF", currency="CHF")
_account(admin, name="Euro Konto", currency="EUR",
identifiers=[{"kind": "text", "value": "Euro"}])
r = admin.post(
"/api/imports/preview",
files={"file": ("k.csv", io.BytesIO(KURZ_CSV.encode("utf-8")), "text/csv")},
data={"account_id": str(giro["id"]), "delimiter": ";", "decimal_sep": ",",
"date_format": "%d.%m.%Y", "encoding": "utf-8", "has_header": "true",
"skip_rows": "0", "amount_mode": "signed", "column_map": COLMAP},
)
assert r.status_code == 200, r.text
typ = {row["payee"]: row["type"] for row in r.json()["rows"]}
assert typ["PayPal Europe S.a.r.l."] == "expense"
assert typ["Europa-Park"] == "expense"
assert typ["TWINT EUROBUS AG"] == "expense"
# Als eigenständiges Wort greift der Erkennungs-Text weiterhin.
assert typ["Umbuchung"] == "transfer"