feat(b08): 옹벽 조립 조각 합판거푸집이 사용횟수 갈래로(「FP-12-04#3회」 · 성분의 reuse_count 그대로) · 집수정 거푸집 6회 → 4회(12-15 표 「합판4회」 정본 · 사유 문구도 그 표) — 화면 자재 표·인계 성분 한 벌(브레인 ㉯ ①②)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
This commit is contained in:
@@ -105,15 +105,17 @@ def annotate(
|
||||
component["reuse_note"] = NOTE_REUSE_MISSING
|
||||
continue
|
||||
count = entry.get("reuse_count")
|
||||
# 근거 — 대개 1-7-1 분류 · 그 공종 표가 직접 적었으면 그 표(집수정 12-15 · 2026-09-14).
|
||||
basis = str(entry.get("basis") or "품셈 1-7-1")
|
||||
for component in targets:
|
||||
component["reuse_count"] = count
|
||||
component["reuse_note"] = (
|
||||
f"품셈 1-7-1 {count}회 — 「{entry.get('matched_example')}」"
|
||||
f"{basis} {count}회 — 「{entry.get('matched_example')}」"
|
||||
if count
|
||||
else NOTE_NOT_APPLICABLE
|
||||
)
|
||||
if count:
|
||||
notes.append(f"{structure.get('name') or type_id} 거푸집 {count}회 (품셈 1-7-1)")
|
||||
notes.append(f"{structure.get('name') or type_id} 거푸집 {count}회 ({basis})")
|
||||
else:
|
||||
missing.append(type_id)
|
||||
return notes, sorted(set(missing))
|
||||
|
||||
@@ -382,6 +382,30 @@ def composite_quantities(
|
||||
entry["not_ready"] = True
|
||||
entry["why"] = why
|
||||
missing.append({"code": spec.get("code"), "reason": why})
|
||||
if suffix == "formwork_reuse":
|
||||
# 12-4 사용횟수 갈래 — B08 이 성분에 단 횟수(`Formwork.annotate`) 그대로(한 벌 · 09-14).
|
||||
counts = {
|
||||
component.get("reuse_count")
|
||||
for component in structure.get("components") or []
|
||||
if str(component.get("name") or "").strip() in found
|
||||
}
|
||||
count = next(iter(counts)) if len(counts) == 1 else None
|
||||
if isinstance(count, int) and count > 0:
|
||||
entry["kind"] = f"{count}회"
|
||||
entry["kind_basis"] = next(
|
||||
(
|
||||
str(component.get("reuse_note") or "")
|
||||
for component in structure.get("components") or []
|
||||
if str(component.get("name") or "").strip() in found
|
||||
),
|
||||
"",
|
||||
)
|
||||
entry["code"] = f"{spec.get('code')}#{count}회"
|
||||
elif found:
|
||||
why = "거푸집 사용횟수가 없거나 둘 이상이라 12-4 갈래를 못 고름"
|
||||
entry["not_ready"] = True
|
||||
entry["why"] = why
|
||||
missing.append({"code": spec.get("code"), "reason": why})
|
||||
if suffix == "rebar_complexity":
|
||||
# 갈래는 원문이 정한다 — 화면·인계에 이름과 근거를 함께 실어 사람이 검증하게 한다.
|
||||
complexity, why = rebar_complexity(
|
||||
|
||||
@@ -67,9 +67,10 @@
|
||||
},
|
||||
{
|
||||
"type_id": "pipe_inlet_basin",
|
||||
"reuse_count": 6,
|
||||
"matched_example": "보호공 기초",
|
||||
"note": "관보호공 집수정 — 원문 6회 줄의 「호안 및 보호공의 기초」에 해당. ⚠ 벽체까지 6회로 볼지는 확인 필요"
|
||||
"reuse_count": 4,
|
||||
"matched_example": "거푸집 합판4회",
|
||||
"note": "그 공종 표가 직접 적은 「거푸집 | 합판4회」 가 정본 — 1-7-1 분류(「호안 및 보호공의 기초」 6회)보다 위(2026-09-14 브레인 ㉯ ②). 앞서 6회로 봤음.",
|
||||
"basis": "품셈 12-15 집수정 표"
|
||||
},
|
||||
{
|
||||
"type_id": "ford_pavement",
|
||||
|
||||
@@ -346,7 +346,8 @@
|
||||
"unit": "㎡",
|
||||
"from_components": [
|
||||
"합판거푸집"
|
||||
]
|
||||
],
|
||||
"kind_suffix": "formwork_reuse"
|
||||
},
|
||||
{
|
||||
"code": "FP-12-38",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
"""거푸집 사용횟수 → 12-4 갈래 잇기 · 집수정 4회 — 2026-09-14 브레인 ㉯ ①②.
|
||||
|
||||
① 옹벽 조립 조각 「FP-12-04 합판거푸집」 에 꼬리가 없어 12-4 사용횟수 갈래(#1~6회)를 못 고름 →
|
||||
B08 이 성분에 단 사용횟수(`reuse_count`, 품셈 1-7-1 옹벽 3회)를 꼬리로 붙임(값은 한 벌).
|
||||
② 집수정은 **12-15 표가 직접 적은 「거푸집 합판4회」 가 정본** — 1-7-1 분류로 본 6회는 걷음.
|
||||
화면(자재 표 · 인계)과 표가 같은 값이어야 함(한 벌이 두 값으로 갈리지 않게).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from B08_Quantity.B08_Quantity_Engine_Formwork import FORMWORK_NAMES # noqa: E402
|
||||
from B08_Quantity.B08_Quantity_Engine_Handoff import build_handoff # noqa: E402
|
||||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table # noqa: E402
|
||||
|
||||
WALL = {"structure_id": "w1", "type_id": "retaining_wall", "start_m": 100.0, "end_m": 110.0,
|
||||
"options": {"form": "반중력식", "height_m": 2.0, "length_m": 10.0}} # fmt: skip
|
||||
BASIN = {"structure_id": "b1", "type_id": "pipe_inlet_basin", "start_m": 50.0, "end_m": 50.0,
|
||||
"options": {"inlet_basin_form": "□형(기본형)", "inlet_basin_material": "콘크리트",
|
||||
"pipe_diameter_mm": "800"}} # fmt: skip
|
||||
|
||||
|
||||
def test_옹벽_조각_합판거푸집이_사용횟수_갈래로_이어져_단가가_섬() -> None:
|
||||
from B09_Estimation.B09_Estimation_UnitPrice import cached_build
|
||||
|
||||
unit = build_table([WALL], {"retaining_wall": "옹벽"})
|
||||
row = next(
|
||||
r for r in build_handoff(unit_quantity_table=unit)["work_items"] if r["composite_parts"]
|
||||
)
|
||||
part = next(p for p in row["composite_parts"] if str(p["code"]).startswith("FP-12-04"))
|
||||
assert part["code"] == "FP-12-04#3회" and not part.get("not_ready"), part
|
||||
assert "B-FP-12-04#3회" in cached_build().book.titles
|
||||
|
||||
|
||||
def test_집수정_거푸집은_12_15_표의_4회_화면과_인계가_같은_값() -> None:
|
||||
unit = build_table([BASIN], {"pipe_inlet_basin": "집수정"})
|
||||
forms = [c for s in unit["structures"] for c in s["components"] if c["name"] in FORMWORK_NAMES]
|
||||
assert forms and all(c["reuse_count"] == 4 for c in forms), forms
|
||||
assert all("12-15" in c["reuse_note"] for c in forms), forms
|
||||
Reference in New Issue
Block a user