aps-agent/tests/golden/test_order_pool.py

152 lines
5.2 KiB
Python
Raw Normal View History

# ============================================================
# OR-03 订单池 / 审核黄金测试
# 固化:未批准不进排产;submit → approve 后可排;编辑已批→CHANGED
# ============================================================
from __future__ import annotations
from server.aps_domain.orders import (
apply_order_action,
apply_order_submit,
is_schedulable,
pool_summary,
)
from server.engines import get_engine
from server.engines.base import EngineParams
from server.state.seed import seed_world
from server.timeutil import add_minutes, fmt_date, today0
def _next_id_factory(world):
tables = {
"audit": "auditEvents",
"conflict": "conflicts",
"log": "logs",
"productionOrder": "productionOrders",
"salesOrder": "salesOrders",
"scheduleVersion": "scheduleVersions",
"workOrder": "workOrders",
}
counters: dict[str, int] = {}
def next_id(kind: str) -> int:
if kind not in counters:
rows = world.get(tables.get(kind, kind + "s"), [])
counters[kind] = max((r.get("id", 0) for r in rows if isinstance(r, dict)), default=0)
counters[kind] += 1
return counters[kind]
return next_id
def _run(world, *, include_unapproved: bool = False):
params = EngineParams(
orderIds=[],
engineType="RULE",
strategyTemplate="COMPREHENSIVE",
planningHorizonDays=14,
startDate=fmt_date(add_minutes(today0(), 24 * 60)),
includeUnapproved=include_unapproved,
)
return get_engine("RULE").solve(world, params, _next_id_factory(world))
def test_draft_excluded_from_schedule_run():
"""DRAFT 订单默认不进入 schedule.run;includeUnapproved 时可试排。"""
world = seed_world()
applied = apply_order_action(world, _next_id_factory(world), "order.upsert", {
"customerName": "待审客户",
"customerLevel": "A",
"deliveryDate": fmt_date(add_minutes(today0(), 9 * 24 * 60)),
"priority": 2,
"status": "DRAFT",
"productId": 1,
"quantity": 50,
})
draft = applied["order"]
assert draft["status"] == "DRAFT"
assert not is_schedulable(draft["status"])
result = _run(world)
assert result.orderCount == 7
assert all(po["salesOrderId"] != draft["id"] for po in world["productionOrders"])
result2 = _run(world, include_unapproved=True)
assert result2.orderCount == 8
assert any(po["salesOrderId"] == draft["id"] for po in world["productionOrders"])
def test_submit_approve_enters_scheduling():
"""DRAFT → submit → approve 后纳入正式排产。"""
world = seed_world()
applied = apply_order_action(world, _next_id_factory(world), "order.upsert", {
"customerName": "审核流客户",
"customerLevel": "VIP",
"deliveryDate": fmt_date(add_minutes(today0(), 10 * 24 * 60)),
"priority": 1,
"status": "DRAFT",
"productId": 1,
"quantity": 80,
})
order = applied["order"]
submitted = apply_order_submit(world, {"id": order["id"]})
assert submitted["order"]["status"] == "SUBMITTED"
assert _run(world).orderCount == 7
approved = apply_order_action(world, _next_id_factory(world), "order.approve", {
"orderIds": [order["id"]],
})
assert approved["order"]["status"] == "APPROVED"
assert approved["approvedCount"] == 1
result = _run(world)
assert result.orderCount == 8
assert any(po["salesOrderId"] == order["id"] for po in world["productionOrders"])
def test_edit_approved_becomes_changed():
"""编辑已批准订单内容 → CHANGED,暂时退出可排池。"""
world = seed_world()
target = world["salesOrders"][0]
assert target["status"] == "APPROVED"
apply_order_action(world, _next_id_factory(world), "order.upsert", {
"id": target["id"],
"customerName": target["customerName"],
"customerLevel": target["customerLevel"],
"deliveryDate": target["deliveryDate"],
"priority": target["priority"],
"productId": target["items"][0]["productId"],
"quantity": target["items"][0]["quantity"] + 10,
"status": "APPROVED",
})
assert target["status"] == "CHANGED"
assert not is_schedulable(target["status"])
assert pool_summary(world)["changed"] >= 1
assert _run(world).orderCount == 6
def test_batch_approve_pending():
"""orderIds=pending 批量批准所有 SUBMITTED。"""
world = seed_world()
for name in ("批甲", "批乙"):
o = apply_order_action(world, _next_id_factory(world), "order.upsert", {
"customerName": name,
"customerLevel": "B",
"deliveryDate": fmt_date(add_minutes(today0(), 11 * 24 * 60)),
"priority": 5,
"status": "DRAFT",
"productId": 2,
"quantity": 40,
})["order"]
apply_order_submit(world, {"id": o["id"]})
sm = pool_summary(world)
assert sm["pending"] == 2
applied = apply_order_action(world, _next_id_factory(world), "order.approve", {
"orderIds": "pending",
})
assert applied["approvedCount"] == 2
assert pool_summary(world)["pending"] == 0
assert _run(world).orderCount == 9