from datetime import timedelta from factories import make_account, make_txn from fintracker.analytics import today_local async def test_rules_crud(client, auth_headers): r = await client.post( "/api/v1/rules", headers=auth_headers, json={"kind": "savings", "match_type": "payee", "pattern": "Копилка", "priority": 10}, ) assert r.status_code == 201 rule_id = r.json()["id"] assert r.json()["enabled"] is True assert r.json()["match_count"] == 0 r = await client.get("/api/v1/rules", headers=auth_headers) assert [x["id"] for x in r.json()] == [rule_id] r = await client.patch( f"/api/v1/rules/{rule_id}", headers=auth_headers, json={"pattern": "Копилка%"} ) assert r.status_code == 200 and r.json()["pattern"] == "Копилка%" r = await client.patch(f"/api/v1/rules/{rule_id}", headers=auth_headers, json={"kind": None}) assert r.status_code == 400 r = await client.post( "/api/v1/rules", headers=auth_headers, json={"kind": "nonsense", "match_type": "payee", "pattern": "x"}, ) assert r.status_code == 422 r = await client.delete(f"/api/v1/rules/{rule_id}", headers=auth_headers) assert r.status_code == 204 r = await client.delete(f"/api/v1/rules/{rule_id}", headers=auth_headers) assert r.status_code == 404 assert (await client.get("/api/v1/rules", headers=auth_headers)).json() == [] async def test_apply_runs_the_refresh_and_reports_stale_rules(client, auth_headers): card = await make_account(name="Карта", balance="10000") await make_txn( today_local() - timedelta(days=2), outcome="5000", outcome_account_id=card, payee="Копилка", ) matching = ( await client.post( "/api/v1/rules", headers=auth_headers, json={"kind": "savings", "match_type": "payee", "pattern": "копилка"}, ) ).json()["id"] rotten = ( await client.post( "/api/v1/rules", headers=auth_headers, json={"kind": "one_off", "match_type": "payee", "pattern": "Ничего не совпадает"}, ) ).json()["id"] r = await client.post("/api/v1/rules/apply", headers=auth_headers) assert r.status_code == 202 assert r.json()["error"] is None assert r.json()["trigger"] == "rules" by_id = {x["id"]: x for x in (await client.get("/api/v1/rules", headers=auth_headers)).json()} assert by_id[matching]["match_count"] == 1 assert by_id[matching]["last_matched_at"] is not None assert by_id[rotten]["match_count"] == 0 r = await client.get("/api/v1/rules/stale", headers=auth_headers) assert [x["id"] for x in r.json()] == [rotten] quality = (await client.get("/api/v1/data-quality", headers=auth_headers)).json() stale = [row for row in quality if row["check_name"] == "stale_rule"] assert len(stale) == 1 and stale[0]["ref"] == {"rule_id": rotten}