fix: Revolut-Import wertet Gebühr, Status und Währung aus
Das Revolut-Preset kannte die Spalten Gebühr/Währung/Status laut Kommentar, der Parser hat sie aber nie gelesen. Folgen: Gebühren fehlten im Saldo, stornierte (REVERTED) und schwebende Zeilen wurden mitgebucht, und Zeilen fremder Währungs-Pockets landeten 1:1 im Konto – der Saldo lief dadurch zu hoch. - Gebührenspalte mindert den Betrag (immer als Kosten) - nur Zeilen mit Status COMPLETED (oder ohne Statusspalte) sind buchbar - Zeilen in anderer Währung als das Zielkonto werden nicht gebucht - Grund wird in der Prüfansicht als Badge angezeigt (storniert / Währung) - Gebühr/Währung/Status in der Spaltenzuordnung wählbar; Revolut-Preset ergänzt - Test mit echtem Revolut-Format (Gebühr, Storno, Fremdwährung), 80 grün Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -118,3 +118,56 @@ def test_reimport_same_file_is_deduped(admin):
|
||||
again = _preview(admin, giro["id"]).json()["rows"]
|
||||
assert all(r["is_duplicate"] for r in again)
|
||||
assert sum(1 for r in again if r["include"]) == 0
|
||||
|
||||
|
||||
# --- Revolut-Besonderheiten: Gebühr, Storno, Fremdwährung ------------------
|
||||
|
||||
REVOLUT_CSV = (
|
||||
"Type,Product,Started Date,Completed Date,Description,Amount,Fee,Currency,State,Balance\n"
|
||||
"TOPUP,Current,2026-01-06 10:00:00,2026-01-06 10:00:00,Von Raiffeisen,200.00,0.00,CHF,COMPLETED,300.23\n"
|
||||
"CARD_PAYMENT,Current,2026-01-07 10:00:00,2026-01-07 10:00:00,Coop,-20.00,0.50,CHF,COMPLETED,279.73\n"
|
||||
"CARD_PAYMENT,Current,2026-01-08 10:00:00,2026-01-08 10:00:00,Storno Laden,-15.00,0.00,CHF,REVERTED,279.73\n"
|
||||
"CARD_PAYMENT,Current,2026-01-09 10:00:00,2026-01-09 10:00:00,Amazon DE,-10.00,0.00,EUR,COMPLETED,90.00\n"
|
||||
)
|
||||
|
||||
REVOLUT_MAP = json.dumps({
|
||||
"date": 3, "amount": 5, "payee": 4, "fee": 6, "currency": 7, "state": 8,
|
||||
})
|
||||
|
||||
|
||||
def _preview_revolut(admin, account_id):
|
||||
return admin.post(
|
||||
"/api/imports/preview",
|
||||
files={"file": ("revolut.csv", io.BytesIO(REVOLUT_CSV.encode("utf-8")), "text/csv")},
|
||||
data={
|
||||
"account_id": str(account_id), "delimiter": ",", "decimal_sep": ".",
|
||||
"date_format": "%Y-%m-%d %H:%M:%S", "encoding": "utf-8", "has_header": "true",
|
||||
"skip_rows": "0", "amount_mode": "signed", "column_map": REVOLUT_MAP,
|
||||
},
|
||||
).json()["rows"]
|
||||
|
||||
|
||||
def test_revolut_fee_state_and_currency(admin):
|
||||
acc = _account(admin, name="Revolut CHF", currency="CHF", opening_balance_cents=10023)
|
||||
rows = _preview_revolut(admin, acc["id"])
|
||||
assert len(rows) == 4
|
||||
|
||||
# Aufladung ohne Gebühr.
|
||||
assert rows[0]["amount_cents"] == 20000
|
||||
# Gebühr 0.50 mindert die Ausgabe: -20.00 - 0.50 = -20.50
|
||||
assert rows[1]["amount_cents"] == -2050
|
||||
# Stornierte Buchung zählt nicht.
|
||||
assert rows[2]["valid"] is False and rows[2]["include"] is False
|
||||
assert rows[2]["skip_reason"] == "state"
|
||||
# Fremdwährungs-Zeile gehört nicht in das CHF-Konto.
|
||||
assert rows[3]["valid"] is False and rows[3]["include"] is False
|
||||
assert rows[3]["skip_reason"] == "currency"
|
||||
|
||||
r = admin.post("/api/imports/commit", json={
|
||||
"account_id": acc["id"], "filename": "revolut.csv", "rows": rows,
|
||||
})
|
||||
assert r.json()["imported_count"] == 2
|
||||
|
||||
# 100.23 + 200.00 - 20.50 = 279.73 (= Balance-Spalte der Bank)
|
||||
bal = admin.get(f"/api/accounts/{acc['id']}").json()["balance_cents"]
|
||||
assert bal == 27973, bal
|
||||
|
||||
Reference in New Issue
Block a user