From 68ca189220abd77c07cf1c6d3bf5c491883f0d68 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Wed, 9 Sep 2026 08:37:44 +0900 Subject: [PATCH] =?UTF-8?q?fix(B08):=20=EC=9A=B4=EB=B0=98=EC=9D=B4=20?= =?UTF-8?q?=EB=91=90=20=EC=B6=95=EC=97=90=20=EC=8B=A4=EB=A0=A4=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=A4=84=EC=9D=B4=20=EB=91=90=20=EB=B2=8C=EC=9D=B4?= =?UTF-8?q?=EB=8D=98=20=EA=B2=83=20=EB=A7=89=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 토공집계표는 실무 토적집계 모양이라 무대·도자운반·덤프운반을 함께 싣는데, 인계본에는 운반표(FP-10-11·FP-10-12)가 같은 물량으로 또 실렸음 — 둘 다 in_bill 이었음 (실측: 도자 17.389·61.130 · 덤프 37.511·122.417 이 두 축에 각각) - 집계 쪽 운반 줄을 in_bill=False 로 두고 사유를 적음. 값은 남김 — 검산 (무대+도자+덤프 = 총 운반토량)이 그 값을 씀(무대를 그렇게 둔 것과 같은 규칙) - 성토 같은 다른 집계 줄은 안 건드림 - tmp/tests/test_b08_haul_double_count.py 신설(5건) Co-Authored-By: Claude Opus 5 (1M context) --- B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py | 12 ++++++++++++ B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py | 11 +++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py b/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py index d66196fe..d20bf41b 100644 --- a/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py +++ b/B08_Quantity/B08_Quantity_Engine_Handoff_Mapping.py @@ -139,6 +139,18 @@ SLOPE_GROUPS = frozenset({"성토면다짐", "초류종자살포", "지장목제 #: 집계 합계 줄 — 내역 줄이 아니라 검산용이다. SUBTOTAL_GROUPS = frozenset({"보정량계"}) +#: ⚠⚠ **토공집계표에도 운반 줄이 있다 — 그런데 내역 줄은 운반표 쪽이다**(2026-09-09 실측). +#: 집계표는 실무 토적집계 모양이라 「무대·도자운반·덤프운반」을 함께 싣는데, 인계본에는 +#: 운반표(`_haul_rows`, FP-10-11·FP-10-12)가 **같은 물량으로 또 실렸다** — 같은 운반이 +#: 두 줄이었다(실측: 도자 17.389·61.130, 덤프 37.511·122.417 이 두 축에 각각). +#: ⇒ 집계 쪽은 **값은 내되 내역 줄이 아니다**. 빼지 않는 까닭은 검산(무대+도자+덤프 = 총 +#: 운반토량)이 그 값을 쓰기 때문이다 — 무대를 그렇게 둔 것과 같은 규칙이다. +HAUL_SUMMARY_GROUPS = frozenset({"무대(종방향유용토)", "도자운반", "덤프운반"}) +NOTE_HAUL_IN_SUMMARY = ( + "집계 값 — 내역 줄은 운반표 쪽(FP-10-11·FP-10-12)이 세움. 여기서 또 세우면 같은 운반이" + " 두 줄이 됨(검산용으로만 실림)" +) + def _latest_dataset_path(directory: Path | None = None) -> Path | None: folder = directory or DATASET_DIR diff --git a/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py b/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py index d650a009..52c7ec19 100644 --- a/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py +++ b/B08_Quantity/B08_Quantity_Engine_Handoff_Rows.py @@ -14,7 +14,9 @@ from B08_Quantity.B08_Quantity_Engine_Handoff_Mapping import ( BLOCKED_FORMULA_MISSING, BLOCKED_INPUT_MISSING, BLOCKED_UNIT_DATA_MISSING, + HAUL_SUMMARY_GROUPS, METHOD_TO_GROUND, + NOTE_HAUL_IN_SUMMARY, NOTE_METHOD_MISSING, ORIGIN_EARTHWORK, ORIGIN_HAUL, @@ -114,7 +116,8 @@ def _earthwork_rows( continue ground = row.get("item") or None origin = ORIGIN_SLOPE if group in SLOPE_GROUPS else ORIGIN_EARTHWORK - is_subtotal = group in SUBTOTAL_GROUPS + # ⚠ 운반은 **집계에도 오르고 운반표에도 오른다** — 내역 줄은 운반표 쪽 하나뿐이다. + is_subtotal = group in SUBTOTAL_GROUPS or group in HAUL_SUMMARY_GROUPS lookup_ground, method_note = _mapping_ground(ground, methods) entry = mapping.for_earthwork(group, lookup_ground) if method_note == "" else None code = (entry or {}).get("work_item_code") @@ -169,9 +172,9 @@ def _earthwork_rows( # 합계 줄과 무대 줄은 값은 내되 내역에 안 선다. "in_bill": bool(row.get("in_bill", True)) and not is_subtotal and mismatch is None, "excavation_method": methods.get(ground) if ground else None, - "in_bill_reason": "집계 합계 줄 — 검산용" - if is_subtotal - else str(row.get("note") or ""), + "in_bill_reason": NOTE_HAUL_IN_SUMMARY + if group in HAUL_SUMMARY_GROUPS + else ("집계 합계 줄 — 검산용" if is_subtotal else str(row.get("note") or "")), "origin": origin, } )