Files
Aislo/B08_Quantity/B08_Quantity_Build_WorkItemMaster_Parents.py
T
eomsangdonandClaude Opus 5 a81bc844fb feat(axis): 부모 공종 모양 parent_mode — 단계 합산형 조립으로 흙깎기 암절취 금액이 섬
- 마스터 부모 94곳에 parent_mode — 기본 choose_one, 합산형은 사람이 적은 셋(9-4·9-5·12-38)만 단계·가중치
- 9-4 암절취 = 암파쇄(연암·보통암·경암, 브레이커+굴착기 조합 1/Q) + 집토(굴착기 0.7 공식) 합으로 조립
- 표에 없는 암질은 9-4-1 [주]① 평균으로만 섬 · 9-5 발파암은 발파 단계(착암기 층 없음) 사유로 막힘
- B08 인계가 흙깎기 암 갈래 이름을 갈래 값으로 넘김 · 갈래 고르기형 부모를 가리키는 줄은 오류로 막음

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BW6Jdsh18WPtYUR6THZJqn
2026-09-13 19:09:39 +09:00

71 lines
3.2 KiB
Python

"""공종 마스터 — 부모 공종의 모양 `parent_mode` (명세 2장 · 2026-09-13 축 C Ⓐ).
아래 절이 있는 공종(부모)은 두 모양이고 규칙이 다르다.
choose_one 갈래 고르기형 — 잎 하나를 고른다. **부모에 금액을 붙이지 않는다.** (기본)
sum_steps 단계 합산형 — 내역 한 줄이 곧 부모이고, 일위대가는 **잎들의 합**으로 조립한다.
⚠ **자동 판정 금지** — 표 모양으로 짐작하면 조용히 틀린다. 합산형은 아래에 **사람이 적은 것**만.
⚠ 가중치(`weight`)도 사람이 적는다 — 원문 절 제목이 준 비율만(「발파 10%」·「깎기(90%)」).
"""
from __future__ import annotations
from typing import Any
PARENT_CHOOSE_ONE = "choose_one"
PARENT_SUM_STEPS = "sum_steps"
#: 단계 합산형 부모 — (잎 코드, 가중치) 차례와 근거. ⚠ 여기 없는 부모는 전부 `choose_one`.
SUM_STEPS: dict[str, dict[str, Any]] = {
"FP-09-04": {
"steps": (("FP-09-04-01", "1"), ("FP-09-04-02", "1")),
"basis": (
"품셈 9-4 암절취 = 9-4-1 암파쇄 + 9-4-2 집토 — 같은 ㎥ 를 깨고 모음"
"(지식DB 토공_수량 「암절취 (암파쇄ㆍ집토) | 9-4」)"
),
},
"FP-09-05": {
"steps": (("FP-09-05-01", "0.1"), ("FP-09-05-02", "0.9"), ("FP-09-05-03", "1")),
"basis": (
"품셈 9-5 발파암 — 절 제목 「9-5-1 육상, 암석 절취(발파 10%)」·「9-5-2 깎기(90%)」·"
"「9-5-3 집토」(지식DB 토공_수량 「발파암 (절취 10 %ㆍ깎기 90 %ㆍ집토) | 9-5」)"
),
},
"FP-12-38": {
"steps": (("FP-12-38-02", "1"), ("FP-12-38-03", "1")),
"basis": (
"품셈 12-38 유로폼 = 12-38-2 사용수량(자재) + 12-38-3 설치 및 해체(품) — "
"12-38-1 사용횟수는 금액 단계가 아니라 사용수량의 잔존율 조건"
),
},
}
def apply_parent_modes(nodes: list[dict[str, Any]]) -> None:
"""부모 공종에 `parent_mode`(합산형이면 `steps`·`steps_basis` 까지)를 단다 — 자리에서.
⚠ 선언한 잎이 그 부모의 자식이 아니면 멈춘다 — 판이 바뀌어 절 번호가 옮겨 간 자리다.
"""
children: dict[str, list[str]] = {}
for node in nodes:
if node.get("parent_code"):
children.setdefault(node["parent_code"], []).append(node["work_item_code"])
for node in nodes:
code = node["work_item_code"]
if code not in children:
continue
declared = SUM_STEPS.get(code)
if declared is None:
node["parent_mode"] = PARENT_CHOOSE_ONE
continue
strays = [step for step, _ in declared["steps"] if step not in children[code]]
if strays:
raise ValueError(f"{code} 합산 단계가 자식이 아닙니다: {strays}")
node["parent_mode"] = PARENT_SUM_STEPS
node["steps"] = [{"code": step, "weight": weight} for step, weight in declared["steps"]]
node["steps_basis"] = declared["basis"]
missing = [code for code in SUM_STEPS if code not in children]
if missing:
raise ValueError(f"합산형으로 적은 부모가 마스터에 없습니다: {missing}")