fix: "Keine Treffer" sagt jetzt, woran es liegt
Bei der Bank-Suche kam nur "Keine Treffer" – das hiess zweierlei: Die Schnittstelle lieferte gar keine Liste, oder sie lieferte eine und der Suchbegriff passte nicht. Beides sieht gleich aus, fuehrt aber an ganz verschiedene Stellen. Genau diese Verwechslung hat heute schon zweimal Zeit gekostet. Die Antwort traegt jetzt die Gesamtzahl mit. Kam nichts, steht der wahrscheinliche Grund dabei: Die Anwendung bei Enable Banking wird erst aktiv, wenn man dort die eigenen Konten verknuepft hat. Ausserdem wird breiter gesucht – auch in BIC und Gruppenname, weil Banken in so einer Liste nicht immer so heissen wie im Alltag – und die Antwort wird defensiv gelesen, falls die Liste ohne Schluessel kommt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,7 +58,7 @@ def delete_app(db: Session = Depends(get_db), user: User = Depends(get_current_u
|
||||
@router.get("/banks")
|
||||
def list_banks(country: str | None = None, search: str | None = None,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Depends(get_current_user)) -> list[dict]:
|
||||
user: User = Depends(get_current_user)) -> dict:
|
||||
"""Banken suchen – in einem Land oder über alle hinweg.
|
||||
|
||||
Ohne ``country`` wird überall gesucht. Das braucht es, weil die IBAN nicht
|
||||
|
||||
@@ -116,7 +116,13 @@ class BankClient:
|
||||
Revolut gibt deutsche IBANs aus, ist aber in Litauen ansässig.
|
||||
"""
|
||||
pfad = f"/aspsps?country={land.upper()}" if land else "/aspsps"
|
||||
return self._anfrage("GET", pfad).get("aspsps", [])
|
||||
daten = self._anfrage("GET", pfad)
|
||||
# Defensiv: manche Fassungen liefern die Liste direkt statt unter
|
||||
# einem Schlüssel. Eine leere Antwort stillschweigend als „keine
|
||||
# Treffer" auszugeben hat schon genug Zeit gekostet.
|
||||
if isinstance(daten, list):
|
||||
return daten
|
||||
return daten.get("aspsps") or daten.get("data") or []
|
||||
|
||||
def starte_autorisierung(self, aspsp_name: str, land: str, redirect_url: str,
|
||||
state: str, tage: int, psu_type: str = "personal") -> dict:
|
||||
|
||||
@@ -66,7 +66,7 @@ MAX_TREFFER = 200
|
||||
|
||||
|
||||
def banken(db: Session, user: User, land: str | None = None,
|
||||
suche: str | None = None) -> list[dict]:
|
||||
suche: str | None = None) -> dict:
|
||||
"""Banken suchen – in einem Land oder über alle hinweg.
|
||||
|
||||
Die Suche über alle Länder ist kein Luxus: Das Sitzland einer Bank steht
|
||||
@@ -80,12 +80,20 @@ def banken(db: Session, user: User, land: str | None = None,
|
||||
name = b.get("name")
|
||||
if not name:
|
||||
continue
|
||||
if begriff and begriff not in name.lower():
|
||||
# Auch im BIC und im Gruppennamen suchen: Banken heissen in der Liste
|
||||
# nicht immer so wie im Alltag.
|
||||
heu = " ".join(str(x) for x in (name, b.get("bic"), b.get("group")) if x).lower()
|
||||
if begriff and begriff not in heu:
|
||||
continue
|
||||
treffer.append({"name": name, "country": b.get("country"),
|
||||
"logo": b.get("logo"), "psu_types": b.get("psu_types", [])})
|
||||
"logo": b.get("logo"), "psu_types": b.get("psu_types", []),
|
||||
"beta": bool(b.get("beta"))})
|
||||
treffer.sort(key=lambda b: (b["name"].lower(), b.get("country") or ""))
|
||||
return treffer[:MAX_TREFFER]
|
||||
# „gesamt" mitliefern: Sonst sieht „keine Treffer" gleich aus, egal ob die
|
||||
# Liste leer kam oder der Suchbegriff nicht passte – und man sucht den
|
||||
# Fehler an der falschen Stelle.
|
||||
return {"gesamt": len(roh), "treffer": treffer[:MAX_TREFFER],
|
||||
"gekuerzt": len(treffer) > MAX_TREFFER}
|
||||
|
||||
|
||||
def starte_verbindung(db: Session, user: User, aspsp_name: str, land: str,
|
||||
|
||||
@@ -191,7 +191,7 @@ def test_banken_eines_landes_abrufen(admin, fake_bank):
|
||||
fake_bank()
|
||||
r = admin.get("/api/bank/banks?country=DE")
|
||||
assert r.status_code == 200, r.text
|
||||
assert [b["name"] for b in r.json()] == ["N26"]
|
||||
assert [b["name"] for b in r.json()["treffer"]] == ["N26"]
|
||||
|
||||
|
||||
def test_verbinden_und_konten_finden(admin, fake_bank):
|
||||
@@ -377,13 +377,17 @@ def test_suche_findet_ueber_alle_laender(admin, fake_bank):
|
||||
|
||||
alle = admin.get("/api/bank/banks?search=revolut")
|
||||
assert alle.status_code == 200, alle.text
|
||||
treffer = alle.json()
|
||||
assert [b["name"] for b in treffer] == ["Revolut"]
|
||||
assert treffer[0]["country"] == "LT"
|
||||
daten = alle.json()
|
||||
assert [b["name"] for b in daten["treffer"]] == ["Revolut"]
|
||||
assert daten["treffer"][0]["country"] == "LT"
|
||||
# Die Gesamtzahl kommt mit: Sonst sieht „keine Treffer" gleich aus, egal ob
|
||||
# die Liste leer kam oder nur der Begriff nicht passte.
|
||||
assert daten["gesamt"] == 2
|
||||
|
||||
# Unter Deutschland gesucht liefert dieselbe Bank NICHT.
|
||||
nur_de = admin.get("/api/bank/banks?country=DE&search=revolut").json()
|
||||
assert nur_de == []
|
||||
assert nur_de["treffer"] == []
|
||||
assert nur_de["gesamt"] == 1
|
||||
|
||||
|
||||
def test_suche_ohne_land_und_ohne_begriff_wird_abgelehnt(admin, fake_bank):
|
||||
@@ -393,3 +397,38 @@ def test_suche_ohne_land_und_ohne_begriff_wird_abgelehnt(admin, fake_bank):
|
||||
r = admin.get("/api/bank/banks")
|
||||
assert r.status_code == 400
|
||||
assert "Suchbegriff" in r.json()["detail"]
|
||||
|
||||
|
||||
|
||||
def test_leere_bankliste_ist_von_keinem_treffer_unterscheidbar(admin, fake_bank):
|
||||
"""„Keine Treffer" darf nicht beides heissen.
|
||||
|
||||
Kam die Liste leer, liegt es an der Anwendung; passte nur der Begriff
|
||||
nicht, liegt es am Begriff. Ohne die Gesamtzahl sucht man den Fehler an
|
||||
der falschen Stelle – das hat schon einmal einen Abend gekostet.
|
||||
"""
|
||||
_app(admin)
|
||||
gegenstelle = fake_bank()
|
||||
gegenstelle.banken_leer = True
|
||||
|
||||
def leer(methode, pfad, **kw):
|
||||
if pfad.startswith("/aspsps"):
|
||||
return 200, {"aspsps": []}
|
||||
return FakeBank.__call__(gegenstelle, methode, pfad, **kw)
|
||||
|
||||
import app.services.bank_api as bank_api_modul
|
||||
urspruenglich = bank_api_modul.BankClient._anfrage
|
||||
|
||||
def _anfrage(self, methode, pfad, **rest):
|
||||
code, daten = leer(methode, pfad, **rest)
|
||||
if code >= 400:
|
||||
raise bank_api_modul.BankFehler(daten.get("message", "Fehler"))
|
||||
return daten
|
||||
|
||||
bank_api_modul.BankClient._anfrage = _anfrage
|
||||
try:
|
||||
daten = admin.get("/api/bank/banks?search=revolut").json()
|
||||
assert daten["gesamt"] == 0
|
||||
assert daten["treffer"] == []
|
||||
finally:
|
||||
bank_api_modul.BankClient._anfrage = urspruenglich
|
||||
|
||||
Reference in New Issue
Block a user