feat: Gegenseite eines Übertrags braucht keine eigene Transfer-Regel
Bisher musste die Regel auf BEIDEN Auszügen ein fremdes Gegenkonto liefern. Beim Empfangs-Auszug zeigt sie aber auf das Konto, das gerade importiert wird – damit blieb die Zeile ohne Gegenkonto und wurde still als Einnahme gebucht. - Gegenbuchungen werden über die Konto-Seite bestehender Transfers gesucht, nicht über das Konto-Paar. Der Empfangs-Auszug braucht damit keine Regel mehr; eine Regel auf der abgehenden Seite genügt für beide Dateien. - Trifft eine Transfer-Regel, ohne dass ein Gegenkonto feststeht, wird die Zeile nicht mehr als Einnahme/Ausgabe gebucht, sondern in der Prüfansicht mit „Gegenkonto wählen" markiert – sonst zählt die Bewegung je nach Import- Reihenfolge doppelt. - Tests für beide Reihenfolgen; 86 grün. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -321,9 +321,9 @@ def test_currency_exchange_pairs_across_statements(admin):
|
||||
chf = _account(admin, name="Rev CHF X", currency="CHF", opening_balance_cents=50000)
|
||||
eur = _account(admin, name="Rev EUR X", currency="EUR", opening_balance_cents=0)
|
||||
|
||||
# Regeln: „umgetauscht" ist ein Transfer zum jeweils anderen Konto.
|
||||
# EINE Regel genügt: „Umgetauscht in EUR" -> Gegenkonto ist das EUR-Konto.
|
||||
admin.post("/api/categories/transfer-keywords",
|
||||
json={"word": "umgetauscht", "target_account_id": eur["id"]})
|
||||
json={"word": "umgetauscht in eur", "target_account_id": eur["id"]})
|
||||
|
||||
# 1) CHF-Auszug: Umtausch geht als Transfer CHF -> EUR raus.
|
||||
rows = _rev_preview(admin, chf["id"], CHF_UMTAUSCH)
|
||||
@@ -333,9 +333,8 @@ def test_currency_exchange_pairs_across_statements(admin):
|
||||
admin.post("/api/imports/commit", json={"account_id": chf["id"], "filename": "chf.csv", "rows": rows})
|
||||
assert admin.get(f"/api/accounts/{chf['id']}").json()["balance_cents"] == 40000
|
||||
|
||||
# 2) EUR-Auszug: dieselbe Bewegung – trotz anderem Betrag als Gegenbuchung erkannt.
|
||||
admin.post("/api/categories/transfer-keywords",
|
||||
json={"word": "umgetauscht", "target_account_id": chf["id"]})
|
||||
# 2) EUR-Auszug: OHNE weitere Regel – die Gegenseite wird über den bereits
|
||||
# gebuchten Transfer erkannt, obwohl der Betrag in EUR ein anderer ist.
|
||||
rows2 = _rev_preview(admin, eur["id"], EUR_UMTAUSCH)
|
||||
assert rows2[0]["type"] == "transfer"
|
||||
assert rows2[0]["is_counterpart"] is True, "Umtausch-Gegenseite muss erkannt werden"
|
||||
@@ -348,3 +347,24 @@ def test_currency_exchange_pairs_across_statements(admin):
|
||||
assert admin.get(f"/api/accounts/{eur['id']}").json()["balance_cents"] == 10642
|
||||
# CHF-Seite bleibt unverändert.
|
||||
assert admin.get(f"/api/accounts/{chf['id']}").json()["balance_cents"] == 40000
|
||||
|
||||
|
||||
def test_exchange_arrival_without_source_asks_instead_of_booking(admin):
|
||||
"""Wird der Empfangs-Auszug zuerst eingelesen, ist die Quelle noch unbekannt.
|
||||
Die Zeile darf dann NICHT still als Einnahme durchgehen, sondern fragt das
|
||||
Konto ab – sonst zählt die Bewegung später doppelt."""
|
||||
chf = _account(admin, name="Rev CHF Y", currency="CHF", opening_balance_cents=50000)
|
||||
eur = _account(admin, name="Rev EUR Y", currency="EUR")
|
||||
admin.post("/api/categories/transfer-keywords",
|
||||
json={"word": "umgetauscht in eur", "target_account_id": eur["id"]})
|
||||
|
||||
rows = _rev_preview(admin, eur["id"], EUR_UMTAUSCH)
|
||||
assert rows[0]["type"] == "transfer"
|
||||
assert rows[0]["to_account_id"] is None
|
||||
assert rows[0]["needs_target"] is True
|
||||
assert rows[0]["include"] is False, "ohne Gegenkonto nicht automatisch buchen"
|
||||
|
||||
r = admin.post("/api/imports/commit", json={"account_id": eur["id"], "filename": "e.csv", "rows": rows})
|
||||
assert r.json()["imported_count"] == 0
|
||||
assert admin.get(f"/api/accounts/{eur['id']}").json()["balance_cents"] == 0
|
||||
assert chf # Quellkonto bleibt unberührt
|
||||
|
||||
Reference in New Issue
Block a user