dodil/erp-brick-sales-order

DODIL ERP brick: sales order

tests/test_v8.py

"""Spec v8: the ship-to address object (and what a drop-ship line needs), SO-50 demand for planning, the tool names."""
from conftest import ADDRESS, ADMIN, INVENTORY, REP, SYSTEM, api, confirm, deliver, hand, must
from test_slice_b import JUICE, warehouse_set


def test_the_ship_to_address_is_the_object_the_order_keeps_shows_and_sends_to_purchasing(neighbours, inventory):
    o = hand(REP, ship_to_bp_id=7313, ship_to_address=ADDRESS, lines=[{"product_id": "PRINTER-X", "quantity": "2", "unit_code": "C62", "usage": "drop_ship"}])
    assert o["ship_to_address"] == {"lines": ["1 High Street"], "city": "London", "postcode": "N1 1AA", "region": None, "country": "GB"}
    assert o["ship_to_country"] == "GB"
    o = confirm(o)
    sent = neighbours.purchasing.requests[f"so:{o['sales_order_id']}:1@r1"]
    assert sent["ship_to_address"] == o["ship_to_address"]
    again = must(api("GET", f"/sales-orders/{o['sales_order_id']}", REP))
    assert again["ship_to_address"]["city"] == "London"


def test_a_drop_ship_line_cannot_be_confirmed_without_the_delivery_address(neighbours, inventory):
    o = must(api("POST", "/sales-orders", REP, {"bp_id": 7311, "currency": "GBP", "ship_to_bp_id": 7313,
                                                "lines": [{"product_id": "PRINTER-X", "quantity": "2", "unit_code": "C62", "usage": "drop_ship"}]}))
    assert o["ship_to_address"] is None
    s, b = api("POST", f"/sales-orders/{o['sales_order_id']}/confirm", REP, {})
    assert s == 422 and b["gate"] == "ship_to_address"
    assert api("POST", "/sales-orders", REP, {"bp_id": 7311, "currency": "GBP", "ship_to_address": {"lines": ["x"], "city": "L", "country": "gb"},
                                              "lines": [{"product_id": "SETUP", "quantity": "1", "unit_code": "HUR"}]})[0] == 422


def test_so50_open_quantity_of_confirmed_goods_lines_from_a_warehouse_without_prices(neighbours, inventory):
    warehouse_set("WH1")
    keep = confirm(hand(REP, lines=JUICE))
    must(api("POST", "/sales-orders", REP, {"bp_id": 7311, "currency": "GBP", "lines": JUICE}))              # a draft is not demand
    gone = confirm(hand(REP, lines=JUICE))
    must(api("POST", f"/sales-orders/{gone['sales_order_id']}/cancel", ADMIN, {"reason": "no"}))              # nor a cancelled order
    out = must(api("GET", "/demand", SYSTEM, {"product_id": "JUICE-075", "warehouse_id": "WH1", "from": "2026-11-01", "to": "2027-12-31"}))
    assert [(d["sales_order_id"], d["line_no"], d["open_quantity"], d["unit_code"], d["open_base"]) for d in out["demand"]] == \
        [(keep["sales_order_id"], 1, "480", "C62", "360")]
    assert out["more"] is False and not {"unit_price", "net_amount", "bp_id", "total"} & set(out["demand"][0])
    must(deliver(keep, 1, 100, "inv:D-1", INVENTORY, source="inventory"))
    again = must(api("GET", "/demand", SYSTEM, {"product_id": "JUICE-075", "warehouse_id": "WH1", "from": "2026-11-01", "to": "2027-12-31"}))
    assert again["demand"][0]["open_quantity"] == "380"
    other = must(api("GET", "/demand", SYSTEM, {"product_id": "JUICE-075", "warehouse_id": "WH9", "from": "2026-11-01", "to": "2027-12-31"}))
    assert other["demand"] == []
    assert api("GET", "/demand", REP, {"product_id": "JUICE-075", "warehouse_id": "WH1", "from": "2026-11-01", "to": "2027-12-31"})[0] == 403   # machine only
    assert api("GET", "/demand", SYSTEM, {"product_id": "JUICE-075", "warehouse_id": "WH1", "from": "2026-12-01", "to": "2026-11-01"})[0] == 422


def test_the_shared_family_tools_name_the_module_noun():
    from brick_sales_order.application import use_cases
    names = {uc.name for uc in use_cases.SO.use_cases}
    assert {"cancel_draft_order", "accept_order_suggestion", "reconcile_order_migration", "get_demand"} <= names
    assert not {"cancel_draft", "accept_suggestion", "reconcile_odoo_orders"} & names