fix(B08): 옹벽 묶음 감사 둘 — 구조물 이름 코드값 노출 · 터파기 빠진 줄이 안 보이던 것

- 레지스트리 이름이 없으면 내역 줄 이름에 코드값이 그대로 떴음(`retaining_wall`).
  _Wording.type_label 이 이미 대비표를 들고 있으므로 그것을 씀 — 이제 「옹벽」으로 섬.
- 관측 원단위로 가는 구조물은 표에 터파기 줄이 없으면 그 구조물만 조용히 빠졌음.
  옹벽이 터파기 0 줄인데 사유도 안 났음(돌쌓기는 세 줄이 섬). 값을 지어내지 않고
  「터파기가 안 선 구조물」 줄을 in_bill False · blocked_kind unit_data_missing 로
  세워 빠졌다는 사실이 보이게 함.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-09 13:06:06 +09:00
co-authored by Claude Opus 5
parent 036da3f9f9
commit 072f560a59
2 changed files with 39 additions and 1 deletions
@@ -24,6 +24,7 @@ from typing import Any
from B08_Quantity.B08_Quantity_Engine_Handoff_Mapping import (
BLOCKED_INPUT_MISSING,
BLOCKED_UNIT_DATA_MISSING,
ORIGIN_EARTHWORK,
ORIGIN_STRUCTURE,
WorkItemMapping,
@@ -203,6 +204,10 @@ def structure_earthwork_rows(
bases: dict[tuple[str, str | None], list[str]] = {}
backfill = 0.0
spoil = 0.0
# ⚠ 터파기 성분이 아예 없는 구조물을 적어 둔다 — **줄이 안 서는 것보다 나쁜 것이
# 「빠진 줄조차 안 보이는 것」**이다(2026-09-09 감사: 옹벽이 터파기 0 줄이었고
# 사유도 안 났다). 관측 원단위로 가는 종류는 표에 터파기 줄이 없으면 이렇게 된다.
without_trench: list[str] = []
for structure in unit_quantity_table.get("structures") or []:
options = structure.get("options") or {}
height = float(structure.get("height_m") or options.get("height_m") or 0.0)
@@ -226,6 +231,14 @@ def structure_earthwork_rows(
backfill += amount
elif name == "잔토처리":
spoil += amount
if not any(
str(component.get("name") or "") == "터파기"
and float(component.get("amount") or 0.0) > 0
for component in structure.get("components") or []
):
without_trench.append(
str(structure.get("name") or structure.get("type_id") or "이름 없는 구조물")
)
rows: list[dict[str, Any]] = []
unmatched: list[str] = []
@@ -302,4 +315,25 @@ def structure_earthwork_rows(
in_bill_reason=SPOIL_REASON,
)
)
if without_trench:
# 값을 지어내지 않고 **빠졌다는 사실만** 낸다 — 관측 원단위(옹벽·집수정 등)는 표에
# 터파기 줄이 있는 것도 있고 없는 것도 있어, 없으면 그 구조물만 조용히 빠진다.
rows.append(
_row(
name=TRENCH_GROUP,
spec="구조물",
spec_detail=(
"⚠ 터파기가 안 선 구조물: "
+ " · ".join(sorted(set(without_trench)))
+ " — 관측 원단위 표에 터파기 줄이 없음(전개식으로 가는 종류는 높이·두께에서"
" 나오지만 관측표는 표에 있는 줄만 냄). **값을 지어내지 않음** —"
" 실무 내역서에서 그 구조물의 터파기를 어떻게 잡는지 확인할 것"
),
quantity=0.0,
in_bill=False,
in_bill_reason="터파기 물량을 못 세움 — 관측 원단위에 그 줄이 없음",
blocked_kind=BLOCKED_UNIT_DATA_MISSING,
blocked_reason="관측 원단위 표에 터파기 줄이 없음",
)
)
return rows, unmatched
@@ -1241,7 +1241,11 @@ def expand(
end = _num(structure.get("end_m"))
length = _num(options.get("length_m")) or abs(end - start)
height = _num(options.get("height_m"))
label = (names or {}).get(type_id, type_id)
# ⚠ 레지스트리 이름이 없으면 **코드값(`retaining_wall`)이 그대로 내역에 뜬다** —
# `_Wording.type_label` 이 이미 대비표를 들고 있으므로 그것을 쓴다(2026-09-09 감사).
from B08_Quantity.B08_Quantity_Wording import type_label as _type_label
label = _type_label(type_id, names)
if structure.get("attachment_label"):
# 「배수관 · 유입부 집수정」처럼 어디에 딸린 줄인지 이름에 남긴다.
parent = (names or {}).get(str(structure.get("attachment_parent_type") or ""), "")