feat(B08): 사용자 확정 5차 반영 — 제근 계열 면적 축 · 터파기 확정 · 뿌리 운반 덤프

1번 비탈 터파기 「지금 이대로」 — `BASIS_WALL` 에서 「확인 후 쓸 것」을 걷고 확정 표시로 바꿈
  (「법정 근거 없음」은 사실이라 그대로 둠)
6번 제근 밑수 **면적 축** — 산림품셈 9-21 에 밑수 표기가 없어 **건설품셈 3-9-2 「1,000㎡당」**
  을 ⚠ **교차 참조**로 빌려 씀. 제근·뿌리 적재가 같은 면적으로 섬(㎡)
  ⚠ 임목축적 등급은 **단가 갈래**이지 물량 밑수가 아님 — 비어도 값은 서고 사유만 남음
4번 뿌리 운반 **덤프**(FP-10-12) — ⚠ 운반 밑수는 부피(㎥)인데 뿌리 부피를 든 곳이 없어
  물량은 안 섬. 사용자 관찰(실무에서 운반품이 안 붙기도 함)도 사유에 적음

곁들여 — 준비공 인계 줄이 **값이 서는 순간 근거를 잃던 자리**를 고침(대분류 이름만 싣고
  있었음). 제근이 확정으로 값이 서자 「교차 참조」 표시가 사라진 것에서 드러남

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-09 12:08:23 +09:00
co-authored by Claude Opus 5
parent ad1e10b3e9
commit 691b356e2a
3 changed files with 51 additions and 21 deletions
@@ -582,7 +582,15 @@ def _preparation_rows(preparation_table: dict[str, Any]) -> list[dict[str, Any]]
"station_from": None,
"station_to": None,
"excavation_method": None,
"spec_detail": str(row.get("group") or ""),
# ⚠ **값이 서는 줄에도 근거를 싣는다**(2026-09-09) — 종전에는 대분류 이름만
# 실어, 값이 서는 순간 **왜 그 값인지가 사라졌다**(제근이 면적 축으로 확정돼
# 값이 서자 「교차 참조: 건설품셈 3-9-2」가 화면에서 사라진 자리).
# 못 서는 줄은 종전대로 `blocked_reason` 이 따로 든다.
"spec_detail": " · ".join(
part
for part in (str(row.get("group") or ""), str(row.get("reason") or ""))
if part
),
"composite_parts": None,
"structure_kind": None,
# ⚠ 못 서는 까닭을 그대로 넘긴다 — 받는 쪽이 「만들어야 할 것」 목록에 얹는다.
+33 -19
View File
@@ -192,9 +192,13 @@ TOPSOIL_HAUL_LAW = (
#: 적혀 있는데 9-21 표에는 그 표기가 없다. 등급을 넣어도 **무엇당 값인지 모르면 못 센다.**
#: 지어내지 않고 그 사실을 사유로 낸다(원문 확인이 필요한 자리).
STAND_VOLUME_CLASSES = ("소림", "중림", "밀림")
ROOT_REMOVAL_BASIS_UNKNOWN = (
"품셈 9-21 표에 **밑수 단위가 없음** — 9-20 은 「10주당」이라 적혀 있으나 9-21 에는"
" 그 표기가 없어 「무엇당 값」인지 원문으로 확인해야 함. 등급을 넣어도 그 전에는 못 셈"
#: ⭐ 2026-09-09 **사용자 확정 5차 6번** — 제근 밑수를 **면적 축**으로 확정.
#: 산림품셈 9-21 표에 밑수 표기가 없어, **건설공사 표준품셈 3-9-2 「1,000㎡당」**을 빌려 쓴다.
#: ⚠ **교차 참조 표시 필수**(CLAUDE.md 3장 — 다른 품셈을 빌려 쓸 때의 규칙).
#: ⇒ 이 확정으로 **제근·뿌리 적재·뿌리 운반·지장목제거 넷이 같은 면적 밑수**로 선다.
ROOT_REMOVAL_BASIS = (
"밑수는 **면적 축**(사용자 확정 5차 6번) — 산림품셈 9-21 에 밑수 표기가 없어"
" ⚠ **교차 참조**: 건설공사 표준품셈 **3-9-2 뿌리뽑기 「1,000㎡당」**을 빌려 씀"
)
ROOT_REMOVAL_CLASS_MISSING = (
"임목축적 등급이 아직 입력되지 않았습니다 — 품셈 9-21 [주]① 이 소림(30~60㎥/㏊)·"
@@ -210,18 +214,20 @@ def _root_removal_row(slope: dict[str, float], stand_volume_class: str | None) -
"""
area = float(slope.get("tree_removal_fill", 0.0)) + float(slope.get("tree_removal_cut", 0.0))
picked = str(stand_volume_class or "").strip()
reasons = [ROOT_REMOVAL_BASIS_UNKNOWN]
reasons = [ROOT_REMOVAL_BASIS, "대상 면적은 지장목제거와 같은 자리(벌개제근 연동)"]
if picked in STAND_VOLUME_CLASSES:
reasons.append(f"등급{picked}로 정해져 있음")
reasons.append(f"임목축적 등급 「{picked} — 품셈 9-21 [주]① 이 품을 그 축으로 가름")
else:
reasons.append(ROOT_REMOVAL_CLASS_MISSING)
# ⚠ 등급은 **품(단가) 갈래**이지 물량 밑수가 아니다 — 면적이 서면 물량은 선다.
# 등급이 비면 값은 서되 **단가를 못 고른다**는 사실만 사유로 남는다.
return {
"group": "준비공",
"item": "제근·뿌리다듬기",
"unit": "",
"amount": None,
"status": STATUS_PENDING,
"reason": " · ".join(reasons) + f" (대상 면적 {area:,.1f}㎡ — 벌개제근 연동)",
"unit": "",
"amount": area if area > 0 else None,
"status": STATUS_READY if area > 0 else STATUS_PENDING,
"reason": " · ".join(reasons),
"reference_amount": area,
"work_item_code": "FP-09-21",
}
@@ -243,34 +249,42 @@ ROOT_STEPS_NOTE = (
def _root_steps_rows(
slope: dict[str, float], stand_volume_class: str | None
) -> list[dict[str, Any]]:
"""뿌리 적재·운반 — **제근과 한 벌로 가는 뒤 단계**. 밑수가 서면 함께 선다."""
"""뿌리 적재·운반 — **제근과 한 벌로 가는 뒤 단계**. 제근이 서면 함께 선다."""
area = float(slope.get("tree_removal_fill", 0.0)) + float(slope.get("tree_removal_cut", 0.0))
return [
{
"group": "준비공",
"item": "뿌리 적재",
"unit": "",
"amount": None,
"status": STATUS_PENDING,
"unit": "",
"amount": area if area > 0 else None,
"status": STATUS_READY if area > 0 else STATUS_PENDING,
"reason": (
f"{ROOT_STEPS_NOTE} · 품셈 9-20-2 「(단위: 10주당)」 — **본수가 서야 셈**"
f" (대상 면적 {area:,.1f}㎡ · 제근과 같은 밑수)"
f"{ROOT_STEPS_NOTE} · {ROOT_REMOVAL_BASIS}"
" · ⚠ **품셈 9-20-2 는 「10주당」이라 밑수 축이 다름** — 면적 축으로 내고"
" 그 사실을 적음(본수가 서면 그 축으로 옮길 것)"
),
"reference_amount": area,
"work_item_code": "FP-09-20-02",
},
{
# ⭐ 2026-09-09 **확정 5차 4번** — 뿌리 운반은 **덤프**로 잡는다.
# ⚠ 사용자 관찰 「실제 운반품이 적용 안 되는 듯함. 나중엔 적용될 가능성도 있음」
# ⇒ 코드는 붙이되 **품이 안 붙으면 그대로 두고 사유**를 낸다. 억지로 안 붙인다.
# ⚠ 물량 축이 다르다 — 운반은 **부피(㎥)** 인데 우리가 든 것은 **면적**뿐이라
# ㎥ 를 지어내지 않고 면적을 참고로만 싣는다.
"group": "준비공",
"item": "뿌리 운반",
"unit": "",
"unit": "",
"amount": None,
"status": STATUS_PENDING,
"reason": (
f"{ROOT_STEPS_NOTE} · ⚠ **9-20 장에 운반 공종이 없음** — 10장 계열 어디에"
" 붙는지 원문이 말하지 않아 공종코드를 못 붙임"
f"{ROOT_STEPS_NOTE} · 사용자 확정 5차 4번 「**덤프**로 잡음」 —"
" ⚠ 운반 밑수는 **부피(㎥)** 인데 뿌리 부피를 든 곳이 없어 물량이 안 섬"
" (대상 면적만 있음). ⚠ 실무에서 **운반품이 안 붙는 경우가 있음**(사용자 관찰) —"
" 안 붙으면 그대로 두고 이 사유가 남음"
),
"reference_amount": area,
"work_item_code": None,
"work_item_code": "FP-10-12",
},
]