fix(B08): 구조물터파기 줄이 근거 문구 탓에 갈리던 것 합침

- 키가 (심도, 토질, 근거문구)라 같은 「암절취 · 심도 2~3m」이 측점 문구가 다르다는
  이유로 두 줄로 갈렸음(실화면 121.75 + 33.875)
- 키를 (심도, 토질)로 좁히고 근거 문구는 모아서 한 줄에 적음
- tmp/tests 1건 추가

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-08 22:58:28 +09:00
co-authored by Claude Opus 5
parent 7e41c94be7
commit cf2c894c0b
@@ -111,7 +111,10 @@ def structure_earthwork_rows(
unit_quantity_table: dict[str, Any], mapping: WorkItemMapping
) -> tuple[list[dict[str, Any]], list[str]]:
"""구조물이 낸 터파기·되메우기·잔토를 **공종 축**으로 올린다."""
trench: dict[tuple[str, str | None, str], float] = {}
# ⚠ 키는 **(심도, 토질)** 뿐이다 — 근거 문구까지 키에 넣으면 같은 「암절취 · 2~3m」이
# 측점 문구가 다르다는 이유로 **두 줄로 갈린다**(2026-09-08 실화면에서 그랬다).
trench: dict[tuple[str, str | None], float] = {}
bases: dict[tuple[str, str | None], list[str]] = {}
backfill = 0.0
spoil = 0.0
for structure in unit_quantity_table.get("structures") or []:
@@ -128,8 +131,11 @@ def structure_earthwork_rows(
if amount <= 0:
continue
if name == "터파기":
key = (band, ground, ground_basis)
key = (band, ground)
trench[key] = trench.get(key, 0.0) + amount
reasons = bases.setdefault(key, [])
if ground_basis and ground_basis not in reasons:
reasons.append(ground_basis)
elif name == "되메우기":
backfill += amount
elif name == "잔토처리":
@@ -143,11 +149,12 @@ def structure_earthwork_rows(
if code is None:
unmatched.append(TRENCH_GROUP)
order = [band for _, band in DEPTH_BANDS] + [DEPTH_OVER]
for (band, ground, ground_basis), amount in sorted(
for (band, ground), amount in sorted(
trench.items(), key=lambda item: (order.index(item[0][0]), str(item[0][1] or ""))
):
if not amount:
continue
ground_basis = " · ".join(bases.get((band, ground)) or [])
label = GROUND_TYPE_LABEL.get(str(ground), str(ground)) if ground else None
reason = WATER_BLOCKED_REASON if ground else f"{GROUND_BLOCKED_REASON}{ground_basis}"
rows.append(