diff --git a/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py b/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py index 6316ab95..1ad700ef 100644 --- a/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py +++ b/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py @@ -441,6 +441,15 @@ def _structure_rows( # 갈래 축과 **저장 제원 원본값**. 가공하지 않는다. variant_axis = str(entry.get("variant_axis") or "") or None variant_value = (structure.get("options") or {}).get(variant_axis) if variant_axis else None + if variant_axis == "back_len_cm": + # 뒷길이만은 **수량표·구조물도가 실제로 쓴 값**과 출처를 싣는다 — 안 고른 벽(관 유입· + # 유출부 기슭막이는 늘 빔)도 [주]⑩ 하한으로 물량이 섰는데 갈래만 못 골랐음(09-14). + from B08_Quantity.B08_Quantity_Engine_StructureFigure import back_length_cm + + back, default_note = back_length_cm(structure) + variant_value = str(back) if variant_value in (None, "") else variant_value + used = f"뒷길이 {back}㎝ — {default_note or '저장 제원'}" + class_basis = " · ".join(part for part in (class_basis, used) if part) secondary_axes = [ {"axis": axis, "value": (structure.get("options") or {}).get(axis)} for axis in entry.get("secondary_axes") or [] diff --git a/resources/tester/test_b08_back_length_handoff.py b/resources/tester/test_b08_back_length_handoff.py new file mode 100644 index 00000000..6ef22f21 --- /dev/null +++ b/resources/tester/test_b08_back_length_handoff.py @@ -0,0 +1,66 @@ +"""관 벽 · 돌쌓기 줄 뒷길이 — 인계가 **B08 이 실제로 쓴 뒷길이 + 출처**를 싣는다(2026-09-14 브레인). + +종전: 인계는 저장 원본 `back_len_cm` 만 실어, 안 고른 벽(관 유입·유출부 기슭막이는 늘 빔)은 +`variant_value=None` → B09 가 13-04-02/05 뒷길이 갈래(#35·55·75cm이하)를 못 고름. 그런데 수량표· +구조물도는 이미 품셈 13-4-4 [주]⑩ 표준표 하한으로 섰음(두께식·고임돌·채움콘크리트가 그 값). +⇒ 값이 선 그 뒷길이를 갈래 값으로 · 출처(저장 / [주]⑩ 하한)를 판정 근거 칸에. +""" + +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_Handoff import build_handoff # noqa: E402 +from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table as build_unit # noqa: E402 + + +def _row(type_id: str, options: dict) -> dict: + unit = build_unit( + [ + { + "structure_id": "x", + "type_id": type_id, + "start_m": 0.0, + "end_m": 10.0, + "options": options, + } + ], + {type_id: type_id}, + ) + handoff = build_handoff(unit_quantity_table=unit) + return next(r for r in handoff["work_items"] if r["variant_axis"] == "back_len_cm") + + +def test_안_고른_뒷길이는_표준표_하한을_출처와_함께_보냄() -> None: + row = _row("masonry_wet", {"height_m": 1.5, "length_m": 10.0}) + assert row["variant_value"] == "25", row # 찰쌓기 ≤1.5m 하한 25㎝ + assert "뒷길이 25㎝" in row["spec_class_basis"] and "[주]⑩" in row["spec_class_basis"] + + +def test_고른_뒷길이는_원본값_그대로_출처는_저장_제원() -> None: + row = _row("masonry_wet", {"height_m": 1.5, "length_m": 10.0, "back_len_cm": "45"}) + assert row["variant_value"] == "45" + assert "[주]⑩" not in row["spec_class_basis"] and "저장 제원" in row["spec_class_basis"] + + +def test_기슭막이_메쌓기도_하한으로_갈래가_서서_내역_금액이_섬() -> None: + from B09_Estimation.B09_Estimation_BillOfQuantities import build_bill + + options = {"height_m": 2.5, "length_m": 10.0, "form": "돌쌓기(메)"} + row = _row("revetment", options) + assert row["variant_value"] == "45", row # 메쌓기 ~3m 하한 36 → 규격 45 + assert row["work_item_code"] == "FP-13-04-02" and not row["blocked_kind"], row + unit = build_unit( + [{"structure_id": "x", "type_id": "revetment", "start_m": 0.0, "end_m": 10.0, + "options": options}], + {"revetment": "revetment"}, + ) # fmt: skip + bill = build_bill(build_handoff(unit_quantity_table=unit)) + line = next(r for r in bill.rows if r.code == "FP-13-04-02") + assert line.amount_krw and int(line.amount_krw) > 0, line.note + assert line.price_code.endswith("#55cm이하"), line.price_code # 45㎝ 를 담는 가장 좁은 구간