# ============================================================ # master.query + 机加工知识库黄金测试 # ============================================================ from __future__ import annotations from server.agent_core.intent import parse_fast from server.aps_domain.kangni_intake import DEFAULT_ROUTE_XLSX, load_site_into_world from server.aps_domain.master_query import format_master_query, run_master_query from server.aps_domain.workflow import handle_intent from server.contracts import IntentResult from server.knowledge import get_knowledge from server.state.seed import seed_world from pathlib import Path class _Mem: def __init__(self, data): self.data = data def next_id(self, kind: str) -> int: self.data[f"_c_{kind}"] = self.data.get(f"_c_{kind}", 100) + 1 return self.data[f"_c_{kind}"] def save(self): pass def _world_site(): w = seed_world() if Path(DEFAULT_ROUTE_XLSX).exists(): load_site_into_world(w, route_path=DEFAULT_ROUTE_XLSX, include_sibling_orders=False) return w def test_intent_master_query_orders(): w = seed_world() r = parse_fast("有哪些订单", w) assert r and r.intent == "master.query" assert r.params.get("entity") == "order" def test_intent_machining_knowledge(): w = seed_world() r = parse_fast("机加工工艺怎么生成", w) assert r and r.intent == "knowledge.query" def test_master_query_on_site_order(): w = _world_site() if not Path(DEFAULT_ROUTE_XLSX).exists(): return q = run_master_query(w, entity="order", code="102285668") assert q["count"] >= 1 assert any(r["orderNo"] == "102285668" for r in q["rows"]) text = format_master_query(q) assert "102285668" in text bom = run_master_query(w, entity="bom", code="28200003654300") assert bom["count"] >= 15 rt = run_master_query(w, entity="routing", code="28200003654300") assert rt["count"] == 10 def test_machining_seed_assets_present(): kb = get_knowledge() n = kb.ensure_seed_assets() titles = {a["title"] for a in kb.assets} assert "机加工工艺路线生成总则" in titles assert "车削工艺路线模式" in titles assert "机械装配工艺模式" in titles assert "城轨机构装配路线模板" in titles assert sum(1 for a in kb.assets if a.get("kind") == "process") >= 10 def test_chat_master_query_and_kb_catalog(): import asyncio w = _world_site() store = _Mem(w) async def _run(): reply = await handle_intent( store, "t", IntentResult(intent="master.query", params={"entity": "overview", "query": "主数据概览"}, confidence=0.95, source="RULE_FAST"), actor="test", ) assert "主数据概览" in reply.text or "工厂" in reply.text reply2 = await handle_intent( store, "t", IntentResult(intent="knowledge.query", params={"query": "知识清单"}, confidence=0.95, source="RULE_FAST"), actor="test", ) assert "机加工工艺路线生成总则" in reply2.text assert "知识库共" in reply2.text asyncio.run(_run()) def test_schedule_this_order_deixis(): """查完订单后「把这个订单排产」应命中 flex.schedule 并带上焦点订单。""" import asyncio from server.agent_core.session_focus import get_last_order_no w = _world_site() if not Path(DEFAULT_ROUTE_XLSX).exists() or not w.get("flexOrders"): return store = _Mem(w) sid = "deixis-sched" r = parse_fast("给我把这个订单进行计划排产", w) assert r and r.intent == "flex.schedule" assert r.params.get("orderRef") == "last" r2 = parse_fast("给订单 102285668 计划排产", w) assert r2 and r2.intent == "flex.schedule" assert r2.params.get("orderNo") == "102285668" async def _run(): q = parse_fast("查询订单 102285668", w) await handle_intent(store, sid, q, actor="test") assert get_last_order_no(sid) == "102285668" reply = await handle_intent(store, sid, r, actor="test") assert "闭环排产被阻断" in reply.text assert "102285668" in reply.text asyncio.run(_run()) def test_outsource_qa_and_plan_report(): """「这个订单有委外吗」可答;「生成排产方案报告」可下载。""" import asyncio from server.agent_core.session_focus import set_focus from server.aps_domain.flex import run_flex_schedule from server.aps_domain.reports import build_plan_report w = _world_site() if not Path(DEFAULT_ROUTE_XLSX).exists() or not w.get("flexOrders"): return store = _Mem(w) sid = "qa-report" r = parse_fast("这个订单有委外订单吗?", w) assert r and r.intent == "master.query" assert r.params.get("entity") == "mrp" assert r.params.get("orderRef") == "last" r_plan = parse_fast("生成排产方案报告", w) assert r_plan and r_plan.intent == "report.generate" assert r_plan.params.get("reportType") == "plan" run_flex_schedule(store, sort_mode="BOTTLENECK", actor="test") plan = build_plan_report(w, order_no="102285668") assert plan["reportId"] assert plan.get("xlsxBytes") assert plan["xlsxBytes"][:2] == b"PK" # zip/xlsx magic assert "工作计划" in plan["markdown"] or "Excel" in plan["markdown"] assert plan["snapshot"]["woCount"] == 0 assert plan["blocked"] is True async def _run(): set_focus(sid, orderNo="102285668") reply = await handle_intent(store, sid, r, actor="test") assert "委外" in reply.text assert "102285668" in reply.text reply2 = await handle_intent(store, sid, r_plan, actor="test") assert reply2.blocks and reply2.blocks[0].type == "report" assert "排产阻断分析报告" in reply2.blocks[0].props["title"] assert reply2.blocks[0].props.get("format") == "xlsx" assert reply2.blocks[0].props.get("downloadUrl") asyncio.run(_run())