fix: Bankabruf verschluckte Umsaetze mit wiederkehrendem Betrag
Der Eingangs-Abgleich vergleicht Betrag und Datum mit ein paar Tagen Spielraum – bewusst unscharf, damit eine per Kurzbefehl erfasste Zahlung nicht ein zweites Mal ankommt. Er merkt sich dabei, welchen Eintrag er schon verbraucht hat. Nur ruft der Bankabruf ihn JE ZEILE einzeln auf, und damit begann diese Menge jedes Mal von vorn: Derselbe Eintrag liess sich beliebig oft verbrauchen. Bei Revolut-Aufrundungen – dreimal 1.00 in drei Tagen – kam so nur die erste an, und der Saldo wich ab, ohne dass irgendwo etwas stand. Zwei Aenderungen: - Der Aufrufer kann die Menge jetzt ueber mehrere Aufrufe mitfuehren; der Bankabruf haelt eine je Konto. - Gegen andere BANK-Eintraege wird gar nicht mehr unscharf verglichen. Zwei Umsaetze derselben Quelle sind nie Dubletten voneinander – dort entscheidet die Kennung der Bank, und die ist exakt. Dazu ein Weg zurueck: Ein verschluckter Umsatz hinterliess keinen Eintrag, der naechste Abruf haette ihn also wieder geholt – nur liegt er dann vor dem Fenster des letzten Abrufs. "Aelteres nachholen" gibt es jetzt auch je Konto, wie beim Postfach. Nachgestellt und als Test festgehalten: dreimal 1.00 in drei Tagen, alle drei kommen an, Saldo -3.00. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ from ..models import (
|
||||
Account,
|
||||
AccountIdentifier,
|
||||
InboxItem,
|
||||
InboxSource,
|
||||
InboxStatus,
|
||||
AmountMode,
|
||||
BudgetTreatment,
|
||||
@@ -663,7 +664,9 @@ def finde_eingangs_treffer(
|
||||
return beste[1] if beste else None
|
||||
|
||||
|
||||
def detect_rows(db: Session, user: User, account: Account, candidates: list[dict]) -> list[dict]:
|
||||
def detect_rows(db: Session, user: User, account: Account, candidates: list[dict], *,
|
||||
eingang_ohne: InboxSource | None = None,
|
||||
verbraucht: set[int] | None = None) -> list[dict]:
|
||||
"""Reichert Kandidaten an: Typ, Auto-Kategorie, Duplikat.
|
||||
|
||||
Wird von CSV- UND Beleg-Import genutzt (gleiche Prüf-/Buchungslogik).
|
||||
@@ -701,17 +704,24 @@ def detect_rows(db: Session, user: User, account: Account, candidates: list[dict
|
||||
# wortgleich mit dem des Auszugs, und das Buchungsdatum der Bank liegt oft
|
||||
# ein bis zwei Tage später. Deshalb wird zusätzlich unscharf verglichen –
|
||||
# gleicher Betrag, Datum in der Nähe.
|
||||
eingang = [
|
||||
(eid, edatum, ebetrag)
|
||||
for eid, edatum, ebetrag in db.query(
|
||||
InboxItem.id, InboxItem.date, InboxItem.amount_cents
|
||||
).filter(
|
||||
InboxItem.owner_id == user.id,
|
||||
InboxItem.account_id == account.id,
|
||||
InboxItem.status.in_((InboxStatus.booked, InboxStatus.discarded)),
|
||||
)
|
||||
]
|
||||
eingang_verbraucht: set[int] = set()
|
||||
frage = db.query(
|
||||
InboxItem.id, InboxItem.date, InboxItem.amount_cents
|
||||
).filter(
|
||||
InboxItem.owner_id == user.id,
|
||||
InboxItem.account_id == account.id,
|
||||
InboxItem.status.in_((InboxStatus.booked, InboxStatus.discarded)),
|
||||
)
|
||||
if eingang_ohne is not None:
|
||||
# Zwei Umsätze DERSELBEN Quelle sind nie Dubletten voneinander – dort
|
||||
# entscheidet die Kennung der Quelle, und die ist exakt. Ohne diese
|
||||
# Ausnahme verschluckt eine Zahlung über 1.00 die nächste über 1.00
|
||||
# drei Tage später, und der Saldo weicht ab.
|
||||
frage = frage.filter(InboxItem.source != eingang_ohne)
|
||||
eingang = [(eid, edatum, ebetrag) for eid, edatum, ebetrag in frage]
|
||||
# Der Aufrufer kann die Menge über mehrere Aufrufe hinweg mitführen: Der
|
||||
# Bankabruf ruft je Zeile einzeln auf, und ohne gemeinsame Menge liesse
|
||||
# sich derselbe Eintrag beliebig oft verbrauchen.
|
||||
eingang_verbraucht: set[int] = verbraucht if verbraucht is not None else set()
|
||||
seen: Counter = Counter()
|
||||
|
||||
out: list[dict] = []
|
||||
|
||||
Reference in New Issue
Block a user