80 lines
3.1 KiB
Python
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)
|