From 9a758c4d27d96aa0918ee21f385e773037b44e20 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 13 Sep 2026 19:51:40 +0900 Subject: [PATCH] =?UTF-8?q?feat(axis):=20=EB=AA=A8=EB=A5=B4=ED=84=B0=20?= =?UTF-8?q?=EC=A4=84=20=EA=B3=B5=EC=A2=85=20=EC=BD=94=EB=93=9C=20AX-WK-c08?= =?UTF-8?q?42a0d=20=EB=AA=A8=EB=A5=B4=ED=83=80=EB=A5=B4=20=EB=B0=B0?= =?UTF-8?q?=ED=95=A9=201:3=20=E2=80=94=20=EC=B0=B0=EC=8C=93=EA=B8=B0=20?= =?UTF-8?q?=EC=9D=BC=EC=9C=84=EB=8C=80=EA=B0=80=20=ED=91=9C=EC=9D=98=20?= =?UTF-8?q?=EB=A7=89=ED=9E=8C=20=EC=A4=84=EC=9D=B4=20=EC=97=B4=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 산림 품셈엔 배합 절이 없어 건설 품셈 [건축] 9-1-1 을 옮김 — 보통인부 0.66인/㎥(모래체가름 포함). 시멘트 510kg·모래 1.10㎥ 는 자재 단가 층이 없어 안 붙은 줄로 드러냄(원문 할증 포함 값). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn --- B09_Estimation/B09_Estimation_UnitPrice.py | 4 ++ B09_Estimation/B09_Estimation_WorkItems_AX.py | 59 +++++++++++++++++++ resources/library_structure/masonry_wet.json | 4 +- .../tester/test_b08_structure_unit_price.py | 4 +- resources/tester/test_b09_work_items_ax.py | 25 ++++++++ 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 B09_Estimation/B09_Estimation_WorkItems_AX.py create mode 100644 resources/tester/test_b09_work_items_ax.py diff --git a/B09_Estimation/B09_Estimation_UnitPrice.py b/B09_Estimation/B09_Estimation_UnitPrice.py index 0207f461..24029293 100644 --- a/B09_Estimation/B09_Estimation_UnitPrice.py +++ b/B09_Estimation/B09_Estimation_UnitPrice.py @@ -929,6 +929,10 @@ def build_unit_prices( from B09_Estimation.B09_Estimation_ParentSteps import attach_parent_steps attach_parent_steps(build, master) + # 산림 품셈에 절이 없는 공종(모르타르 배합 등) — 명세 2장 ② 갈래 WK. + from B09_Estimation.B09_Estimation_WorkItems_AX import attach_work_items_ax + + attach_work_items_ax(build) # 기계 수송비 — 기계경비의 셋째 몫(손료·운전경비·**수송비**). 거리가 있어야 선다. from B09_Estimation.B09_Estimation_Transport import attach_transport diff --git a/B09_Estimation/B09_Estimation_WorkItems_AX.py b/B09_Estimation/B09_Estimation_WorkItems_AX.py new file mode 100644 index 00000000..43f77128 --- /dev/null +++ b/B09_Estimation/B09_Estimation_WorkItems_AX.py @@ -0,0 +1,59 @@ +"""B09 원가계산 — **산림 품셈에 절이 없는 공종**(`AX-WK-*`)의 일위대가 (명세 2장 ② 갈래 WK). + +산림 품셈이 **부르기만 하고 품을 안 주는** 자리를 원문이 있는 다른 품셈에서 그대로 옮긴다. +⚠ 코드는 난수 8자리 · 동등 비교만(명세 2장 ④) — 읽기는 이름 칸이 맡음. +⚠ 값은 원문 그대로 · 줄마다 출처. 자재는 단가 층이 없어 **드러내기만** 함(치즐과 같은 자리). +""" + +from __future__ import annotations + +from decimal import Decimal +from typing import Any + +from B09_Estimation.B09_Estimation_PriceBook import PriceDetail, PriceKind, PriceTitle + +#: 모르타르 배합 1:3 — 찰쌓기·찰붙임 줄눈메꿈(산림 품셈 13-4-4 [주]④ · 13-5-1 [주]③ 0.009㎥/㎡). +MORTAR_MIX = "AX-WK-c0842a0d" + +WORK_ITEMS: dict[str, dict[str, Any]] = { + MORTAR_MIX: { + "name": "모르타르 배합", + "spec": "1:3", + "unit": "㎥", + "basis": ( + "건설공사 표준품셈(2026) [건축부문] 9-1-1 모르타르 배합(㎥당)" + " — 산림 품셈엔 배합 절이 없음 · 배합비 1:3 은 돌쌓기 시방(시멘트:잔골재 부피비) · 실무 울진 대흥(2024)·소광(2025)" + " 「모르타르배합 1:3」 과 같은 짜임" + ), + # (노임 코드, 수량, 칸) — 원문 [주]② 「배합이 포함된 것이며, 비빔은 제외」. + "labor": (("1002", "0.66", "보통인부 — 모래체가름 포함 칸(제외 칸 0.43)"),), + # 원문 참고자료 1:3 줄 · ※ 「위 재료량은 할증이 포함된 것이다」 — 할증 전 값이 아님. + "materials": ("시멘트 510 kg", "모래 1.10 ㎥"), + }, +} + + +def attach_work_items_ax(build: Any) -> None: + """`B-AX-WK-*` 제목을 세운다 — 노임 층이 없으면 안 세우고 사유를 남긴다.""" + for code, item in WORK_ITEMS.items(): + missing = [ref for ref, _, _ in item["labor"] if ref not in build.book.titles] + if missing: + build.component_gaps[code] = f"노임 단가 층이 없습니다 — {', '.join(missing)}" + continue + title_code = f"B-{code}" + build.book.add_title( + PriceTitle( + code=title_code, + kind=PriceKind.UNIT_PRICE, + name=item["name"], + spec=item["spec"], + unit=item["unit"], + ) + ) + for ref, quantity, cell in item["labor"]: + build.book.add_detail( + PriceDetail(title_code, ref, Decimal(quantity), note=f"{cell} · {item['basis']}") + ) + build.unattached[code] = [ + f"{material} — 자재 단가 층 없음(원문 할증 포함 값)" for material in item["materials"] + ] diff --git a/resources/library_structure/masonry_wet.json b/resources/library_structure/masonry_wet.json index 75e53841..b9c1cc9a 100644 --- a/resources/library_structure/masonry_wet.json +++ b/resources/library_structure/masonry_wet.json @@ -263,7 +263,7 @@ } ], "unit_price": { - "note": "하단 일위대가 틀(PLAN 3장 하단 ①) — 갈 곳 unit_price 줄마다 한 줄. 수량은 원단위 줄(from_row), 단가는 B09 단가표. 공종 코드는 인계 대응표(찰쌓기 FP-13-04-05 · 갈래 뒷길이)와 10장 판정(기초잡석 FP-12-25)을 따름. 모르터는 코드 미정이라 막힘으로 둠", + "note": "하단 일위대가 틀(PLAN 3장 하단 ①) — 갈 곳 unit_price 줄마다 한 줄. 수량은 원단위 줄(from_row), 단가는 B09 단가표. 공종 코드는 인계 대응표(찰쌓기 FP-13-04-05 · 갈래 뒷길이)와 10장 판정(기초잡석 FP-12-25)을 따름. 모르터는 산림 품셈에 배합 절이 없어 AX-WK-c0842a0d 모르타르 배합 1:3(건설 품셈 건축 9-1-1)", "rows": [ { "seq": 1, @@ -272,7 +272,7 @@ "work_item_code": "FP-13-04-05", "variant_from": "L3" }, - { "seq": 2, "name": "모르터", "from_row": 8 }, + { "seq": 2, "name": "모르터", "from_row": 8, "work_item_code": "AX-WK-c0842a0d" }, { "seq": 3, "name": "기초잡석", "from_row": 15, "work_item_code": "FP-12-25" } ] } diff --git a/resources/tester/test_b08_structure_unit_price.py b/resources/tester/test_b08_structure_unit_price.py index f930019c..5cb92450 100644 --- a/resources/tester/test_b08_structure_unit_price.py +++ b/resources/tester/test_b08_structure_unit_price.py @@ -254,4 +254,6 @@ def test_창구가_실제_단가표로_찰쌓기_갈래를_찾는다(client: Tes assert rows[1]["ref_code"] == "B-FP-13-04-05#55cm이하" assert rows[1]["labor"] > 0 and rows[1]["quantity"] == pytest.approx(2.5 * 1.09**0.5) assert rows[3]["ref_code"] == "B-FP-12-25" - assert rows[2]["reason"] == "공종 코드 미정" and table["complete"] is False + # 모르터 — 산림 품셈에 배합 절이 없어 AX-WK 모르타르 배합 1:3(2026-09-13) + assert rows[2]["ref_code"] == "B-AX-WK-c0842a0d" and rows[2]["labor"] > 0 + assert table["complete"] is True diff --git a/resources/tester/test_b09_work_items_ax.py b/resources/tester/test_b09_work_items_ax.py new file mode 100644 index 00000000..35ed26a2 --- /dev/null +++ b/resources/tester/test_b09_work_items_ax.py @@ -0,0 +1,25 @@ +"""산림 품셈에 절이 없는 공종 `AX-WK-*` (명세 2장 ② 갈래 WK · 2026-09-13). + +지키는 것 — 모르타르 배합 1:3 = 보통인부 0.66인/㎥(건설 품셈 건축 9-1-1, 모래체가름 포함) · +시멘트·모래는 자재 단가 층이 없어 금액에 안 들고 「안 붙은 줄」로 드러남. +""" + +from __future__ import annotations + +from decimal import Decimal + +from B09_Estimation.B09_Estimation_UnitPrice import cached_build +from B09_Estimation.B09_Estimation_WorkItems_AX import MORTAR_MIX + + +def test_모르타르_배합은_보통인부_066인이고_자재는_드러내기만() -> None: + build = cached_build() + title = build.book.title(f"B-{MORTAR_MIX}") + assert (title.name, title.spec, title.unit) == ("모르타르 배합", "1:3", "㎥") + money = build.book.resolve(f"B-{MORTAR_MIX}") + wage = build.book.resolve("1002").labor # 보통인부 + assert money.labor == wage * Decimal("0.66") and money.material == 0 + assert [label.split(" —")[0] for label in build.unattached[MORTAR_MIX]] == [ + "시멘트 510 kg", + "모래 1.10 ㎥", + ]