feat: resolve shortage names from Git-synced Kingdee material cache

This commit is contained in:
ar51
2026-10-09 10:18:34 +08:00
parent ad7c45d2d6
commit cf31549415
12 changed files with 7813 additions and 7 deletions

View File

@@ -569,6 +569,58 @@ class UnavailableReasonTests(unittest.TestCase):
class ShortageMaterialNamesTests(unittest.TestCase):
def setUp(self) -> None:
patcher = mock.patch.object(bridge, "load_material_names", return_value={})
self.load_names = patcher.start()
self.addCleanup(patcher.stop)
def test_code_only_shortages_use_local_names_and_preserve_api_name_priority(self) -> None:
self.load_names.return_value = {"20.40.00001": "编码器", "20.50.00002": "轴承"}
lines = bridge.shortage_material_names_line([
{"缺料物料": "20.40.00001"},
{"缺料物料": " 20.50.00002 "},
{"缺料物料": "20.40.00001"},
{"缺料物料": "20.50.00002", "物料名称": "API更新后的轴承名称"},
])
self.assertEqual(lines, "- 缺料物料明细:编码器;轴承;API更新后的轴承名称")
self.load_names.assert_called_once_with()
self.assertNotIn("20.40", lines)
self.assertNotIn("20.50", lines)
def test_missing_or_invalid_cache_keeps_available_names_and_explains_failure(self) -> None:
for reason in ("本地物料名称缓存文件缺失", "本地物料名称缓存计数或完整性校验失败"):
with self.subTest(reason=reason):
self.load_names.side_effect = bridge.MaterialNameCacheError(reason)
line = bridge.shortage_material_names_line([
{"物料名称": "编码器"},
{"缺料物料": "20.50.00002"},
{"缺料物料": "20.50.00003"},
])
self.assertIn("编码器", line)
self.assertIn("2项缺料记录未找到物料名称", line)
self.assertIn(reason, line)
self.assertNotIn("20.50.", line)
def test_initial_and_continuation_code_only_shortages_resolve_offline(self) -> None:
request = bridge.RequestInput(model="eRob70H50I-FS-18CN[V5]", quantity=10)
self.load_names.return_value = {"20.40.00001": "编码器"}
def query(query_request: bridge.RequestInput) -> dict[str, object]:
payload = successful_payload()
payload["data"]["采购信息"]["缺料明细"] = [{"缺料物料": "20.40.00001"}]
return payload
for offset in (0, bridge.CANDIDATE_BATCH_SIZE):
with (
self.subTest(offset=offset),
mock.patch.object(bridge, "run_controlled_query", side_effect=query) as run_query,
mock.patch.object(bridge, "write_record"),
):
report = bridge.build_report(request, candidate_offset=offset)
self.assertEqual(report.count("- 缺料物料明细:编码器"), run_query.call_count)
self.assertNotIn("未找到物料名称", report)
self.assertNotIn("20.40.00001", report)
def test_all_shortage_names_are_shown_without_non_reducer_raw_fields(self) -> None:
payload = successful_payload()
payload["data"]["采购信息"]["缺料明细"] = [
@@ -601,7 +653,7 @@ class ShortageMaterialNamesTests(unittest.TestCase):
lines = bridge.lead_time_details(payload, requested_quantity=10)["evidence_lines"]
expected = "4项缺料记录未返回物料名称,需人工复核"
expected = "4项缺料记录未找到物料名称,请核对物料编码并更新本地名称缓存后复核"
if valid_name:
expected = f"轴承(另有{expected})"
self.assertEqual(lines, [f"- 缺料物料明细:{expected}"])