aps-agent/tests/golden/test_order_pool.py

152 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ============================================================
# 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