# ============================================================ # M-A 黄金测试:通用 Excel 导入器(profile 配置化,康尼零硬编码) # ============================================================ from __future__ import annotations from pathlib import Path import pytest from server.aps_domain.kangni_intake import DEFAULT_ROUTE_XLSX, load_site_into_world from server.importers import list_profiles, load_profile from server.state.seed import seed_world ROUTE = Path(DEFAULT_ROUTE_XLSX) def test_kangni_profile_holds_site_constants(): """工厂命名/工时推断规则等在 profile 中维护,代码不再写死。""" prof = load_profile("kangni") assert prof["projectCode"] == "kangni" assert prof["factory"]["name"] == "城轨机构装配工厂" assert prof["inferStdMin"]["部装"] == 45.0 assert prof["inferStdMin"]["装配"] == 30.0 assert prof["stationCount"] == 4 assert any(p["profileId"] == "kangni" for p in list_profiles()) def test_missing_profile_returns_empty(): assert load_profile("no-such-customer") == {} @pytest.mark.skipif(not ROUTE.exists(), reason="现场 Excel 不在本机") def test_profile_overrides_flow_into_world(monkeypatch): """改 profile 的工厂名 → 导入结果跟着变(证明读配置而非硬编码)。""" world = seed_world() custom = dict(load_profile("kangni")) custom["factory"] = {"code": "X-F01", "name": "泛用机加工厂", "timezone": "Asia/Shanghai"} custom["inferStdMin"] = {"部装": 50.0, "装配": 30.0, "_default": 30.0} meta = load_site_into_world(world, route_path=ROUTE, clear_all=True, profile=custom) assert meta["primaryOrder"] == "102285668" assert world["factories"][0]["name"] == "泛用机加工厂" # 部装类推断工时按新规则 50 分钟 assert any( r.get("stdTimeSource") == "推断" and r["stdTimePerUnit"] == 50.0 for r in world["flexRoutings"] ) @pytest.mark.skipif(not ROUTE.exists(), reason="现场 Excel 不在本机") def test_import_marks_std_time_source(monkeypatch): """导入后每条柔性路线都带工时来源标记(实测/推断)。""" world = seed_world() load_site_into_world(world, route_path=ROUTE, clear_all=True) assert world["flexRoutings"] assert all(r.get("stdTimeSource") in ("实测", "推断") for r in world["flexRoutings"]) assert all(s.get("stdTimeSource") in ("实测", "推断") for s in world["routingSteps"])