dodil/erp-brick-payroll
DODIL ERP brick: payroll
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 number of payslips in a run or of unrelated rows. Counted at the engine (erp_platform.testing.count_statements): a run of 2
employees and a run of 20 cost the same number of statements to calculate, approve (journal, payouts and documents included)
and read."""
import pytest
from conftest import EMP4410, MANAGER, api, approve, calculate, must, on_day, onboard, open_run, peer_approves_own, setup_company
from erp_platform.testing import count_statements
@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 _a_run_of(nb, extra: int, period: str):
"""The four people of conftest plus `extra` salaried employees, all with tax details."""
for k in range(extra):
nb.salaried(7000 + k, f"{30000 + 1000 * k}.00", cost_centre=["SALES-N", "OPS", "FIN"][k % 3])
run = open_run(period)["pay_run_id"]
onboard(run, pension=("4410-1", *[f"{7000 + k}-1" for k in range(0, extra, 2)]))
return run
def test_calculating_approving_and_reading_a_run_does_not_grow_with_its_payslips(nb, counted):
setup_company()
with on_day("2026-10-20T10:00:00+01:00"):
small = _a_run_of(nb, 0, "2026-10") # 4 payslips
with counted() as calc_few:
must(calculate(small))
peer_approves_own(small)
with counted() as appr_few:
must(approve(small))
with counted() as read_few:
must(api("GET", f"/pay-runs/{small}", MANAGER, {"lines": True}))
big = _a_run_of(nb, 16, "2026-11") # 20 payslips
with counted() as calc_many:
must(calculate(big))
peer_approves_own(big)
with counted() as appr_many:
must(approve(big))
with counted() as read_many:
must(api("GET", f"/pay-runs/{big}", MANAGER, {"lines": True}))
for label, few, many, cap in (("calculate", calc_few, calc_many, 24), ("approve+journal+payouts+documents+FPS+pension file", appr_few, appr_many, 90),
("get run with lines", read_few, read_many, 7)):
_show(f"{label} (4)", few)
_show(f"{label} (20)", many)
assert many.statements == few.statements and few.statements <= cap, (label, few.statements, many.statements)
def test_my_payslips_do_not_grow_with_other_peoples_payslips(nb, counted):
setup_company()
with on_day("2026-10-20T10:00:00+01:00"):
run = _a_run_of(nb, 0, "2026-10")
peer_approves_own(run)
must(approve(run))
with on_day("2026-10-31T10:00:00+00:00"):
with counted() as few:
assert len(must(api("GET", "/my/payslips", EMP4410))["payslips"]) == 1
run = _a_run_of(nb, 16, "2026-11")
peer_approves_own(run)
must(approve(run))
with on_day("2026-12-01T10:00:00+00:00"):
with counted() as many:
assert len(must(api("GET", "/my/payslips", EMP4410))["payslips"]) == 2
_show("my payslips (4 around)", few)
_show("my payslips (24 around)", many)
assert many.statements == few.statements and few.statements <= 3, (few.statements, many.statements)