aps-agent/tests/golden/test_campaign.py

80 lines
3.1 KiB
Python

# ============================================================
# SC-08 批次/战役合并黄金测试
# ============================================================
from __future__ import annotations
from server.aps_domain.campaign import merge_entries_to_campaigns, preview_campaigns
from server.engines.base import EngineParams
from server.engines.rule_engine import RuleEngine
from server.state.seed import seed_world
from server.timeutil import add_minutes, fmt_date, today0
def test_preview_merges_same_product_in_window():
world = seed_world()
report = preview_campaigns(world, window_days=7)
assert report["summary"]["inputOrders"] == 7
assert report["summary"]["poSaved"] >= 1
assert report["summary"]["mergedCampaigns"] >= 1
# CTRL-A 两单交期差 1 天,应合并
a_camps = [c for c in report["campaigns"] if c["productCode"] == "CTRL-A" and c["isCampaign"]]
assert a_camps
assert a_camps[0]["memberCount"] == 2
assert a_camps[0]["totalQty"] == 1300 # 500+800
def test_rush_not_merged():
world = seed_world()
report = preview_campaigns(world, window_days=30)
rush_rows = [c for c in report["campaigns"] if c.get("isRush")]
assert rush_rows
assert all(c["memberCount"] == 1 for c in rush_rows)
def test_campaign_strategy_fewer_pos():
world = seed_world()
start = fmt_date(add_minutes(today0(), 24 * 60))
counter = {"n": 4000}
def next_id(_k: str) -> int:
counter["n"] += 1
return counter["n"]
base = EngineParams(
strategyTemplate="COMPREHENSIVE", name="base",
planningHorizonDays=14, startDate=start,
constraints={"materialKit": False, "changeover": True, "capacity": True, "dueDate": True,
"equipment": True, "personnel": True, "tooling": True, "freeze": True},
)
r0 = RuleEngine("RULE").solve(world, base, next_id)
assert r0.poCount == 7
world2 = seed_world()
camp = EngineParams(
strategyTemplate="CAMPAIGN", name="campaign",
planningHorizonDays=14, startDate=start,
constraints={"materialKit": False, "changeover": True, "capacity": True, "dueDate": True,
"equipment": True, "personnel": True, "tooling": True, "freeze": True},
)
r1 = RuleEngine("RULE").solve(world2, camp, next_id)
assert r1.orderCount == 7 # 源订单仍计 7
assert r1.poCount < 7
ver = next(v for v in world2["scheduleVersions"] if v["id"] == r1.versionId)
assert ver["campaign"]["enabled"] is True
assert ver["campaign"]["poSaved"] >= 1
camp_pos = [p for p in world2["productionOrders"]
if p.get("schedulingVersionId") == r1.versionId and p.get("isCampaign")]
assert camp_pos
assert camp_pos[0]["campaignMemberCount"] >= 2
assert len(camp_pos[0]["campaignSourceOrderNos"]) >= 2
def test_merge_entries_unit():
world = seed_world()
entries = []
for so in world["salesOrders"]:
for item in so["items"]:
entries.append({"so": so, "item": item})
camps = merge_entries_to_campaigns(world, entries, window_days=7)
assert len(camps) < len(entries)