Files
Aislo/B08_Quantity/B08_Quantity_Engine_Preparation_FrameMaterial.py
eomsangdonandClaude Opus 5 364c28a700 fix(b08): 준비공 상태 칸 「입력이 필요함」과 「값을 낼 근거가 없음」을 가름 · 인계 막힘 갈래도 상태를 따름(㉴)
- 입력이면 서는 줄(표토 두께·거리 · 임목폐기물 조사값 · 부대시설 개소 · 임목파쇄 부피 · 앞 단계 횡단·사면표) → 「입력이 필요함」 · 인계 input_missing
- 자료·산식이 없는 줄(뿌리 운반 부피 · 사방 원단위 · 사면표에 성토고 칸 없음) → 「근거 없음」 · 인계 unit_data_missing(종전 input_missing = 반대 방향 거짓 사유)
- 사면표가 섰는데 비탈 규준틀 0 개소 → 「해당 없음」
- 품셈 공종이 없는 부대시설은 개소를 넣어도 인계 input_missing 그대로(별도 단가)
- 표 머리 「입력이 필요한 줄 N · 근거 없는 줄 M」 · 700줄 — 규준틀 재료를 `_Preparation_FrameMaterial` 로 뗌(719 → 651)
- 936be972: 15줄 중 입력 7 · 근거 없음 1(뿌리 운반) · 내역 「원단위가 없습니다(우리가 만들 것)」 · 금액 불변 155,207,971

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
2026-09-15 00:44:33 +09:00

82 lines
4.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""준비공 — 규준틀 재료 줄 (`B08_Quantity_Engine_Preparation` 에서 갈라냄 · 2026-09-14 700줄 제한).
내용·규칙은 그대로 옮겼다 — 개소 × 개소당 수량을 자재 축으로 보내고,
값은 제안값이며 산출 조건이 이긴다.
"""
from __future__ import annotations
from typing import Any
#: 규준틀 재료 — **세는 것은 확정이고 수량만 몰랐던 자리**(2026-09-09).
#: 품셈 11-2·11-3 [주]④ 「재료량은 **설계수량에 따른다**」 ⇒ 품셈이 값을 안 주는 것이지
#: 「안 센다」가 아니다. 그래서 **제안값을 보이고 사용자가 고치는** 모양으로 둔다
#: (확정 ⑨·⑩ 과 같은 틀 — 「가는 기본값이고 나 선택처럼 동작할 수 있어야 함」).
#: ⚠ **제안값은 실무 관측값이지 법정 기준이 아니다** — 울진 소광 원단위 라이브러리 §8
#: 「규준틀 수평 | 개소 | 각재 50×50 0.0044㎥ · 판재 T12 0.0029㎥ · 못 0.03㎏」.
#: ⚠ **비탈 규준틀 값은 그 시트에 없다** — 수평 값을 준용하고 그 사실을 사유에 적는다.
#: ⚠ **손율은 원문에 있다** — 품셈 11-2 [주]③ 비탈 **50%** · 11-3 [주]③ 수평 **80%**.
FRAME_MATERIAL_SUGGESTED = {
"각재 50×50": (0.0044, "㎥"),
"판재 T12": (0.0029, "㎥"),
"못": (0.03, "㎏"),
}
FRAME_MATERIAL_SOURCE = (
"⚠ 실무 관측값(울진 소광 원단위 라이브러리 §8 규준틀 수평) — **법정 기준 아님**."
" 품셈 11-2·11-3 [주]④ 는 「재료량은 설계수량에 따른다」로만 둠. 산출 조건에서 고칠 수 있음"
)
FRAME_LOSS_RATE = {"비탈 규준틀": 50, "수평 규준틀": 80}
#: 자재 줄의 **이름 · 규격** — 이름 칸에 규격을 섞으면 할증률표(「각재」·「판재」)와 안 맞음
#: (2026-09-14 · 돌 줄 8210c2b7 과 같은 병). 산출 조건 키·관급구분 키(이름+규격)는 글자 그대로.
FRAME_MATERIAL_NAME_SPEC = {"각재 50×50": ("각재", "50×50"), "판재 T12": ("판재", "T12")}
def frame_material_rows(
frame_rows: list[dict[str, Any]], overrides: dict[str, Any] | None = None
) -> list[dict[str, Any]]:
"""규준틀 재료 — 개소 × 개소당 수량. **자재 축으로 보낸다.**
⚠ 개소가 안 서면 재료도 안 선다(밑수가 그 줄이다).
⚠ 값은 **제안값**이고 산출 조건에서 덮어쓸 수 있다 — 그 사실이 사유에 적힌다.
"""
given = overrides or {}
rows: list[dict[str, Any]] = []
for frame in frame_rows:
count = frame.get("amount")
if not count:
continue
loss = FRAME_LOSS_RATE.get(str(frame.get("item")), None)
for name, (default, unit) in FRAME_MATERIAL_SUGGESTED.items():
raw = given.get(name)
try:
per_ea = (
float(raw) if raw is not None and str(raw).strip() != "" else float(default)
)
except (TypeError, ValueError):
per_ea = float(default)
picked = "산출 조건에서 고른 값" if raw not in (None, "") else "제안값(기본)"
material, spec = FRAME_MATERIAL_NAME_SPEC.get(name, (name, ""))
rows.append(
{
"name": material,
"spec": spec,
"unit": unit,
"amount": float(count) * per_ea,
"destination": "material",
"source": str(frame.get("item") or "규준틀"),
"basis": (
f"{frame.get('item')} {float(count):g}개소 × {per_ea:g}{unit}/개소"
f" ({picked}) · {FRAME_MATERIAL_SOURCE}"
# ⚠ 준용이라는 사실이 상수 주석에만 있고 **화면 근거에는 없던**
# 자리다 — 값이 서면 어디서 온 값인지 안 보인다(2026-09-09 감사).
+ (
" · ⚠ 비탈 규준틀 재료량은 그 시트에 없어 **수평 값을 준용**함"
if str(frame.get("item")) == "비탈 규준틀"
else ""
)
+ (f" · 손율 {loss}%(품셈 [주]③)" if loss else "")
),
}
)
return rows