Files
Aislo/M02_MasterTemplete/M02_Machine_Hourly.py
T
eomsangdonandClaude Opus 5.5 58a3e039b3 feat(813-2): 보조 문서 부품 표지 73 · 작업량당 기계경비 6 지움 · 단가산출 목록에서 뺌 · 기계 → 부품 길
- 표지 = 수식 문서 머리 · 옛 로직 줄 칸 「부품」 — 기계경비식 9 · 작업량 틀 60(기종 = 기계표 상세구분 · 규격 열쇠) · 계수식 4 · 변환기가 옮김 · 틀 문서 9 장
- 지움 = 작업량당 기계경비 6(GC001145 · 1148 · 1151 · 1156 · 1159 · 1166 · 부르는 곳 0 · 요구 734-4 · 735-4) — 수식 문서 · 옛 로직 · 키대장 폐기 칸 · 빌더 · 변수표
- 이름 꼬리 4 = 원문 제목(지게운반 · 인력운반(기계설비) · 벽돌운반 · 수중펌프 설치 및 해체) · 키 폐기 0
- 서버 = `M01_MasterData_Parts` — M01 `/logics` · M02 `/logic-lib/logics` 목록에서 부품 뺌(1,440) · 키로 열기 · 부르기 그대로 · `/m01/parts`(기종 계산식 · 틀 · 계수식) · `/m02/logic-lib/machine-parts` · 연결 찾기 과녁에서 부품 뺌(1,444 → 1,435 · 판정 코드 그대로)
- 금액 전후 = 문서 1,513 · 셈 9,626(기본 + 옵션 표본) 모두 같음 · 791_1 지문 남은 1,513 같음 → 지문 다시 뜸 · 802_2 변환 대조 1,513 · 목록 xlsx 다시 씀(요약 수)
- 낡은 시험 = 1,519 · 1,518 기대 → 1,513 · GC001148 견본 → 같은 꼴 GF000089 토사깍기(기계)(블록 Q 39.293 · 합계 2,190) · 지운 6 을 셈하던 줄 걷음 · 목록 수 1,440 · 묶음 328 · 부르는 수 507
- 새 지킴 시험 test_813_2_parts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 20:49:52 +09:00

86 lines
3.7 KiB
Python

"""M02 기계(M01 EQ) 한 시간 값 — [항목 추가] 창에서 기계를 고르면 고정 줄 단가(PLAN 736-3).
기계 줄 = 일위대가 · 단가산출 더한줄의 고정 줄(이음 기계 EQ · 수량 1) — 단가 = 이 값(노 · 재 · 경).
셈 = M01 「건설기계」 장 기계경비 로직 가운데 그 기종을 받는 짝 차례 첫째
(`로직(GC, 기계='원문번호')` · 옵션은 기본값). 짝 차례 · 셈은
`DataFlow/M02_DF_Values._machine_hourly` 와 같은 규칙(그 폴더는 시험 길이라 따로 둠).
마스터 파일은 읽기만 · 로그인 사용자 모두.
"""
from __future__ import annotations
from typing import Any
from M01_MasterData import M01_MasterData_Store as store
cm = store.cm
_PLAIN = {"기계", "지역", "보정작업", "조종원직종"} # 이 밖의 입력 = 부착 장비 전용
def _family() -> list[dict]:
"""기계 시간당 경비 로직 — 「건설기계」 장 파일 안 · 입력 「기계」 고르기가 있는 돈 로직."""
return [
row
for name, data in store.loaded()[0].items()
if data.get("그룹") == "로직" and "건설기계" in name
for row in data.get("줄") or []
if str(row.get("결과단위") or "").startswith("원")
and any(i.get("이름") == "기계" and i.get("고르기") for i in row.get("입력") or [])
]
def _codes(row: dict) -> list:
return next(i["고르기"] for i in row["입력"] if i.get("이름") == "기계")
def _rank(row: dict) -> tuple:
"""부착 전용 · 손료만 · 보정 · 기종 수 · 키 — 작을수록 먼저."""
names = [i.get("이름") for i in row.get("입력") or []]
attach = any(n not in _PLAIN for n in names)
loss = "지역" not in names
return (attach, loss, loss and "보정작업" in names, len(_codes(row)), str(row.get("키")))
def logic_of(code: str) -> dict | None:
"""기계 원문번호 → 그 기계 시간당 경비 로직(짝 차례 첫째) · 없으면 None(813-2 M01 화면도 씀)."""
fit = [r for r in _family() if code in [str(c) for c in _codes(r)]]
return min(fit, key=_rank) if fit else None
def hourly(key: str) -> dict[str, Any]:
"""`{ok, 이름, 규격, 로직, 원문번호, 노무비, 재료비, 경비, 계}` · 못 셈 = `{ok: False, reason}`."""
if not key.startswith("EQ"):
return {"ok": False, "reason": f"「{key}」 는 기계 아님"}
try:
row = store.loaded()[1].get(key)
except cm.mf.FormulaError as e:
return {"ok": False, "reason": str(e)}
code = str(row.get("원문번호") or "")
logic = logic_of(code)
if not logic:
return {"ok": False, "reason": f"「{row.get('이름')}」 은 시간당 경비를 셀 자료가 없음"}
args = "".join(
f", {i['이름']}='{(i.get('고르기') or [''])[0]}'"
for i in logic.get("입력") or []
if i.get("이름") != "기계"
)
call = f"로직({logic['키']}, 기계='{code}'{args})"
line = {"종류": "로직", "요소": call, "이름": "기계", "단위": "시간", "수량": "1"}
holder = {
"키": "", "원문번호": "", "이름": "기계 시간", "결과단위": "원/식", "출처": "자체",
"입력": [], "중간": [], "호표": [line], "덧줄": [], "끝수": None,
} # fmt: skip
got = store.calc("", {}, holder, None)
if not got.get("ok") or "sums" not in got:
return {"ok": False, "reason": got.get("reason") or "셈 못 함"}
sums = {k: float(got["sums"][k]) for k in (*cm.mf.COST_ITEMS, "계")}
# 804-3 줄 쌓기 기계 줄 = 이 로직 + 기계='원문번호'
return {
"ok": True,
"이름": row.get("이름"),
"규격": row.get("규격"),
"로직": logic["키"],
"원문번호": code,
**sums,
}