From c4a83dbb095bdce108bf3ea2b1996fe357102b62 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 14 Sep 2026 13:56:51 +0900 Subject: [PATCH] =?UTF-8?q?fix(b09):=209-21=20=EC=A0=9C=EA=B7=BC=20?= =?UTF-8?q?=E3=80=8C=EB=B0=91=EC=88=98=20=EB=AF=B8=ED=99=95=EB=B3=B4?= =?UTF-8?q?=E3=80=8D=20=EB=A7=89=ED=9E=98=20=EA=B1=B7=EC=9D=8C=20=E2=80=94?= =?UTF-8?q?=20=EB=A7=88=EC=8A=A4=ED=84=B0=20=EB=AA=A9=EB=A1=9D(F0294)?= =?UTF-8?q?=EC=9D=80=20=EC=9B=90=EB=AC=B8=20=EC=82=AC=EC=8B=A4=EC=9D=B4?= =?UTF-8?q?=EB=9D=BC=20=EB=91=90=EA=B3=A0=20=EB=8B=A8=EA=B0=80=20=EC=A1=B0?= =?UTF-8?q?=EB=A6=BD=EC=9D=B4=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=ED=99=95?= =?UTF-8?q?=EC=A0=95=20=EB=B9=8C=EB=A6=B0=20=EB=B0=91=EC=88=98=20=EA=B3=B5?= =?UTF-8?q?=EC=A2=85=EB=A7=8C=20=EC=A0=9C=EC=99=B8(=C3=B71,000=20=EC=9D=80?= =?UTF-8?q?=20ChooseOne)=20=C2=B7=20=EA=B0=88=EB=9E=98=20=EC=84=A0=20?= =?UTF-8?q?=EB=82=B4=EC=97=AD=20=EC=A4=84=20=EA=B8=88=EC=95=A1=20=EC=84=AC?= =?UTF-8?q?=20=C2=B7=20=EC=9D=BC=EC=9C=84=EB=8C=80=EA=B0=80=20453=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20=EB=B3=80=ED=99=94=200?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn --- B09_Estimation/B09_Estimation_UnitPrice.py | 6 ++++- resources/tester/test_b09_table_reading_2.py | 24 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/B09_Estimation/B09_Estimation_UnitPrice.py b/B09_Estimation/B09_Estimation_UnitPrice.py index b776bf41..4d5570d3 100644 --- a/B09_Estimation/B09_Estimation_UnitPrice.py +++ b/B09_Estimation/B09_Estimation_UnitPrice.py @@ -65,6 +65,7 @@ from B09_Estimation.B09_Estimation_ResourceAxis import ( load_labor_catalog, load_work_item_master, ) +from B09_Estimation.B09_Estimation_WorkItemUnit import BORROWED_BASIS_PER from B09_Estimation.B09_Estimation_WorkItemUnit import unit_of as work_item_unit from B09_Estimation.B09_Estimation_Rounding import OutputPlace, round_at from B09_Estimation.B09_Estimation_Transport import parse_distance_km @@ -889,9 +890,12 @@ def build_unit_prices( continue # ⚠ 밑수를 못 찾은 표를 쓰면 **곱하면 안 되는 줄**로 표시한다. + # 예외 = 사용자가 다른 품셈 밑수를 확정한 자리(9-21 「1,000㎡당」 · ÷ 는 ChooseOne 이 검) — + # 마스터 목록은 원문 사실이라 그대로 두고 여기서만 걷음(2026-09-14 브레인 · 사유는 비고). + borrowed = work_item_code.startswith(tuple(BORROWED_BASIS_PER)) for row in rows: section = missing_basis.get(str(row.pum_table_id)) - if section: + if section and not borrowed: build.basis_missing[work_item_code] = section break diff --git a/resources/tester/test_b09_table_reading_2.py b/resources/tester/test_b09_table_reading_2.py index dcaf749b..a8dd2e5f 100644 --- a/resources/tester/test_b09_table_reading_2.py +++ b/resources/tester/test_b09_table_reading_2.py @@ -68,3 +68,27 @@ def test_토사면_고르기는_두_표가_섞여_값이_불완전하다고_먼 note = known_gap_note("FP-09-19-01") assert "절토면" in note and "성토면" in note and "불완전" in note assert "불완전" in detail_of(cached_build(), "B-FP-09-19-01")["known_gap_note"] + + +def test_제근은_빌린_밑수가_확정이라_갈래가_서면_내역_금액이_섬() -> None: + """9-21 원문엔 밑수가 없어 마스터 `basis_missing` 에 F0294 가 남음(원문 사실 그대로) — 그러나 + 사용자 확정(건설품셈 3-9-2 「1,000㎡당」 · ÷1,000 은 ChooseOne 이 검)이 있어 내역에서 + 「밑수 미확보」로 막히면 안 됨(2026-09-14 브레인). 교차 참조 사유는 비고에 그대로 남음.""" + from B09_Estimation.B09_Estimation_BasisSheet import open_gaps + from B09_Estimation.B09_Estimation_BillOfQuantities import build_bill + from B09_Estimation.B09_Estimation_UnitPrice import detail_of, load_basis_missing + + assert "F0294" in load_basis_missing() + build = cached_build() + assert "FP-09-21" not in build.basis_missing + assert not [g for g in open_gaps(build) if g["code"] == "FP-09-21"] + title = "B-FP-09-21#굴착기(무한궤도)0.7·소" + # ㎡당 환산이 걸린 값 — 1,000㎡당 그대로면 5만원대로 섬 + assert build.book.title(title) and 50 <= int(detail_of(build, title)["total"]) <= 60 + item = {"work_item_code": "FP-09-21", "name": "지장목제거", "spec": "뿌리뽑기", "unit": "㎡", + "quantity": "1000", "in_bill": True, "variant_axis": "stand_volume_class", + "variant_value": "굴착기(무한궤도)0.7·소"} # fmt: skip + result = build_bill({"work_items": [item], "materials": []}, build=build) + assert not result.missing, result.missing + row = next(r for r in result.rows if r.code == "FP-09-21") + assert row.amount_krw and int(row.amount_krw) > 0, row.note