feat: API meldet mögliche Doppelzählung mit 409, Speichern nur mit Bestätigung (A12-T3)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
from decimal import Decimal
|
||||
|
||||
H = {"Authorization": "Bearer test-key"}
|
||||
KREDIT = {"name": "Auto", "principal": "1200.00", "annual_rate_pct": "0",
|
||||
"term_months": 12, "payout_date": "2026-01-15", "repayment_type": "annuity"}
|
||||
POSTEN = {"name": "Rate Auto", "amount": "-100.00", "rhythm": "monthly", "due_day": 15}
|
||||
|
||||
|
||||
def _count(client, path):
|
||||
return len(client.get(path, headers=H).json())
|
||||
|
||||
|
||||
def test_posten_zu_bestehendem_kredit_409(client):
|
||||
assert client.post("/api/loans", headers=H, json=KREDIT).status_code == 201
|
||||
r = client.post("/api/recurring", headers=H, json=POSTEN)
|
||||
assert r.status_code == 409
|
||||
d = r.json()["detail"]
|
||||
assert d["code"] == "doppelzaehlung_kredit"
|
||||
assert "doppelt" in d["meldung"]
|
||||
assert d["konflikte"] == [{"posten": "Rate Auto", "posten_betrag": "-100.00",
|
||||
"kredit": "Auto", "kredit_rate": "100.00"}]
|
||||
assert _count(client, "/api/recurring") == 0
|
||||
|
||||
|
||||
def test_posten_mit_bestaetigung_gespeichert(client):
|
||||
client.post("/api/loans", headers=H, json=KREDIT)
|
||||
r = client.post("/api/recurring", headers=H,
|
||||
json={**POSTEN, "doppelzaehlung_bestaetigt": True})
|
||||
assert r.status_code == 201
|
||||
assert "doppelzaehlung_bestaetigt" not in r.json()
|
||||
assert _count(client, "/api/recurring") == 1
|
||||
|
||||
|
||||
def test_kredit_zu_bestehendem_posten_409_und_bestaetigung(client):
|
||||
client.post("/api/recurring", headers=H, json=POSTEN)
|
||||
r = client.post("/api/loans", headers=H, json=KREDIT)
|
||||
assert r.status_code == 409
|
||||
assert r.json()["detail"]["konflikte"][0]["posten"] == "Rate Auto"
|
||||
assert _count(client, "/api/loans") == 0
|
||||
r = client.post("/api/loans", headers=H, json={**KREDIT, "doppelzaehlung_bestaetigt": True})
|
||||
assert r.status_code == 201
|
||||
assert "doppelzaehlung_bestaetigt" not in r.json()
|
||||
|
||||
|
||||
def test_ohne_konflikt_unveraendert(client):
|
||||
client.post("/api/loans", headers=H, json=KREDIT)
|
||||
r = client.post("/api/recurring", headers=H, json={**POSTEN, "amount": "-50.00"})
|
||||
assert r.status_code == 201
|
||||
|
||||
|
||||
def test_patch_posten_erzeugt_konflikt_409_ohne_aenderung(client):
|
||||
client.post("/api/loans", headers=H, json=KREDIT)
|
||||
item = client.post("/api/recurring", headers=H, json={**POSTEN, "amount": "-50.00"}).json()
|
||||
r = client.patch(f"/api/recurring/{item['id']}", headers=H, json={"amount": "-100.00"})
|
||||
assert r.status_code == 409
|
||||
stored = client.get("/api/recurring", headers=H).json()[0]
|
||||
assert Decimal(stored["amount"]) == Decimal("-50.00")
|
||||
r = client.patch(f"/api/recurring/{item['id']}", headers=H,
|
||||
json={"amount": "-100.00", "doppelzaehlung_bestaetigt": True})
|
||||
assert r.status_code == 200
|
||||
assert Decimal(r.json()["amount"]) == Decimal("-100.00")
|
||||
|
||||
|
||||
def test_patch_nur_name_bei_bestehendem_konflikt_ohne_flag(client):
|
||||
client.post("/api/loans", headers=H, json=KREDIT)
|
||||
item = client.post("/api/recurring", headers=H,
|
||||
json={**POSTEN, "doppelzaehlung_bestaetigt": True}).json()
|
||||
r = client.patch(f"/api/recurring/{item['id']}", headers=H, json={"name": "Rate Auto neu"})
|
||||
assert r.status_code == 200
|
||||
loan = client.get("/api/loans", headers=H).json()[0]
|
||||
r = client.patch(f"/api/loans/{loan['id']}", headers=H, json={"name": "Auto neu"})
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_patch_kredit_erzeugt_konflikt_409(client):
|
||||
client.post("/api/recurring", headers=H, json=POSTEN)
|
||||
loan = client.post("/api/loans", headers=H, json={**KREDIT, "principal": "2400.00"}).json()
|
||||
r = client.patch(f"/api/loans/{loan['id']}", headers=H, json={"principal": "1200.00"})
|
||||
assert r.status_code == 409
|
||||
assert Decimal(client.get("/api/loans", headers=H).json()[0]["principal"]) == Decimal("2400.00")
|
||||
r = client.patch(f"/api/loans/{loan['id']}", headers=H,
|
||||
json={"principal": "1200.00", "doppelzaehlung_bestaetigt": True})
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_vorschlag_uebernehmen_nutzt_denselben_endpunkt(client):
|
||||
# „Vorschlag übernehmen" sendet dieselben Felder (inkl. start_date/category_id=null).
|
||||
client.post("/api/loans", headers=H, json=KREDIT)
|
||||
r = client.post("/api/recurring", headers=H, json={
|
||||
**POSTEN, "start_date": None, "category_id": None})
|
||||
assert r.status_code == 409
|
||||
Reference in New Issue
Block a user