- 사전조합 대가 블록 규격 = 「내 자료집 · 회사 · 마스터」 · 키는 spec_raw(풍선) · 복사해 새 일위대가 창 규격은 빈 칸 - B09 설계내역서 구조물 줄 비고 = 「층 낱말 · 조합 이름」(옛 「personal|1/3|SP3-000015」) - M02 일위대가 격자 머리 = 번호꼴 일위대가번이면 이름 · 「일위대가」 · 참조 줄 비고 = 층 낱말 · 참조 창 제목 · 이미 담음 알림에서 키 뺌 - 내 자료집 저장 알림 · 같은 이름 물음에서 키 뺌 - 시험: test_704_3 격자 · test_701_1 비고 고침 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
129 lines
4.4 KiB
Python
129 lines
4.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""701-1 — 석축 · 옹벽 길이 → B08 구조물 집계표 열 · B09 설계내역서 구조물 줄(owners 수량).
|
|
|
|
견본: 옹벽 H=2.0 구간 100~112(12 m) · 돌쌓기(찰) H=2.0 구간 196~204(옛 길이 칸 99 안 씀) ·
|
|
돌쌓기(찰) 높이 빈칸(null · 금액 안 듦 = 값 빈칸) · 큰돌쌓기 사본 없음(안 셈 · 미연결)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from B08_Quantity import B08_Quantity_Router_Summary as summary
|
|
from B09_Estimation.B09_Estimation_Bill_Items import structure_items
|
|
from M02_MasterTemplete.StructOptions import M02_SO_Definition as definition
|
|
|
|
|
|
def _item(key: str) -> dict:
|
|
return {"layer": "system", "owner": None, "key": key, "name": key}
|
|
|
|
|
|
STRUCTURES = [
|
|
{
|
|
"structure_id": "s-wall",
|
|
"type_id": "retaining_wall",
|
|
"placement": "interval",
|
|
"chainage_m": 106,
|
|
"start_m": 100,
|
|
"end_m": 112,
|
|
"options": {"height_m": 2},
|
|
"summary_item": _item("SS000201"),
|
|
},
|
|
{
|
|
"structure_id": "s-wet",
|
|
"type_id": "masonry_wet",
|
|
"placement": "interval",
|
|
"chainage_m": 200,
|
|
"start_m": 196,
|
|
"end_m": 204,
|
|
"options": {"height_m": 2.0, "length_m": 99},
|
|
"summary_item": _item("SS000202"),
|
|
},
|
|
{
|
|
"structure_id": "s-wet-blank",
|
|
"type_id": "masonry_wet",
|
|
"placement": "interval",
|
|
"chainage_m": 300,
|
|
"start_m": 295,
|
|
"end_m": 305,
|
|
"options": {"height_m": None},
|
|
"summary_item": _item("SS000202"),
|
|
},
|
|
{
|
|
"structure_id": "s-boulder",
|
|
"type_id": "boulder_masonry",
|
|
"placement": "interval",
|
|
"chainage_m": 400,
|
|
"start_m": 395,
|
|
"end_m": 405,
|
|
"options": {"height_m": 3},
|
|
"summary_item": _item("SS000203"),
|
|
},
|
|
]
|
|
|
|
|
|
@pytest.fixture
|
|
def out(tmp_path: Path) -> dict:
|
|
root = tmp_path / "proj"
|
|
route = root / "B05_Profile/route"
|
|
route.mkdir(parents=True)
|
|
(route / "structures.json").write_text(
|
|
json.dumps({"revision": 1, "structures": STRUCTURES}, ensure_ascii=False),
|
|
encoding="utf-8",
|
|
)
|
|
names = definition.read()["종류"]["pipe"]["이름"]
|
|
linked = {"s-wall": {}, "s-wet": {}, "s-wet-blank": {}} # 큰돌쌓기 = 사본 없음
|
|
return summary.pipe_summary(root, [], names, 6.0, linked=linked)
|
|
|
|
|
|
def _col(out: dict, cid: str) -> dict:
|
|
return next(c for c in out["columns"] if c["id"] == cid)
|
|
|
|
|
|
def test_옹벽_석축_높이마다_길이_열(out):
|
|
wall = _col(out, "pipe:wall|retaining_wall|2.0")
|
|
assert wall["group"] == ["옹벽", "H=2.0"] and wall["label"] == "m"
|
|
assert wall["combos"] == ["system||SS000201"]
|
|
assert wall["owners"] == {"s-wall": 12.0} # 구간 시작~종료
|
|
wet = _col(out, "pipe:wall|masonry_wet|2.0")
|
|
assert wet["owners"] == {"s-wet": 8.0} # 구간이 옛 길이 칸을 이김
|
|
assert out["total"]["pipe:wall|retaining_wall|2.0"] == 12.0
|
|
|
|
|
|
def test_빈_높이_미입력_열_값_빈칸(out):
|
|
blank = _col(out, "pipe:wall|masonry_wet|-")
|
|
assert blank["group"] == ["돌쌓기(찰)", "미입력"]
|
|
assert blank["owners"] == {} and "pipe:wall|masonry_wet|-" not in out["total"]
|
|
|
|
|
|
def test_사본_없는_벽_안_셈_미연결(out):
|
|
assert not any("boulder_masonry" in c["id"] for c in out["columns"])
|
|
assert [f["id"] for f in out["unlinked"]] == ["s-boulder"]
|
|
assert {"retaining_wall", "masonry_wet", "boulder_masonry"} <= set(out["types"])
|
|
|
|
|
|
def test_B09_구조물_줄_기타구조물_수량(out):
|
|
rows = {r["key"]: r for r in structure_items(out)}
|
|
wall = rows["st:pipe:wall|retaining_wall|2.0"]
|
|
assert (wall["section"], wall["name"], wall["spec"], wall["unit"]) == (
|
|
"2.3",
|
|
"옹벽",
|
|
"H=2.0",
|
|
"m",
|
|
)
|
|
assert wall["qty"] == 12.0 and wall["owners"] == {"s-wall": 12.0}
|
|
assert rows["st:pipe:wall|masonry_wet|-"]["qty"] is None
|
|
|
|
|
|
def test_B09_금액_길이_곱하기_대가(out):
|
|
from B09_Estimation.B09_Estimation_Calc_Bill import compute_estimation
|
|
|
|
price = {"no": "대가1", "key": "blk:w", "labor": 96868, "material": 11309, "expense": 16417}
|
|
inputs = {"bill": {"items": structure_items(out)}}
|
|
sheets = compute_estimation(inputs, {}, {"s-wall": price}.get)
|
|
row = next(r for r in sheets["bill"]["rows"] if r["key"].endswith("#blk:w"))
|
|
assert (row["qty"], row["sum"], row["note"]) == (12.0, 1495128, "대가1 · 마스터")
|