77 lines
3.2 KiB
Python
77 lines
3.2 KiB
Python
# ============================================================
|
|
# EX-03 冲突解决工作流黄金测试
|
|
# ============================================================
|
|
from __future__ import annotations
|
|
|
|
from server.aps_domain.conflicts import apply_conflict_fix, list_conflict_center
|
|
from server.aps_domain.flex import apply_equipment_fault, run_flex_schedule
|
|
from server.state.seed import seed_world
|
|
|
|
|
|
class _MemStore:
|
|
def __init__(self, data):
|
|
self.data = data
|
|
|
|
def next_id(self, kind: str) -> int:
|
|
key = f"_c_{kind}"
|
|
self.data[key] = self.data.get(key, 2000) + 1
|
|
return self.data[key]
|
|
|
|
def save(self):
|
|
pass
|
|
|
|
|
|
def test_conflict_center_lists_with_fixes():
|
|
store = _MemStore(seed_world())
|
|
run_flex_schedule(store, sort_mode="BOTTLENECK", actor="test")
|
|
apply_equipment_fault(store, "WELD-01", status="MAINTENANCE", reschedule=True, actor="test")
|
|
data = list_conflict_center(store.data, scope="flex")
|
|
assert data["total"] >= 0
|
|
# 焊接故障后通常有 NO_CAPABILITY 或至少 DELAY
|
|
if data["rows"]:
|
|
row = data["rows"][0]
|
|
assert row["fixes"]
|
|
assert all("action" in f and "label" in f for f in row["fixes"])
|
|
|
|
|
|
def test_apply_mold_unlock_resolves_mold_life():
|
|
store = _MemStore(seed_world())
|
|
# 人为制造模具寿命冲突记录
|
|
run_flex_schedule(store, sort_mode="BOTTLENECK", actor="test")
|
|
mold = next(m for m in store.data["flexMolds"] if m["code"] == "MOLD-HV-01")
|
|
mold["status"] = "LOCKED"
|
|
mold["lifeUsed"] = mold["lifeTotal"]
|
|
vid = store.data["flexScheduleVersions"][-1]["id"]
|
|
cid = store.next_id("flexConflict")
|
|
store.data["flexConflicts"].append({
|
|
"id": cid, "versionId": vid, "conflictType": "MOLD_LIFE", "severity": "MAJOR",
|
|
"resourceType": "MOLD", "resourceName": "MOLD-HV-01",
|
|
"orderNo": "FO-001", "description": "模具寿命用尽",
|
|
"suggestedSolution": "解锁", "isResolved": False,
|
|
})
|
|
r = apply_conflict_fix(store, cid, "flex.mold.unlock",
|
|
params={"moldCode": "MOLD-HV-01"}, actor="test")
|
|
assert r["applied"] is True
|
|
assert mold["status"] == "AVAILABLE"
|
|
cf = next(c for c in store.data["flexConflicts"] if c["id"] == cid)
|
|
assert cf["isResolved"] is True
|
|
|
|
|
|
def test_apply_reschedule_stages_p2():
|
|
store = _MemStore(seed_world())
|
|
run_flex_schedule(store, sort_mode="BOTTLENECK", actor="test")
|
|
vid = store.data["flexScheduleVersions"][-1]["id"]
|
|
cid = store.next_id("flexConflict")
|
|
store.data["flexConflicts"].append({
|
|
"id": cid, "versionId": vid, "conflictType": "DELAY", "severity": "MAJOR",
|
|
"resourceType": "TIME", "orderNo": "FO-001",
|
|
"description": "交期延误", "suggestedSolution": "重排", "isResolved": False,
|
|
})
|
|
before = len(store.data["flexScheduleVersions"])
|
|
r = apply_conflict_fix(store, cid, "flex.reschedule",
|
|
params={"level": "L2"}, actor="test", session_id="t1")
|
|
assert r.get("staged") is True
|
|
assert r.get("block")
|
|
assert len(store.data["flexScheduleVersions"]) == before # 未执行
|
|
assert not next(c for c in store.data["flexConflicts"] if c["id"] == cid)["isResolved"]
|