936be972 실측: 고정형(봉화 제6호표) 가져오기 → 구조물터파기·되메우기·잔토·버림 타설 전과 같음(전엔 −6,037,712원) · 본체 차이는 미완으로 금액 밖이 된 돌쌓기 2줄 −4,062,480 뿐 · 되돌려 전부 같음 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
90 lines
3.7 KiB
Python
90 lines
3.7 KiB
Python
"""㉯ 양식이 안 품은 토공·버림 성분은 전개 값을 남김 (2026-09-14 브레인 판정 · 목록으로 못박음).
|
||
|
||
실측(936be972): STmate 호표(고정형)를 가져오니 전개 성분이 통째로 갈음돼 구조물터파기 85.25→25㎥
|
||
(−6,037,712원) · 되메우기·잔토·버림 타설도 줄었음. STmate 호표는 원래 토공을 안 품음(토공 따로 셈).
|
||
규칙 — `KEEP_ENGINE_COMPONENTS` 목록에 있는 이름은 **양식에 그 이름 줄이 없을 때** 전개 값을 보존,
|
||
목록에 없는 성분은 양식으로 갈음. 양식형(돌쌓기 찰)은 그 줄을 스스로 품어 겹치지 않음.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from collections import Counter
|
||
|
||
from B05_Profile.B05_Profile_Structures_Schema import StructureInstance
|
||
from B08_Quantity.B08_Quantity_Engine_StmateRecipe import recipe_item
|
||
from B08_Quantity.B08_Quantity_Engine_StructureSheet import build_standard_sheets
|
||
from B08_Quantity.B08_Quantity_Engine_StructureTemplate import (
|
||
KEEP_ENGINE_COMPONENTS,
|
||
apply_templates,
|
||
)
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table
|
||
|
||
HOPYO = {
|
||
"no": 6,
|
||
"source_code": "B00010",
|
||
"name": "기슭막이",
|
||
"spec": "H=2.0m",
|
||
"unit": "M",
|
||
"basis": [],
|
||
"contract_rows": 0,
|
||
"rows": [
|
||
{
|
||
"name": "깬잡석찰쌓기",
|
||
"spec": "L3=45",
|
||
"amount": 2.09,
|
||
"unit": "M2",
|
||
"remark": "",
|
||
"source_code": "",
|
||
},
|
||
],
|
||
}
|
||
WALL = StructureInstance.model_validate(
|
||
{
|
||
"structure_id": "a",
|
||
"type_id": "masonry_wet",
|
||
"placement": "interval",
|
||
"start_m": 0.0,
|
||
"end_m": 10.0,
|
||
"options": {"height_m": 2.5, "back_len_cm": 45, "foundation": "기초유"},
|
||
}
|
||
).model_dump()
|
||
NAMES = {"masonry_wet": "돌쌓기(찰)"}
|
||
|
||
|
||
def _fixed() -> dict:
|
||
return {
|
||
**recipe_item(HOPYO, type_id="masonry_wet", file_name="a", project="p"),
|
||
"code": "AX-ST-0000abcd",
|
||
}
|
||
|
||
|
||
def test_목록이_코드에_못박혀_있다() -> None:
|
||
assert set(KEEP_ENGINE_COMPONENTS) >= {"터파기", "되메우기", "잔토처리", "버림콘크리트"}
|
||
|
||
|
||
def test_고정형을_가져와도_토공_버림_성분은_남는다() -> None:
|
||
engine = build_table([WALL], NAMES, {}, {}, None, use_templates=False)["structures"][0]
|
||
fixed = build_table([WALL], NAMES, {}, {}, None, structure_templates={"masonry_wet": _fixed()})
|
||
components = {c["name"]: c for c in fixed["structures"][0]["components"]}
|
||
for name in ("터파기", "되메우기", "잔토처리", "버림콘크리트"):
|
||
before = next(c for c in engine["components"] if c["name"] == name)
|
||
assert components[name]["amount"] == before["amount"], name
|
||
assert "깬잡석찰쌓기" in components and "돌" not in components # 목록 밖은 양식으로 갈음
|
||
|
||
|
||
def test_양식형은_그_줄을_스스로_품어_겹치지_않는다() -> None:
|
||
table = build_table([WALL], NAMES, {}, {}, None)
|
||
counts = Counter(c["name"] for c in table["structures"][0]["components"])
|
||
assert all(count == 1 for count in counts.values()), counts
|
||
|
||
|
||
def test_구조물도_장에도_남긴_줄이_보인다() -> None:
|
||
templates = {"masonry_wet": _fixed()}
|
||
table = build_table([WALL], NAMES, {}, {}, None, structure_templates=templates)
|
||
payload = build_standard_sheets(table, {})
|
||
apply_templates(payload, {}, templates)
|
||
names = [row["name"] for row in payload["sheets"][0]["rows"]]
|
||
assert names[0] == "깬잡석찰쌓기" and "터파기" in names and "버림콘크리트" in names
|
||
numbers = [row["no"] for row in payload["sheets"][0]["rows"]]
|
||
assert len(numbers) == len(set(numbers)) # 남긴 줄 차례가 양식 줄과 안 겹침
|