dodil/erp-brick-purchasing
DODIL ERP brick: purchasing
tests/test_stories_readside.py
"""The read side other bricks use (expected receipts, open bills, receiving locations) and release levels (PUR-38)."""
from conftest import (
ALICE,
APPROVER,
APPROVER2,
BUYER,
CLERK,
INVENTORY,
OWNER,
RECEIVER,
SUPPLIER_A,
api,
bill,
confirmed,
draft,
must,
receive,
set_limit,
supplier_price,
world,
)
def test_expected_receipts_are_derived_from_confirmed_lines_less_receipts_and_need_the_expected_permission():
world()
supplier_price()
o = confirmed(lines=[{"product_id": "COLA-075", "quantity": "10"}])
got = must(api("GET", "/expected-receipts", INVENTORY, {"product_id": "COLA-075"}))
assert len(got) == 1 and str(got[0]["quantity_base_outstanding"]).startswith("240")
receive(o, quantity="4")
assert str(must(api("GET", "/expected-receipts", INVENTORY, {}))[0]["quantity_base_outstanding"]).startswith("144")
one = must(api("GET", f"/purchase-orders/{o['purchase_order_id']}/expected", INVENTORY))
assert str(one["lines"][0]["outstanding"]).startswith("6") and str(one["lines"][0]["received"]).startswith("4")
assert api("GET", "/expected-receipts", CLERK, {})[0] == 403
def test_open_bills_are_the_approved_bills_less_allocations_as_of_a_date():
world()
supplier_price()
o = confirmed(lines=[{"product_id": "COLA-075", "quantity": "10"}])
receive(o)
s, b = bill(o)
assert must(api("GET", "/bills/open", ALICE, {"as_of": "2026-11-20"}))["items"] == [] # a bill nobody approved is not open
must(api("POST", f"/bills/{b['bill_id']}/approve", as_approver(), {}))
items = must(api("GET", "/bills/open", ALICE, {"as_of": "2026-11-20"}))["items"]
assert len(items) == 1 and items[0]["bp_id"] == str(SUPPLIER_A) and str(items[0]["outstanding"]) == "216.00"
def as_approver():
from conftest import PAYAPPROVER
return PAYAPPROVER
def test_receiving_locations_come_from_inventory_for_a_receiver(neighbours):
got = must(api("GET", "/receiving-locations", RECEIVER, {}))
assert got and api("GET", "/receiving-locations", CLERK, {})[0] == 403
def test_pur38_two_release_levels_need_two_different_approvers_and_the_final_limit_to_cover():
world(threshold="0", limits=False)
set_limit("approver@shop.example", "5000", start="2026-11-20")
set_limit("approver2@shop.example", "500000", start="2026-11-20")
must(api("POST", "/release-strategies", OWNER, {"levels": 2, "level_thresholds": ["1000", "50000"], "min_amount": "0", "valid_from": "2026-11-20"}))
supplier_price(product="LAPTOP", unit="C62", price="900.0000")
o = draft(lines=[{"product_id": "LAPTOP", "quantity": "10"}])
oid = o["purchase_order_id"]
must(api("POST", f"/purchase-orders/{oid}/submit", BUYER, {}))
s, b = api("POST", f"/purchase-orders/{oid}/approve", APPROVER2, {}) # the final level before level 1
assert s == 409
lvl = must(api("POST", f"/purchase-orders/{oid}/approve-level", APPROVER, {}))
assert lvl["status"] == "to_approve" and "level 2 of 2" in str(lvl["waiting"])
s, b = api("POST", f"/purchase-orders/{oid}/approve", APPROVER, {}) # the same person cannot give the second level
assert s == 409 and "second_person" in str(b)
done = must(api("POST", f"/purchase-orders/{oid}/approve", APPROVER2, {}))
assert done["status"] == "approved" and done["approved_levels"] == 2
assert api("POST", f"/purchase-orders/{oid}/confirm", BUYER, {})[0] == 200