Files
Aislo/resources/tester/test_b08_frame_material.py
T

115 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""규준틀 재료 — **세는 것은 확정이고 수량만 몰랐던 자리** (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