"""설계서 구성표 — 법이 정한 목차와 우리가 내는 것 (2026-09-09). 산림자원법 시행규칙 [별표2] (5)(가) 가 **설계서 작성 순서를 열셋으로 못 박아** 두었다. 그 목록과 우리 화면을 맞대 두지 않으면 「무엇을 못 내는가」가 계획서에만 남는다. ⚠ 겨누는 것 넷 ① 법이 적은 **차례 그대로**다 — 순서를 우리가 바꾸지 않는다 ② **「없음」과 「우리 몫 아님」을 가른다** — 시방서·예정공정표는 설계자가 쓰는 문서다 ③ 「반쪽」은 반쪽이라 적는다 — 중기경비계산서·산출기초 ④ 못 내는 것에는 **무엇을 받아야 내는지**가 적혀 있다 """ from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT)) from B09_Estimation.B09_Estimation_DesignDocIndex import ( # noqa: E402 DESIGN_DOC_ITEMS, OWNER_DESIGNER, OWNER_PROGRAM, STATUS_MISSING, STATUS_PARTIAL, STATUS_READY, design_doc_index, ) #: 별표2 (5)(가) 원문 차례. _LAW_ORDER = ( "목차", "공사설명서", "일반시방서", "특별시방서", "예정공정표", "예산내역서", "일위대가표", "단가산출서", "각종 중기경비계산서", "공종별 수량계산서", "각종 소요자재총괄표", "토적표", "산출기초", ) def test_법이_적은_차례_그대로다() -> None: assert tuple(item["name"] for item in DESIGN_DOC_ITEMS) == _LAW_ORDER assert [item["order"] for item in DESIGN_DOC_ITEMS] == list(range(1, 14)) def test_설계자_몫과_우리_몫을_가른다() -> None: """② 「없음」 넷 가운데 셋은 **애초에 우리가 만들 것이 아니다.**""" theirs = {item["name"] for item in DESIGN_DOC_ITEMS if item["owner"] == OWNER_DESIGNER} assert theirs == {"일반시방서", "특별시방서", "예정공정표"} for item in DESIGN_DOC_ITEMS: if item["owner"] == OWNER_DESIGNER: assert item["status"] == STATUS_MISSING def test_반쪽이_남지_않았다() -> None: """⚠ 2026-09-09 밤 — 중기경비계산서·산출기초를 차례로 세우며 **반쪽이 다 없어졌다.** 이제 우리 몫 가운데 「없음」은 공사설명서 하나이고, 그것은 **서식·설계하중 표기를 사용자에게 받아야** 서는 자리다. """ partial = {item["name"] for item in DESIGN_DOC_ITEMS if item["status"] == STATUS_PARTIAL} assert partial == set() ours_missing = { item["name"] for item in DESIGN_DOC_ITEMS if item["owner"] == OWNER_PROGRAM and item["status"] != STATUS_READY } assert ours_missing == {"공사설명서"} def test_서는_것은_어디서_나오는지_적혀_있다() -> None: for item in DESIGN_DOC_ITEMS: if item["status"] == STATUS_READY: assert item["where"], f"{item['name']}: 어느 화면인지 안 적혀 있음" def test_못_내는_것에는_무엇이_필요한지_적혀_있다() -> None: """④ 「없음」으로만 두면 다음 사람이 무엇부터 해야 할지 모른다.""" for item in DESIGN_DOC_ITEMS: if item["status"] != STATUS_READY: assert item["note"].strip(), f"{item['name']}: 사유가 비어 있음" def test_요약이_셈과_맞는다() -> None: data = design_doc_index() assert data["counts"][STATUS_READY] == 9 assert sum(data["counts"].values()) == len(DESIGN_DOC_ITEMS) ours_missing = [ item["name"] for item in DESIGN_DOC_ITEMS if item["owner"] == OWNER_PROGRAM and item["status"] != STATUS_READY ] for name in ours_missing: assert name in data["summary"]