"""STMATE 재현 앱 단가산출근거(D코드) 재계산 — COSTN.SMT 식을 다시 셈해 실무 STC 저장 단가와 1원 대조. 정답 = STC 의 COSTN 저장 단가(낙찰률 단가는 2칸 원단가). 참조 단가(X·L·M·S)는 저장값을 씀. 변경설계 파일(영덕 변경 · 소광 변경1차)의 산근은 설계변경 기능 몫 — 낙찰률 규칙만 대조. """ import json import subprocess import sys from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT / "tools/stmate-test")) import server # noqa: E402 HELPER = Path(__file__).with_name("helper_stmate_smt.cjs") DOCS = ROOT / "resources/knowledge/original/실무문서" ORIGINAL = { "봉화2024": "04.산불 봉화/01. 내역서/13-2024년 산불진화임도 실시설계(기번41_현동)_ L=3.46km.STC", "울진2025": "25년 산불진화임도(기번8)(울진소광)/2025년 산불진화임도 신설사업(기번8 울진.금강송.소광.산29외).STC", "영월2024": "05. 동부청 영월/내역서/2024년 임도시설사업2차(산불진화_기번6)-영월.STC", "대흥2024": "2024년 간선임도(기번3-울진.대흥)(공통)/1. 설계원본/01 내역자료/2024년 간선임도사업(기번3).STC", "소광원설계": "25년 산불진화임도(기번8)(울진소광)/1. 설계원본/03-내역/22-2025년 산불진화임도사업(울진 금강송 소광).STC", } CHANGED = { "영덕변경": "20250527 2025년 계류보전사업(기번1-영덕.병곡.영리.산214-1)(변경)/01.내역자료/2025년 계류보전사업(기번1 영덕.병곡.영.산214)(변경).STC", "소광변경1차": "25년 산불진화임도(기번8)(울진소광)/변경 1차분-2025년 산불진화임도 신설사업(기번8 울진.금강송.소광.산29외).STC", } def run(rel): loaded = server.api_load(server.LoadReq(source_path=str(DOCS / rel))) payload = { "costn_rows": loaded["costn_rows"], "memos": {k: v["text"] for k, v in loaded["costn_memos"].items()}, "start_ini": loaded["start_ini"], } out = subprocess.check_output( ["node", str(HELPER)], input=json.dumps(payload, ensure_ascii=False), text=True, encoding="utf-8", ) return loaded, json.loads(out) @pytest.mark.parametrize("name", list(ORIGINAL)) def test_d_codes_match_stored_unit_prices(name): loaded, out = run(ORIGINAL[name]) rows = {r["CODE"].strip(): r for r in loaded["costn_rows"]} assert out["smt"], f"{name} 산근 없음" diffs = {} for code, got in out["smt"].items(): r = rows[code] slot = 2 if float(r.get("NAGCD") or 0) > 0 else 1 exp = [float(r[f"{k}AMT{slot}"]) for k in "MLS"] if any(abs(g - e) >= 0.5 for g, e in zip(got, exp)): diffs[code] = (got, exp) assert not diffs, f"{name} 산근 불일치 {len(diffs)}/{len(out['smt'])} {list(diffs.items())[:5]}" @pytest.mark.parametrize("name", list(ORIGINAL) + list(CHANGED)) def test_bid_rate_unit_prices(name): loaded, out = run({**ORIGINAL, **CHANGED}[name]) rows = {r["CODE"].strip(): r for r in loaded["costn_rows"]} for code, m, l, s in out["bid"]: exp = [float(rows[code][f"{k}AMT1"]) for k in "MLS"] assert [m, l, s] == exp, (name, code, [m, l, s], exp)