2026-08-11 00:54:05 +08:00
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
import shutil
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
|
|
from server.aps_domain.drawing_dxf import inspect_dxf
|
|
|
|
|
|
from server.aps_domain.folder_pack import analyze_work_dir
|
|
|
|
|
|
from server.state.seed import seed_world
|
2026-09-08 00:07:26 +08:00
|
|
|
|
from tests.external_data import external_dir
|
2026-08-11 00:54:05 +08:00
|
|
|
|
|
2026-09-08 00:07:26 +08:00
|
|
|
|
_DEFAULT_SAMPLE = external_dir("RUIYANG_DEMO_DIR", "ruiyang") / "5060102101-001-e(1).dxf"
|
2026-08-11 00:54:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _sample_dxf() -> Path:
|
|
|
|
|
|
try:
|
|
|
|
|
|
import ezdxf # noqa: F401
|
|
|
|
|
|
except ImportError as exc:
|
|
|
|
|
|
pytest.skip(f"DXF 运行依赖未完整安装:{exc}; 需要 ezdxf 及其 fontTools 依赖")
|
|
|
|
|
|
path = Path(os.environ.get("APS_DXF_SAMPLE", str(_DEFAULT_SAMPLE)))
|
|
|
|
|
|
if not path.is_file():
|
|
|
|
|
|
pytest.skip(f"真实 DXF 样例不存在:{path};可通过 APS_DXF_SAMPLE 指定")
|
|
|
|
|
|
return path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _bind_project(monkeypatch: pytest.MonkeyPatch, work_dir: Path) -> None:
|
|
|
|
|
|
class FakeProjectStore:
|
|
|
|
|
|
def snapshot(self, include_messages: bool = False):
|
|
|
|
|
|
return {
|
|
|
|
|
|
"projects": [{"id": "p-dxf", "name": "DXF验收项目", "workDir": str(work_dir)}],
|
|
|
|
|
|
"sessions": [{"id": "s-dxf", "projectId": "p-dxf"}],
|
|
|
|
|
|
"files": [],
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
monkeypatch.setattr("server.state.projects.get_project_store", lambda: FakeProjectStore())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_real_dxf_is_discoverable_and_has_stable_identity():
|
|
|
|
|
|
parsed = inspect_dxf(_sample_dxf())
|
|
|
|
|
|
|
|
|
|
|
|
assert parsed["contractVersion"] == "drawing-dxf.v1"
|
|
|
|
|
|
assert parsed["asset"]["kind"] == "DXF"
|
|
|
|
|
|
assert parsed["asset"]["filename"].lower().endswith(".dxf")
|
|
|
|
|
|
assert parsed["asset"]["sizeBytes"] > 1_000_000
|
|
|
|
|
|
assert len(parsed["asset"]["sha256"]) == 64
|
|
|
|
|
|
assert parsed["asset"]["idempotencyKey"] == f'drawing:{parsed["asset"]["sha256"]}'
|
|
|
|
|
|
assert parsed["drawing"]["drawingNumber"] == "5060102101-001"
|
|
|
|
|
|
assert parsed["drawing"]["revision"].lower() == "e"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_project_folder_contract_discovers_dxf_without_treating_it_as_tabular(monkeypatch, tmp_path: Path):
|
|
|
|
|
|
sample = _sample_dxf()
|
|
|
|
|
|
copied = tmp_path / sample.name
|
|
|
|
|
|
shutil.copyfile(sample, copied)
|
|
|
|
|
|
_bind_project(monkeypatch, tmp_path)
|
|
|
|
|
|
|
|
|
|
|
|
report = analyze_work_dir(seed_world(), "s-dxf")
|
|
|
|
|
|
drawing_rows = report.get("drawings") or [
|
|
|
|
|
|
row for row in report.get("files", [])
|
|
|
|
|
|
if str(row.get("name") or "").lower().endswith(".dxf")
|
|
|
|
|
|
]
|
|
|
|
|
|
if not drawing_rows:
|
|
|
|
|
|
pytest.skip(
|
|
|
|
|
|
"依赖未合并:folder_pack.analyze_work_dir 尚未返回 drawings 或 DXF 文件行;"
|
|
|
|
|
|
"接线后本契约要求工程目录可发现 DXF,且不把它计入 Excel/CSV 有效行。"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert any(str(row.get("name") or "").lower() == copied.name.lower() for row in drawing_rows)
|
|
|
|
|
|
assert report["totalOk"] == 0
|
|
|
|
|
|
assert report["totalErrors"] == 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_folder_pack_without_dxf_keeps_existing_tabular_behavior(monkeypatch, tmp_path: Path):
|
|
|
|
|
|
(tmp_path / "订单.csv").write_text(
|
|
|
|
|
|
"订单号,产品编码,数量,交期,客户\nSO-DXF-REG,P-1,10,2026-08-20,验收客户\n",
|
|
|
|
|
|
encoding="utf-8-sig",
|
|
|
|
|
|
)
|
|
|
|
|
|
(tmp_path / "物料.csv").write_text(
|
|
|
|
|
|
"编码,名称,类型,单位,库存\nP-1,回归成品,FINISHED_PRODUCT,件,100\n",
|
|
|
|
|
|
encoding="utf-8-sig",
|
|
|
|
|
|
)
|
|
|
|
|
|
_bind_project(monkeypatch, tmp_path)
|
|
|
|
|
|
|
|
|
|
|
|
report = analyze_work_dir(seed_world(), "s-dxf")
|
|
|
|
|
|
|
|
|
|
|
|
assert report["ok"] is True
|
|
|
|
|
|
assert report["totalOk"] >= 1
|
|
|
|
|
|
assert report["totalErrors"] == 0
|
|
|
|
|
|
assert any(row["name"] == "订单.csv" for row in report["files"])
|
|
|
|
|
|
assert not any(str(row.get("name") or "").lower().endswith(".dxf") for row in report["files"])
|