From 5e09a86104a51477e73b55e99abf55ec9f2086a4 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 13 Sep 2026 09:13:13 +0900 Subject: [PATCH] =?UTF-8?q?test(b09):=20=EC=A4=80=EB=B9=84=EA=B3=B5=20?= =?UTF-8?q?=EC=A4=84=EC=9D=B4=20=EC=9D=B8=EA=B3=84=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=82=B4=EC=97=AD=EC=84=9C=EA=B9=8C=EC=A7=80=20=EC=95=88=20?= =?UTF-8?q?=EC=83=88=EB=8A=94=EC=A7=80=20=EC=9E=A0=EA=B8=88=20=E2=80=94=20?= =?UTF-8?q?V-12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit B08 인계의 준비공·부대시설 줄이 B09 에서 내역 본체 또는 제외 줄로 반드시 서는지, 표토제거 2,359.035㎥ 가 수량째 본체에 서는지 마주 걸어 확인. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01DJffo4VwgTumVUM3kdbJzd --- .../tester/test_b09_prep_handoff_bill.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 resources/tester/test_b09_prep_handoff_bill.py diff --git a/resources/tester/test_b09_prep_handoff_bill.py b/resources/tester/test_b09_prep_handoff_bill.py new file mode 100644 index 00000000..ab264508 --- /dev/null +++ b/resources/tester/test_b09_prep_handoff_bill.py @@ -0,0 +1,57 @@ +"""PLAN 7장 V-12 — 준비공 줄이 B08 인계에서 **B09 내역서까지 하나도 안 새나** (2026-09-13). + +「안 하면 표토제거 2,359.03㎥ 가 다시 통째로 사라짐」 자리. 보내는 쪽(B08)과 받는 쪽(B09)을 +**마주 걸어** 본다 — 한쪽만 보면 양쪽 다 조용히 틀린다(PLAN 7장 머리 규칙). + +⚠ 겨누는 것 둘 + ① 준비공·부대시설 줄은 **내역 줄 아니면 제외 줄**로 반드시 선다 — 어디에도 없는 줄이 0 + ② 금액이 서는 줄(`in_bill`)은 **수량째** 내역 본체에 선다 — 표토제거 2,359.035㎥ +⚠ 단가가 붙는지는 여기서 안 본다 — 표토 축(시트 9번)·임목축적 입력이 정해져야 서는 자리다. +""" + +from __future__ import annotations + +import sys +from decimal import Decimal +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) + +from B08_Quantity.B08_Quantity_Engine_Handoff import build_handoff # noqa: E402 +from B08_Quantity.B08_Quantity_Engine_Preparation import build_table as build_prep # noqa: E402 +from B09_Estimation.B09_Estimation_BillOfQuantities import build_bill # noqa: E402 + +SLOPE = { + "face_dressing_fill": 9000.0, + "face_dressing_cut": 6726.9, + "tree_removal_fill": 9000.0, + "tree_removal_cut": 6726.9, + "bench_cut_fill": 9000.0, +} + + +def _handoff_and_bill(): + handoff = build_handoff(preparation_table=build_prep(SLOPE, [], [], 0.15)) + return handoff, build_bill(handoff) + + +def test_준비공_줄은_내역_아니면_제외로_반드시_선다() -> None: + handoff, bill = _handoff_and_bill() + sent = [r for r in handoff["work_items"] if r["origin"] == "preparation"] + assert len(sent) >= 6 + body = [r.name for r in bill.rows if not r.is_group] + excluded = [r.name for r in bill.excluded] + for row in sent: + landed = body if row["in_bill"] else excluded + assert row["name"] in landed, (row["name"], row["in_bill"]) + + +def test_금액이_서는_줄은_수량째_본체에_선다() -> None: + handoff, bill = _handoff_and_bill() + topsoil = next(r for r in bill.rows if not r.is_group and r.name == "표토제거") + assert Decimal(str(topsoil.quantity)).quantize(Decimal("0.01")) == Decimal("2359.04") + in_bill = [ + r["name"] for r in handoff["work_items"] if r["origin"] == "preparation" and r["in_bill"] + ] + assert {"표토제거", "제근·뿌리다듬기", "뿌리 적재"} <= set(in_bill)