dodil/erp-brick-tax

DODIL ERP brick: tax

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
unrelated documents. Counted at the engine, one request at a time (erp_platform.testing.count_statements)."""
import pytest
from conftest import FULL, SYSTEM, TODAY, api, filing_ready, frozen_sale, line, must, prepare
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 _sales(first, n):
    for k in range(first, first + n):
        frozen_sale(f"S-{k}", [line(1, "100.00")])


def test_preparing_a_vat_return_does_not_grow_with_the_number_of_documents(hmrc_world, counted):
    filing_ready()
    _sales(1, 2)
    with counted() as few:
        must(prepare("26AD"))
    _sales(3, 8)
    with counted() as many:
        must(prepare("26AD"))
    _show("prepare return (2 documents)", few)
    _show("prepare return (10 documents)", many)
    # entries are claimed in bulk (one read of the existing keys, one insert, one upsert): the count is flat in the number of documents
    _sales(11, 10)
    with counted() as most:
        must(prepare("26AD"))
    _show("prepare return (20 documents)", most)
    assert few.statements <= 30 and many.statements == few.statements and most.statements == few.statements, (few.statements, many.statements, most.statements)      # was 33 and 81


def test_freezing_a_document_does_not_grow_with_the_number_of_frozen_documents(hmrc_world, counted):
    filing_ready()

    def freeze_one(ref):
        must(api("POST", "/documents/compute", SYSTEM, {"lines": [line(1, "100.00")], "tax_point": TODAY, "bp_id": 7311, "document_ref": ref}))
        with counted() as c:
            must(api("POST", f"/documents/{ref}/freeze", SYSTEM, {"contents": FULL}))
        return c
    _sales(1, 2)
    few = freeze_one("F-1")
    _sales(3, 8)
    many = freeze_one("F-2")
    _show("freeze (2 frozen)", few)
    _show("freeze (10 frozen)", many)
    assert many.statements <= few.statements and few.statements <= 12, (few.statements, many.statements)       # was 16



def test_computing_a_kept_document_is_flat_in_its_lines_and_in_other_documents(hmrc_world, counted):
    filing_ready()

    def compute(ref, n):
        with counted() as c:
            must(api("POST", "/documents/compute", SYSTEM, {"lines": [line(k, "100.00") for k in range(1, n + 1)], "tax_point": TODAY,
                                                            "bp_id": 7311, "document_ref": ref}))
        return c
    _sales(1, 2)
    two = compute("C-1", 2)
    twenty = compute("C-2", 20)
    again = compute("C-1", 2)                      # a recompute of a kept document: loaded once, saved by its snapshot
    _sales(3, 48)
    later = compute("C-3", 2)
    for label, c in (("compute 2 lines", two), ("compute 20 lines", twenty), ("recompute 2 lines", again), ("compute, 50 others", later)):
        _show(label, c)
    assert two.statements == twenty.statements == later.statements, (two.statements, twenty.statements, later.statements)
    assert two.statements <= 15 and again.statements <= 15, (two.statements, again.statements)     # was 20: registrations read twice, a new document's keys re-read