- 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
48 lines
1.8 KiB
Python
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
|