Files
Aislo/B09_Estimation/B09_Estimation_Rates.py
T
eomsangdonandClaude Opus 5.5 8013fd901b feat(B09): 총괄설계내역서 · 공사원가계산서 탭 · 제비율 셈 파이썬 · TS 짝(145-4)
- compute_total(sums, estimate) · computeTotal — 설계내역서 비목 합(bill.sums) + 사용자 요율 · 손입력
- 끝수 엑셀 그대로(줄마다 ROUNDDOWN 0 · 관급 ROUNDUP −3 · 이윤 − 보정 · 부가세 + 조정) · 안전관리비 A/B 작은 쪽
- 요율 빈칸 시작 · 빈칸이면 그 줄 · 소계 빈칸 · 후보 = M01 요율_조달청제비율 글(확정 아님)
- 엑셀에 없는 현행 비목 다섯 = 줄만 · 원가계산서 = 총괄 거울 + 구성비 · 줄 누름 = 총괄 그 줄
- 엑셀 검산(순공사원가 868,874,829 · 총공사비 1,201,879,000) · 거울 시험

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TNMXVCZXMpHpVvqmFkeChL
2026-10-09 15:12:40 +09:00

48 lines
1.8 KiB
Python

"""B09 원가 요율 후보(PLAN 145-4) — M01 `요율_조달청제비율.json` 을 읽어 줄마다 후보 글 한 줄.
후보는 보이기만 — 구간(추정가격 · 공기 · 공종 · 연도)을 고르는 값은 사용자 몫이라 확정하지 않음.
요율 칸은 빈칸에서 시작(사용자 입력 · `user.estimate.rates`).
"""
from __future__ import annotations
import json
from functools import lru_cache
from pathlib import Path
from typing import Any
FILE = Path(__file__).resolve().parents[1] / "resources" / "master_data" / "요율_조달청제비율.json"
def _percents(value: Any) -> list[float]:
"""값 안 모든 rate_percent — 구간 · 연도 · 공종 갈래 통째로."""
if isinstance(value, dict):
own = value.get("rate_percent")
found = [float(own)] if isinstance(own, (int, float)) else []
return found + [
p for key, v in value.items() if key != "rate_percent" for p in _percents(v)
]
if isinstance(value, list):
return [p for item in value for p in _percents(item)]
return []
@lru_cache(maxsize=1)
def rate_candidates() -> dict[str, str]:
"""{RT 키: 「M01 RT… 3.56%」 · 「… 1.01~1.57%(구간 · 고르는 값 사용자)」} — 파일 없으면 {}."""
try:
rows = json.loads(FILE.read_text(encoding="utf-8")).get("줄") or []
except (OSError, ValueError):
return {}
out: dict[str, str] = {}
for row in rows:
percents = sorted(set(_percents(row.get("값"))))
if not percents:
text = "구간 식(고르는 값 사용자)"
elif len(percents) == 1:
text = f"{percents[0]:g}%"
else:
text = f"{percents[0]:g}~{percents[-1]:g}%(구간 · 고르는 값 사용자)"
out[str(row.get("키"))] = f"M01 {row.get('키')} {text}"
return out