dodil/erp-brick-time-off
DODIL ERP brick: time off
tests/test_statement_budget.py
"""Statement budgets: every statement is a round trip (100-300 ms on the live pg wire), so a request's statements must not grow with the days it
covers or with unrelated people's rows. Counted at the engine, one request at a time (erp_platform.testing.count_statements)."""
import pytest
from conftest import EMPLOYEE, MANAGER, api, approve, balance, decided, get, must, request
from erp_platform.testing import count_statements
from test_invariants import seed_others
@pytest.fixture
def counted(engine):
return lambda: count_statements(engine)
def _show(label, c):
print(f"BUDGET {label}: statements={c.statements} round_trips={c.round_trips}")
def test_asking_does_not_grow_with_the_days_asked_for(counted):
with counted() as two:
request("2026-11-09", "2026-11-10") # 2 working days
with counted() as twenty:
request("2026-11-16", "2026-12-11") # 20 working days
_show("request (2 days)", two)
_show("request (20 days)", twenty)
assert twenty.statements == two.statements and two.statements <= 16, (two.statements, twenty.statements)
def test_reading_a_balance_and_a_request_does_not_grow_with_the_days_booked(counted):
short = decided("2026-11-09", "2026-11-10")["request_id"]
long = decided("2026-11-16", "2026-12-11")["request_id"]
with counted() as few:
get(short)
with counted() as many:
get(long)
_show("get request (2 days)", few)
_show("get request (20 days)", many)
assert many.statements == few.statements and few.statements <= 4, (few.statements, many.statements)
with counted() as bal:
balance()
_show("balance (22 days booked)", bal)
assert bal.statements <= 8
def test_approving_does_not_grow_with_the_days(counted):
a, b = request("2026-11-09", "2026-11-10")["request_id"], request("2026-11-16", "2026-12-11")["request_id"]
with counted() as few:
must(approve(a))
with counted() as many:
must(approve(b))
_show("approve (2 days)", few)
_show("approve (20 days)", many)
assert many.statements == few.statements and few.statements <= 12, (few.statements, many.statements)
def test_cancelling_does_not_grow_with_the_days(counted):
a, b = decided("2026-11-09", "2026-11-10")["request_id"], decided("2026-11-16", "2026-12-11")["request_id"]
with counted() as few:
must(api("POST", f"/leave-requests/{a}/cancel", MANAGER, {"reason": "x"}))
with counted() as many:
must(api("POST", f"/leave-requests/{b}/cancel", MANAGER, {"reason": "x"}))
_show("cancel (2 days)", few)
_show("cancel (20 days)", many)
assert many.statements == few.statements and few.statements <= 12, (few.statements, many.statements)
def test_the_hr_calls_do_not_grow_with_the_days_either(hr):
request("2026-11-09", "2026-11-10")
short = len(hr.calls)
request("2026-11-16", "2026-12-11")
assert len(hr.calls) - short == short # the same four calls: person, employment, one pattern, manager... for 20 days
def test_nothing_grows_with_fifty_unrelated_people(counted):
mine = decided("2026-11-09", "2026-11-10")["request_id"]
with counted() as few:
balance()
must(api("GET", "/leave-requests", EMPLOYEE))
must(api("GET", "/leave-requests", MANAGER, {"scope": "waiting"}))
get(mine)
seed_others(50)
with counted() as many:
balance()
must(api("GET", "/leave-requests", EMPLOYEE))
must(api("GET", "/leave-requests", MANAGER, {"scope": "waiting"}))
get(mine)
_show("balance + lists + get (1 person around)", few)
_show("balance + lists + get (51 people around)", many)
assert many.statements == few.statements and few.statements <= 20, (few.statements, many.statements)
def test_asking_approving_and_cancelling_do_not_grow_with_fifty_unrelated_people(counted):
seed_others(2)
with counted() as few:
rid = request("2026-11-09", "2026-11-10")["request_id"]
must(approve(rid))
must(api("POST", f"/leave-requests/{rid}/cancel", MANAGER, {"reason": "x"}))
seed_others(50, first=2)
with counted() as many:
rid = request("2026-11-09", "2026-11-10")["request_id"]
must(approve(rid))
must(api("POST", f"/leave-requests/{rid}/cancel", MANAGER, {"reason": "x"}))
_show("ask+approve+cancel (3 people around)", few)
_show("ask+approve+cancel (52 people around)", many)
assert many.statements == few.statements, (few.statements, many.statements)