feat: Absender-Zuordnung kann nach Waehrung unterscheiden
Revolut verschickt fuer eine Zahlung in Euro und eine in Franken dieselbe Mail vom selben Absender. Ohne die Waehrung als Kriterium landete alles auf demselben Konto. Die Erkennung liest die Waehrung ohnehin aus; sie wird jetzt VOR der Zuordnung ausgewertet und ist ein optionales Filterkriterium. Zuordnungen mit Waehrung werden zuerst geprueft – wer neben ein allgemeines "revolut" ein genaues "revolut + EUR" stellt, meint das genaue, unabhaengig von der Anlagereihenfolge. Uebergangene Mails melden ausserdem die erkannte Waehrung mit, damit beim Einrichten sichtbar ist, welcher Wert zu filtern waere. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -339,3 +339,63 @@ def test_zuordnung_laesst_sich_aendern_und_loeschen(admin):
|
||||
assert admin.delete(f"/api/mail/senders/{a['id']}").status_code == 204
|
||||
uebrig = admin.get(f"/api/mail/sources/{quelle['id']}/senders").json()
|
||||
assert not [x for x in uebrig if x["id"] == a["id"]]
|
||||
|
||||
|
||||
def test_waehrung_entscheidet_ueber_das_konto(admin, monkeypatch):
|
||||
"""Revolut schickt für Euro und Franken dieselbe Mail vom selben Absender.
|
||||
|
||||
Erst die erkannte Währung sagt, auf welches der beiden Revolut-Konten die
|
||||
Zahlung gehört – ohne dieses Kriterium landet alles auf demselben.
|
||||
"""
|
||||
eur = _konto(admin, name="Revolut Euro", currency="EUR")
|
||||
chf = _konto(admin, name="Revolut CHF", currency="CHF")
|
||||
quelle = _postfach(admin)
|
||||
admin.post(f"/api/mail/sources/{quelle['id']}/senders", json={
|
||||
"from_contains": "revolut", "currency": "EUR", "account_id": eur["id"]})
|
||||
admin.post(f"/api/mail/sources/{quelle['id']}/senders", json={
|
||||
"from_contains": "revolut", "currency": "CHF", "account_id": chf["id"]})
|
||||
|
||||
def mail(message_id: str, betrag: str, waehrung: str) -> bytes:
|
||||
return (
|
||||
f"From: Revolut <no-reply@revolut.com>\n"
|
||||
f"To: kundin@example.com\n"
|
||||
f"Date: Sat, 01 Aug 2026 10:41:51 +0000\n"
|
||||
f"Message-Id: <{message_id}@example.invalid>\n"
|
||||
f"Subject: Zahlung\n"
|
||||
f"Content-Type: text/plain; charset=utf-8\n"
|
||||
f"\nDu hast Geld gesendet.\nGesendet\n{betrag} {waehrung}\nAn\nAlex Muster\n"
|
||||
).encode("utf-8")
|
||||
|
||||
monkeypatch.setattr(mail_import, "_verbinden",
|
||||
lambda q: FakeImap([mail("waehrung-eur", "324.00", "EUR"),
|
||||
mail("waehrung-chf", "50.00", "CHF")]))
|
||||
assert admin.post(f"/api/mail/sources/{quelle['id']}/fetch").json()["neu"] == 2
|
||||
|
||||
eintraege = admin.get("/api/inbox").json()
|
||||
in_eur = [e for e in eintraege if e["amount_cents"] == -32400]
|
||||
in_chf = [e for e in eintraege if e["amount_cents"] == -5000]
|
||||
assert in_eur and in_eur[0]["account_id"] == eur["id"], "EUR gehört aufs Euro-Konto"
|
||||
assert in_chf and in_chf[0]["account_id"] == chf["id"], "CHF gehört aufs Franken-Konto"
|
||||
|
||||
|
||||
def test_zuordnung_mit_waehrung_schlaegt_die_allgemeine(admin, monkeypatch):
|
||||
"""Wer eine genaue Regel neben eine allgemeine stellt, meint die genaue."""
|
||||
eur = _konto(admin, name="Genau EUR", currency="EUR")
|
||||
sammel = _konto(admin, name="Sammelkonto", currency="CHF")
|
||||
quelle = _postfach(admin)
|
||||
# Die allgemeine zuerst anlegen – sie darf trotzdem nicht gewinnen.
|
||||
admin.post(f"/api/mail/sources/{quelle['id']}/senders", json={
|
||||
"from_contains": "revolut", "account_id": sammel["id"]})
|
||||
admin.post(f"/api/mail/sources/{quelle['id']}/senders", json={
|
||||
"from_contains": "revolut", "currency": "EUR", "account_id": eur["id"]})
|
||||
|
||||
roh = ("From: Revolut <no-reply@revolut.com>\nTo: k@example.com\n"
|
||||
"Date: Sat, 01 Aug 2026 10:41:51 +0000\n"
|
||||
"Message-Id: <vorrang-eur@example.invalid>\nSubject: Zahlung\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"\nDu hast Geld gesendet.\nGesendet\n12.00 EUR\nAn\nAlex Muster\n").encode("utf-8")
|
||||
monkeypatch.setattr(mail_import, "_verbinden", lambda q: FakeImap([roh]))
|
||||
admin.post(f"/api/mail/sources/{quelle['id']}/fetch")
|
||||
|
||||
treffer = [e for e in admin.get("/api/inbox").json() if e["amount_cents"] == -1200]
|
||||
assert treffer and treffer[0]["account_id"] == eur["id"]
|
||||
|
||||
Reference in New Issue
Block a user