Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
115 lines
5.0 KiB
Python
115 lines
5.0 KiB
Python
"""규준틀 재료 — **세는 것은 확정이고 수량만 몰랐던 자리** (2026-09-09).
|
||
|
||
품셈 11-2·11-3 [주]④ 「재료량은 **설계수량에 따른다**」 ⇒ 품셈이 값을 안 주는 것이지
|
||
「안 센다」가 아니다. 근주이식·임목파쇄(**셀지 말지가 설계 판단**)와 성격이 다르다.
|
||
그래서 **제안값을 보이고 고칠 수 있게** 둔다 — 확정 ⑨·⑩ 과 같은 틀.
|
||
|
||
⚠ 겨누는 것 여섯
|
||
① 개소가 서면 재료도 선다
|
||
② ⚠ 개소가 안 서면 재료도 안 선다 — 밑수가 그 줄이다
|
||
③ 값은 **제안값**이고 산출 조건이 이긴다
|
||
④ ⚠ 제안값이 **실무 관측값이지 법정 기준이 아님**이 사유에 적힌다
|
||
⑤ 손율은 원문값이 함께 적힌다(비탈 50% · 수평 80%)
|
||
⑥ 자재 축으로 간다(할증은 자재총괄에서 한 번만)
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parents[2]
|
||
sys.path.insert(0, str(ROOT))
|
||
|
||
from B08_Quantity.B08_Quantity_Engine_Preparation import ( # noqa: E402
|
||
FRAME_MATERIAL_SUGGESTED,
|
||
frame_material_rows,
|
||
)
|
||
|
||
규준틀 = [
|
||
{"item": "비탈 규준틀", "unit": "개소", "amount": 28.0},
|
||
{"item": "수평 규준틀", "unit": "개소", "amount": 33.0},
|
||
]
|
||
|
||
|
||
def 이름별(rows: list[dict]) -> dict:
|
||
return {(row["source"], f"{row['name']} {row.get('spec', '')}".strip()): row for row in rows}
|
||
|
||
|
||
def test_이름과_규격을_가른다() -> None:
|
||
"""이름 칸에 규격을 섞으면 할증률표(각재 5 · 판재 10)와 안 맞음 — 관급구분 키는 그대로."""
|
||
from B08_Quantity.B08_Quantity_Engine_MaterialSummary import build_table
|
||
|
||
rows = frame_material_rows(규준틀)
|
||
assert {(row["name"], row["spec"]) for row in rows} == {
|
||
("각재", "50×50"),
|
||
("판재", "T12"),
|
||
("못", ""),
|
||
}
|
||
table = build_table({"structures": []}, extra_materials=rows)
|
||
rates = {row["supply_key"]: row["surcharge_pct"] for row in table["rows"]}
|
||
assert rates == {"각재 50×50": 5, "판재 T12": 10, "못": None}
|
||
|
||
|
||
def test_개소가_서면_재료도_선다() -> None:
|
||
rows = 이름별(frame_material_rows(규준틀))
|
||
assert abs(rows[("비탈 규준틀", "각재 50×50")]["amount"] - 28.0 * 0.0044) < 1e-9
|
||
assert abs(rows[("수평 규준틀", "못")]["amount"] - 33.0 * 0.03) < 1e-9
|
||
|
||
|
||
def test_개소가_안_서면_재료도_안_선다() -> None:
|
||
"""⚠ 밑수가 개소 줄이다 — 개소가 없으면 재료를 지어내지 않는다."""
|
||
assert frame_material_rows([{"item": "비탈 규준틀", "amount": None}]) == []
|
||
|
||
|
||
def test_산출_조건이_이긴다() -> None:
|
||
rows = 이름별(frame_material_rows(규준틀, {"못": 0.05}))
|
||
assert abs(rows[("비탈 규준틀", "못")]["amount"] - 28.0 * 0.05) < 1e-9
|
||
assert "고른 값" in rows[("비탈 규준틀", "못")]["basis"]
|
||
|
||
|
||
def test_관측값이지_법정_기준이_아님이_적힌다() -> None:
|
||
"""⚠ 값만 박고 근거를 안 보이면 「대신 페이지에 남길 것」 지시를 어기는 것이다."""
|
||
basis = 이름별(frame_material_rows(규준틀))[("비탈 규준틀", "각재 50×50")]["basis"]
|
||
assert "실무 관측값" in basis and "법정 기준 아님" in basis
|
||
assert "설계수량에 따른다" in basis
|
||
|
||
|
||
def test_손율이_원문값으로_적힌다() -> None:
|
||
rows = 이름별(frame_material_rows(규준틀))
|
||
assert "손율 50%" in rows[("비탈 규준틀", "판재 T12")]["basis"]
|
||
assert "손율 80%" in rows[("수평 규준틀", "판재 T12")]["basis"]
|
||
|
||
|
||
def test_자재_축으로_간다() -> None:
|
||
assert all(row["destination"] == "material" for row in frame_material_rows(규준틀))
|
||
|
||
|
||
def test_화면과_인계가_같은_한_벌을_부른다() -> None:
|
||
"""자재총괄 화면(6줄)·인계(9줄)가 갈리던 자리 — 규준틀 재료를 한 곳에서 얹음(2026-09-14).
|
||
|
||
⚠ 두 라우터가 이 함수를 부르는지까지 본다 — 한쪽이 옛 길로 돌아가면 다시 갈림.
|
||
"""
|
||
import inspect
|
||
|
||
from B08_Quantity import B08_Quantity_Router_Material as router
|
||
|
||
table = router.material_table_for(
|
||
{"structures": []},
|
||
{"material_supply": {"각재 50×50": "owner_supplied"}},
|
||
{"rows": 규준틀},
|
||
)
|
||
keys = {row["supply_key"]: row for row in table["rows"]}
|
||
assert set(keys) == {"각재 50×50", "판재 T12", "못"}
|
||
assert keys["각재 50×50"]["supply"] == "owner_supplied" # 화면에서 고른 값이 먹음
|
||
for route in (router.get_material_summary, router.get_handoff):
|
||
source = inspect.getsource(route)
|
||
assert "material_table_for(" in source and "build_material_table(" not in source
|
||
|
||
|
||
def test_제안값이_실무_관측값과_같다() -> None:
|
||
"""울진 소광 §8 — 각재 50×50 0.0044㎥ · 판재 T12 0.0029㎥ · 못 0.03㎏(개소당)."""
|
||
assert FRAME_MATERIAL_SUGGESTED["각재 50×50"][0] == 0.0044
|
||
assert FRAME_MATERIAL_SUGGESTED["판재 T12"][0] == 0.0029
|
||
assert FRAME_MATERIAL_SUGGESTED["못"][0] == 0.03
|