feat: Konto wird aus der Datei erkannt – ein Kurzbefehl genuegt

Bisher brauchte es je Konto einen eigenen Kurzbefehl, weil account_id
Pflicht war. Jetzt ist sie optional: Raiffeisen fuehrt die eigene IBAN in der
Datei mit (Treffer gegen die Erkennungs-Texte der Konten), Revolut die
Waehrung – zusammen mit der erkannten Bank und dem Import-Verlauf reicht das.

Bleibt es mehrdeutig, wird NICHT geraten: Ein Auszug im falschen Konto
verfaelscht zwei Salden auf einmal. Stattdessen nennt die Fehlermeldung die
Konten samt Nummern, sodass man sie im Kurzbefehl nachtragen kann. Hat der
Schluessel ein Standardkonto, gilt das.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-08-22 23:54:27 +02:00
co-authored by Claude Opus 5
parent 1b401ff358
commit e8a862bd63
5 changed files with 161 additions and 14 deletions
+48 -5
View File
@@ -319,12 +319,10 @@ def test_fehler_am_kurzbefehl_sind_im_feld_message_lesbar(admin):
kopf = {"X-Certain-Token": marke["token"]}
import io
# Datei da, aber account_id vergessen: Pflichtfeld fehlt.
r = client.post("/api/quick/statement",
files={"file": ("a.csv", io.BytesIO(b"Datum;Betrag\n"), "text/csv")},
headers=kopf)
# Gar keine Datei mitgeschickt: Pflichtfeld fehlt.
r = client.post("/api/quick/statement", data={"account_id": str(konto["id"])}, headers=kopf)
assert r.status_code == 422
assert "account_id" in r.json()["message"]
assert "file" in r.json()["message"]
assert "Formular" in r.json()["message"]
# Falsche Marke.
@@ -339,3 +337,48 @@ def test_fehler_am_kurzbefehl_sind_im_feld_message_lesbar(admin):
data={"account_id": str(konto["id"])}, headers=kopf)
assert r.status_code == 400
assert "leer" in r.json()["message"].lower()
def test_konto_wird_aus_der_datei_erkannt(admin):
"""Ein Kurzbefehl statt einer je Konto: Raiffeisen fuehrt die eigene IBAN
in der Datei mit, damit ist die Zuordnung eindeutig."""
client = _fremd()
iban = "CH43 8080 8007 9160 7106 9"
konto = _konto(admin, name="Lohnkonto IBAN", currency="CHF",
identifiers=[{"kind": "iban", "value": iban}])
# Zweites Konto derselben Waehrung, damit es etwas zu verwechseln gibt.
_konto(admin, name="Anderes CHF-Konto", currency="CHF")
marke = _marke(admin, None, name="Ohne Standardkonto " + secrets.token_hex(3))
import io
csv_text = (
"IBAN;Booked At;Text;Credit/Debit Amount;Balance;Valuta Date\n"
"CH4380808007916071069;2026-01-05 00:00:00.0;LSV Viseca;-1718.7;702.47;2026-01-05 00:00:00.0\n"
"CH4380808007916071069;2026-01-06 00:00:00.0;Coop;-42.10;660.37;2026-01-06 00:00:00.0\n"
)
r = client.post("/api/quick/statement",
files={"file": ("raiff.csv", io.BytesIO(csv_text.encode()), "text/csv")},
headers={"X-Certain-Token": marke["token"]})
assert r.status_code == 201, r.text
assert "IBAN" in r.json()["erkannt_als"]
wartend = [u for u in admin.get("/api/imports/uploads").json()
if u["filename"] == "raiff.csv"]
assert wartend and wartend[0]["account_id"] == konto["id"]
def test_unklares_konto_nennt_die_moeglichkeiten(admin):
"""Raten waere teuer: Ein Auszug im falschen Konto verfaelscht zwei Salden."""
client = _fremd()
_konto(admin, name="Erstes Konto", currency="CHF")
_konto(admin, name="Zweites Konto", currency="CHF")
marke = _marke(admin, None, name="Ratlos " + secrets.token_hex(3))
import io
r = client.post("/api/quick/statement",
files={"file": ("x.csv", io.BytesIO(
b"Datum;Betrag;Text\n01.02.2026;-5,00;Kiosk\n"), "text/csv")},
headers={"X-Certain-Token": marke["token"]})
assert r.status_code == 400
assert "account_id" in r.json()["message"]
assert "Erstes Konto" in r.json()["message"]