"""157-4 B09 일위대가표 품셈 규격 — 기계 · 직종 원문번호 → 「이름 규격」 · 번호 = 풍선(157-3 `raw`). - 품셈 블록 `spec` = 「기계 굴착기(무한궤도) 0.6㎥ · …」 · `spec_raw` = 옛 글(번호) · 줄 그대로 - 일위대가목록표 · 일위대가표 규격 칸 풍선 = 「원문번호 …」(바꾼 칸만) """ import json import re import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) from B09_Estimation import B09_Estimation_Labor_Source as source # noqa: E402 from M02_MasterTemplete import M02_Item_Prices as item_prices # noqa: E402 B09 = ROOT / "B09_Estimation" IMPORTS = re.compile(r"^import[^;]*;\n", re.MULTILINE) def _block(code, given): whole = item_prices.load_prices(item_prices.to_json(item_prices.collect([code]))) builder = source.Builder() bid = builder.poomsem(whole, {"로직": code, "입력값": given}) return builder.blocks[bid] def test_기계_번호는_이름_규격_번호는_spec_raw(): given = {"기계": "0201-0060", "지역": "전국평균", "보정작업": "해당 없음"} block = _block("GC000267", given) assert block["spec"] == "기계 굴착기(무한궤도) 0.6㎥ · 보정작업 해당 없음 · 지역 전국평균" assert block["spec_raw"] == "기계 0201-0060 · 보정작업 해당 없음 · 지역 전국평균" assert len(block["lines"]) == 4 def test_직종_번호도_이름(): given = {"기계": "2106-0002", "지역": "전국평균", "조종원직종": "1048"} block = _block("GC000275", given) assert "1048" in block["spec_raw"] and "1048" not in block["spec"] assert not re.search(r"\d{4}-\d{4}", block["spec"]) def test_규격_칸_풍선(): spec, raw = "기계 굴착기(무한궤도) 0.6㎥", "기계 0201-0060" sheets = { "daega": [{"no": 1, "key": "DG:a", "kind": "품셈", "name": "n", "spec": spec, "spec_raw": raw, "unit": "시간"}], "daega_blocks": [{"id": "DG:a", "no": 1, "kind": "품셈", "name": "n", "spec": spec, "spec_raw": raw, "unit": "시간", "cite": "", "lines": [ {"kind": "daega", "key": "DG:a", "name": "n", "spec": spec, "spec_raw": raw, "qty": 1, "unit": "시간", "price": 1, "amount": 1, "prices": {"labor": 1, "material": 0, "expense": 0}, "amounts": {"labor": 1, "material": 0, "expense": 0}}], "labor": 1, "material": 0, "expense": 0, "sum": 1}], } # fmt: skip sangeun = (B09 / "B09_Estimation_UI_Tabs_Sangeun.ts").read_text("utf-8") src = re.search(r"^export const raw =.*?;$", sangeun, re.MULTILINE | re.DOTALL)[0] + "".join( IMPORTS.sub("", (B09 / f"B09_Estimation_{n}.ts").read_text("utf-8")) for n in ("UI_Tabs", "UI_Tabs_Labor") ) # 산근 탭의 풍선 함수 `raw` 만(같은 이름 상수가 겹쳐 파일째는 못 잇음) body = f""" const sheets = {json.dumps(sheets, ensure_ascii=False)}; const list = buildDaegaList({{ sheets }}); const blocks = buildDaegaBlocks({{ sheets }}); console.log(JSON.stringify({{ list: list.tip(0, "spec"), listName: list.tip(0, "name"), head: blocks.tip(0, "spec"), line: blocks.tip(1, "spec"), total: blocks.tip(2, "spec"), }}));""" result = subprocess.run( ["node", "--experimental-strip-types", "--no-warnings", "--input-type=module-typescript", "-e", src + body], capture_output=True, text=True, encoding="utf-8", timeout=60, ) # fmt: skip assert result.returncode == 0, result.stderr got = json.loads(result.stdout) tip = "원문번호 기계 0201-0060" assert got == {"list": tip, "listName": None, "head": tip, "line": tip, "total": None}