diff --git a/backend/app/services/csv_import.py b/backend/app/services/csv_import.py index 8138c73..9dd51c0 100644 --- a/backend/app/services/csv_import.py +++ b/backend/app/services/csv_import.py @@ -288,7 +288,7 @@ COUNTERPART_DAYS = 5 # damit er noch als dieselbe Bewegung gilt. Bei einem Währungstausch rechnen wir # mit dem EZB-Kurs, die Bank nutzt ihren eigenen – ein paar Prozent Unterschied # sind normal, eine andere Buchung liegt praktisch nie so nah. -COUNTERPART_TOLERANCE = 0.10 +COUNTERPART_TOLERANCE = 0.20 def _find_counterpart( @@ -303,10 +303,11 @@ def _find_counterpart( Bei einem Umtausch stehen zwei Währungen und damit zwei Beträge gegenüber; dann zählt ein plausibler Betrag statt eines exakten.""" absamt = abs(amount) - unscharf = None + bester = None for eintrag in side_index.get(account.id, []): txn_id, t_date, erwartet, other_id, richtung = eintrag - if txn_id in verbraucht or abs((t_date - d).days) > COUNTERPART_DAYS: + tage = abs((t_date - d).days) + if txn_id in verbraucht or tage > COUNTERPART_DAYS: continue # Die Richtung muss stimmen: Wo Geld ankam, kann keine Ausgabe die # Gegenseite sein. Ohne diese Prüfung verschluckt eine Ausgabe über @@ -319,9 +320,18 @@ def _find_counterpart( if absamt == erwartet: return eintrag cross = waehrung.get(other_id, account.currency) != account.currency - if cross and erwartet and abs(absamt - erwartet) <= erwartet * COUNTERPART_TOLERANCE: - unscharf = unscharf or eintrag - return unscharf + if not cross or not erwartet: + continue + abweichung = abs(absamt - erwartet) / erwartet + if abweichung > COUNTERPART_TOLERANCE: + continue + # Den BESTEN Treffer nehmen, nicht den ersten: Liegen mehrere Umtausche + # im Zeitfenster, schnappte sonst der frühere den passenden Transfer weg + # und die eigentlich gemeinte Zeile blieb ohne Gegenstück. + rang = (tage, abweichung) + if bester is None or rang < bester[0]: + bester = (rang, eintrag) + return bester[1] if bester else None def parse_file_to_candidates(data: bytes, template: ImportTemplate) -> list[dict]: