- 새 master_bundle — 호표 · 덧줄 = 비목 따라 · 비목 없는 로직 줄 = 기계경비면 경비 + 장비 · 아니면 하위 - 기계경비 판별 = 결과단위 원/시간(is_machine) — M02 엑셀 맞춤(이름 「시간당」) · B09 산근 · 산근 텍스트(입력 「기계」) 갈아 끼움 - 엔진 run 줄 덧칸 「묶음」 · 기계경비 줄 「장비」(출력 꼬리표만 · 노 · 재 · 경 몫은 줄 비목 그대로) - 정본 칸 안 더함 · 5,911 줄 중 하위 31 · 기계경비 줄 1,044 - 지킴 시험 test_712_1_bundle Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
61 lines
2.8 KiB
Python
61 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""인력 · 재료 · 경비 묶음 — **셈 때 파생**(정본에 칸 없음 · PLAN 712-1 · 요구서 원칙 5).
|
|
|
|
규칙 한 줄:
|
|
- 호표 · 덧줄 = `비목` 따라(노무비 → 인력 · 재료비 → 재료 · 경비 → 경비).
|
|
- 비목 없는 로직 줄 = 부르는 로직이 기계경비(`is_machine`)면 경비 + `장비` · 아니면 하위.
|
|
두 줄 모두 엔진 줄 `비목` 에 노무비 · 재료비 · 경비 세 몫이 그대로 남음(한 줄 · 흩어 넣기 둘 다).
|
|
|
|
기계경비 판별 = `is_machine` 한 곳 — M01 엔진 · M02 엑셀 맞춤(`M02_Hopyo_Ours`) ·
|
|
B09 산근(`B09_Estimation_Sangeun` · `_Text`)이 같이 씀.
|
|
엔진 줄 덧칸 = `묶음`(출력 꼬리표만 · 입력 값 덧칸 `값묶음` 은 715-1b 몫) · 기계경비 줄 `장비` true.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
import master_formula as mf
|
|
|
|
BUNDLES = ("인력", "재료", "경비", "하위")
|
|
BY_ITEM = {"노무비": "인력", "재료비": "재료", "경비": "경비"}
|
|
BY_KIND = {"인력": "인력", "재료": "재료", "기계": "경비"} # 비목 빈 옛 줄 받침
|
|
|
|
|
|
def is_machine(row: dict | None) -> bool:
|
|
"""기계경비 로직 — 돈 로직이고 결과단위 「원/시간」(작업량 「㎥/시간」 · 이름 「시간당」 아님)."""
|
|
if not row or "결과" in row or isinstance(row.get("흐름"), dict):
|
|
return False
|
|
return re.sub(r"\s", "", str(row.get("결과단위") or "")) == "원/시간"
|
|
|
|
|
|
def called(master, item: dict, env: dict | None = None) -> dict | None:
|
|
"""로직 줄이 부르는 로직 줄(정본) — 못 찾으면 None."""
|
|
try:
|
|
node = mf.parse(item.get("요소") or "")
|
|
if not node or node[0] != "logic":
|
|
return None
|
|
key = mf.fill(node[1], env) if env is not None and "{" in node[1] else node[1]
|
|
return master.logic(key)
|
|
except (mf.FormulaError, mf.EmptyInput, KeyError, TypeError):
|
|
return None
|
|
|
|
|
|
def bundle(master, item: dict, env: dict | None = None) -> tuple[str, bool]:
|
|
"""줄 하나(호표 · 덧줄 정본 줄) → (묶음, 장비인가)."""
|
|
if item.get("비목") in BY_ITEM:
|
|
return BY_ITEM[item["비목"]], False
|
|
if item.get("종류") == "로직":
|
|
return ("경비", True) if is_machine(called(master, item, env)) else ("하위", False)
|
|
return BY_KIND.get(str(item.get("종류")), "하위"), False
|
|
|
|
|
|
def tag(master, row: dict, lines: list[dict], env: dict | None = None) -> list[dict]:
|
|
"""엔진 `run` 줄에 `묶음`(+ 기계경비 줄 `장비`) — 줄 차례 = 호표 줄 하나씩 뒤 덧줄 하나씩."""
|
|
for item, line in zip([*row.get("호표", []), *row.get("덧줄", [])], lines):
|
|
name, machine = bundle(master, item, env)
|
|
line["묶음"] = name
|
|
if machine:
|
|
line["장비"] = True
|
|
return lines
|