- 입력이면 서는 줄(표토 두께·거리 · 임목폐기물 조사값 · 부대시설 개소 · 임목파쇄 부피 · 앞 단계 횡단·사면표) → 「입력이 필요함」 · 인계 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
82 lines
4.3 KiB
Python
82 lines
4.3 KiB
Python
"""준비공 — 규준틀 재료 줄 (`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
|