"""183-1 재료비목록표 = 연결된 일위대가 · 산근 · 중기가 쓰는 자재만 · 수량 · 단가 한 줄 · 쓰는 곳. - 수요: 사본 일위대가 자재 · 굳힌 사전조합 자재 코드도 든다(`Linked.used_keys`) - 거름: 대가 · 산근 · 중기 블록 재료 줄 · B08 줄 · 관급 · 별도 줄만 남김(`Summary.used_materials`) - 수량 = 입력 `material_qty`(1차 역전개 총수량) — `Calc_Base` 짝 거울 · 두 번 셈(`Router.compute_twice`) - 화면 비고 = 쓰는 곳(`UI_Tabs_Base.usesOf`) """ import json from pathlib import Path from B09_Estimation import B09_Estimation_Router as router_mod from B09_Estimation.B09_Estimation_Calc_Base import compute_base from B09_Estimation.B09_Estimation_Linked import used_keys from B09_Estimation.B09_Estimation_Summary import used_materials from resources.tester.test_144_b09_base_calc import _run_ts ROOT = Path(__file__).resolve().parents[2] MATERIALS = [ {"key": "MT1", "name": "쓰는 자재", "prices": {"물가자료": 1000}}, {"key": "MT2", "name": "고르기 후보", "prices": {"물가자료": 500}}, {"key": "MT3", "name": "관급 표시", "prices": {"물가자료": 300}}, {"key": "MO1", "name": "경유", "prices": {"유가": 1800}}, {"key": "b08:pipe_800", "name": "파형강관", "prices": {}, "qty": 8, "supply": "관급"}, ] USER = {"materials": {"MT3": {"supply": "관급"}}} SG = [{"key": "SG1", "no": 1, "lines": [{"kind": "material", "ref": {"key": "MT1"}, "qty": 2}]}] MACHINE = [{"key": "EQ1", "lines": [{"kind": "material", "ref": {"key": "MO1"}, "qty": None}]}] def test_사본_일위대가_자재_사전조합_자재_코드도_수요(tmp_path): labor = { "줄": {"담은로직": [], "자재": [{"코드": "MT000053"}, {"코드": "PM000001"}]}, "참조사본": {"참조|system||SC-000001": {"담은로직": [], "자재": [{"코드": "MT000008"}]}}, } (tmp_path / "일위대가.json").write_text(json.dumps(labor, ensure_ascii=False), "utf-8") assert used_keys(tmp_path) == ["MT000053", "MT000008"] # 개인 자재(PM) = 원가 표 밖 def test_쓰는_자재만_남김(): sheets = {"sg": SG, "daega_blocks": [], "machine_blocks": MACHINE} inputs = {"materials": MATERIALS} assert used_materials(sheets, inputs, USER) == {"MT1", "MO1", "MT3", "b08:pipe_800"} def test_수량_원천_material_qty_거울(): inputs = {"labor": [], "machines": [], "materials": MATERIALS} old = {r["key"]: r["qty"] for r in compute_base(inputs, USER)["material"]} assert old["b08:pipe_800"] == 8 and old["MT1"] is None # 없으면 입력 줄 수량(지금 길) got = compute_base({**inputs, "material_qty": {"MT1": 6, "b08:pipe_800": 8}}, USER) rows = {r["key"]: r for r in got["material"]} assert (rows["MT1"]["qty"], rows["MT1"]["amount"]) == (6, 6000) assert rows["MT2"]["qty"] is None and rows["MT2"]["amount"] is None # 없는 키 = 빈칸 for case in (inputs, {**inputs, "material_qty": {"MT1": 6}}): assert _run_ts(case, USER) == compute_base(case, USER) def test_두_번_셈_후보_줄_빠지고_수량_역전개(monkeypatch): calls = [] def fake(root, inputs, user): calls.append([m["key"] for m in inputs["materials"]]) base = compute_base(inputs, user) bill = {"rows": [{"kind": "item", "qty": 3, "ref": {"tab": "sg", "key": "SG1"}}]} return {**base, "sg": SG, "daega_blocks": [], "machine_blocks": MACHINE, "bill": bill} monkeypatch.setattr(router_mod, "compute_sheets", fake) inputs = {"labor": [], "machines": [], "materials": list(MATERIALS)} sheets, summary = router_mod.compute_twice(Path("."), inputs, USER) assert calls[0] == [m["key"] for m in MATERIALS] assert calls[1] == ["MT1", "MT3", "MO1", "b08:pipe_800"] # 후보 MT2 뺌 assert inputs["material_qty"] == {"MT1": 6.0} # 설계내역서 3 × 호표 2 rows = {r["key"]: r for r in sheets["material"]} assert (rows["MT1"]["qty"], rows["MT1"]["amount"]) == (6.0, 6000) assert [r["qty"] for r in summary["sum_material"]] == [rows["MT1"]["qty"]] # 집계표와 같은 값 def test_화면_비고_쓰는_곳(): src = (ROOT / "B09_Estimation" / "B09_Estimation_UI_Tabs_Base.ts").read_text(encoding="utf-8") for label in ( "`대가 ${b.no}호표`", "`산근 ${b.no}호표`", "`중기 ${n + 1}호표`", '"내역 자재대"', ): assert label in src assert 'text("uses", "비고(쓰는 곳)"' in src and 'text("origin", "비고"' not in src