fix: Die Meldung sagt jetzt, wenn die Gegenseite schon anderweitig verbunden ist
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b1f5eb9a51
commit
14254b483e
@@ -173,6 +173,20 @@ def _pruefe_gegenseite(db: Session, user: User, konto: Account, ziel: Account,
|
||||
datum, exakt)
|
||||
if schon is None:
|
||||
return
|
||||
# Haengt die gefundene Buchung schon an einer anderen, ist sie NICHT die
|
||||
# Gegenseite dieser hier. Der Rat „verbinden" ginge dann ins Leere: Die
|
||||
# Vorschlagsliste laesst vergebene Buchungen aus, es kaeme nie ein
|
||||
# Vorschlag – und der Nutzer sucht etwas, das es nicht gibt.
|
||||
if _schon_verknuepft(db, user, schon):
|
||||
raise UebertragFehler(
|
||||
f"Auf '{ziel.name}' steht zwar eine passende Buchung vom "
|
||||
f"{schon.date.strftime('%d.%m.%Y')}, die ist aber schon mit einer "
|
||||
f"anderen Buchung verbunden – also nicht die Gegenseite dieser "
|
||||
f"hier. Verbinden geht deshalb nicht. Sieh auf '{ziel.name}' nach, "
|
||||
f"ob die vorhandene Verknüpfung stimmt, oder ob der zweite Zugang "
|
||||
f"dort schlicht fehlt.",
|
||||
nachfragen=True,
|
||||
)
|
||||
raise UebertragFehler(
|
||||
f"Auf '{ziel.name}' steht schon eine passende Buchung vom "
|
||||
f"{schon.date.strftime('%d.%m.%Y')}. Beide Seiten sind also bereits "
|
||||
|
||||
@@ -455,3 +455,61 @@ def test_verknuepfte_buchungen_landen_nicht_in_uebersprungen(admin):
|
||||
# Und sie bleibt unangetastet: kein Uebertrag, kein verschobenes Geld.
|
||||
assert admin.get(f"/api/transactions/{raus['id']}").json()["type"] == "expense"
|
||||
assert admin.get(f"/api/accounts/{pocket['id']}").json()["balance_cents"] == betrag
|
||||
|
||||
|
||||
def _tx(admin, konto, typ, datum, cents, payee):
|
||||
return admin.post("/api/transactions", json={
|
||||
"type": typ, "date": datum, "account_id": konto["id"],
|
||||
"amount_cents": cents, "payee": payee}).json()
|
||||
|
||||
|
||||
def test_vergebene_gegenseite_wird_als_solche_benannt(admin):
|
||||
"""Die Pruefung fragt „gibt es auf dem Zielkonto eine passende Buchung?",
|
||||
nicht „ist sie noch frei?". Haengt die gefundene schon an einer anderen
|
||||
Buchung, ist sie NICHT die Gegenseite dieser hier – und der Rat „verbinden"
|
||||
geht ins Leere, denn die Vorschlagsliste laesst vergebene Buchungen aus.
|
||||
Dann muss die Meldung sagen, was wirklich los ist."""
|
||||
quelle = _kto(admin, name=f"Revolut {secrets.token_hex(3)}")
|
||||
pocket = _kto(admin, name=f"Sparen Pocket {secrets.token_hex(3)}")
|
||||
anderes = _kto(admin, name=f"Anderes {secrets.token_hex(3)}")
|
||||
kennung = f"um chf sparen {secrets.token_hex(6)}"
|
||||
betrag = 62 + secrets.randbelow(900)
|
||||
|
||||
# Der Zugang im Pocket gehoert schon zu einer Buchung vom dritten Konto.
|
||||
zugang = _tx(admin, pocket, "income", "2026-05-20", betrag, "Pocket")
|
||||
fremd = _tx(admin, anderes, "expense", "2026-05-20", betrag, "Fremd")
|
||||
assert admin.post("/api/uebertraege/verbinden",
|
||||
json={"a_id": fremd["id"], "b_id": zugang["id"]}).status_code == 200
|
||||
|
||||
# Und jetzt kommt die Revolut-Ausgabe, gleicher Tag, gleicher Betrag.
|
||||
raus = _tx(admin, quelle, "expense", "2026-05-20", betrag, kennung.upper())
|
||||
assert admin.post("/api/categories/transfer-keywords", json={
|
||||
"word": kennung, "target_account_id": pocket["id"]}).status_code == 201
|
||||
|
||||
r = admin.post("/api/categories/keywords/anwenden", params={"vorschau": False}).json()
|
||||
grund = next(z["grund"] for z in r["uebersprungen"] if z["text"] == kennung.upper())
|
||||
assert "schon mit einer anderen Buchung verbunden" in grund
|
||||
assert "Richtig ist hier, die beiden zu verbinden" not in grund, \
|
||||
"zum Verbinden raten waere hier falsch – die Gegenseite ist vergeben"
|
||||
|
||||
# Geblockt wird weiter: kein Uebertrag, kein verschobenes Geld.
|
||||
assert admin.get(f"/api/transactions/{raus['id']}").json()["type"] == "expense"
|
||||
assert admin.get(f"/api/accounts/{pocket['id']}").json()["balance_cents"] == betrag
|
||||
|
||||
|
||||
def test_freie_gegenseite_raet_weiter_zum_verbinden(admin):
|
||||
"""Die Gegenprobe: Ist die Gegenseite noch frei, bleibt es beim alten Rat.
|
||||
Sonst schluckte der neue Zweig alle Faelle."""
|
||||
quelle = _kto(admin, name=f"Revolut {secrets.token_hex(3)}")
|
||||
pocket = _kto(admin, name=f"Sparen Pocket {secrets.token_hex(3)}")
|
||||
kennung = f"um chf sparen {secrets.token_hex(6)}"
|
||||
betrag = 62 + secrets.randbelow(900)
|
||||
|
||||
_tx(admin, pocket, "income", "2026-05-20", betrag, "Pocket")
|
||||
_tx(admin, quelle, "expense", "2026-05-20", betrag, kennung.upper())
|
||||
assert admin.post("/api/categories/transfer-keywords", json={
|
||||
"word": kennung, "target_account_id": pocket["id"]}).status_code == 201
|
||||
|
||||
r = admin.post("/api/categories/keywords/anwenden", params={"vorschau": False}).json()
|
||||
grund = next(z["grund"] for z in r["uebersprungen"] if z["text"] == kennung.upper())
|
||||
assert "Richtig ist hier, die beiden zu verbinden" in grund
|
||||
|
||||
Reference in New Issue
Block a user