Merge remote-tracking branches 'origin/main_laptop_1' and 'origin/sub_laptop_1' into sub_laptop_2
This commit is contained in:
@@ -3,11 +3,14 @@
|
||||
|
||||
계수 = `master_machine_coef`(TS 짝 `common_util/common_util_machine_coef.ts`) ·
|
||||
시간당 = 서버 기계경비식(`M02_Machine_Hourly.hourly` · 전국평균 · 기본 옵션) ·
|
||||
쓰는 계산식 = `M02_Machine_Hourly.pick`(목록 › 꼴 · 822-2) · [새 기계] 저장 = 꼴에 맞는 식 목록에 원문번호 등록 ·
|
||||
M01 에서 만든 기계(출처 모두 「자체」)를 지우면 그 번호 기계가 더 없을 때 목록에서 뺌(`register`) ·
|
||||
마스터 파일은 읽기만 — 쓰기는 `Store_Make.save`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import json
|
||||
import re
|
||||
from decimal import Decimal
|
||||
@@ -102,6 +105,78 @@ def hourly(keys: list[str]) -> dict[str, dict]:
|
||||
return out
|
||||
|
||||
|
||||
def formula(row: dict) -> dict:
|
||||
"""기계 줄(저장 전 고친 값도) → 쓰는 계산식 {키, 이름, 방법 목록|꼴|그 기계 식, 까닭}(822-2 상세 페이지)."""
|
||||
from M02_MasterTemplete import M02_Machine_Hourly as mh # M02 가 M01 을 부름 — 늦게
|
||||
|
||||
code = str(row.get("원문번호") or "")
|
||||
got = mh.pick({**row, "값": store._dec(row.get("값") or {})})
|
||||
how = "목록" if mh.listed(code) else "그 기계 식" if got and mh._own(code) else "꼴"
|
||||
base = {"방법": how, "까닭": mh.why({**row, "값": store._dec(row.get("값") or {})}, got)}
|
||||
return base | ({"키": got["키"], "이름": got.get("이름")} if got else {})
|
||||
|
||||
|
||||
def _family_files() -> dict[str, str]:
|
||||
"""기계경비식 키 → 로직 파일 이름."""
|
||||
return {
|
||||
str(r.get("키")): name
|
||||
for name, data in store.loaded()[0].items()
|
||||
if data.get("그룹") == "로직" and "건설기계" in name
|
||||
for r in data.get("줄") or []
|
||||
}
|
||||
|
||||
|
||||
def register(batch: list[dict]) -> None:
|
||||
"""[새 기계] 저장 = 꼴 식 「기계」 목록에 그 원문번호 더함 · M01 에서 만든 기계(출처 모두 「자체」)를
|
||||
지우면 같은 번호 기계가 더 없을 때 목록에서 뺌 — 로직 파일 고침을 같은 저장 묶음에 붙임(정본 저장 길)."""
|
||||
from M02_MasterTemplete import M02_Machine_Hourly as mh # M02 가 M01 을 부름 — 늦게
|
||||
from M02_MasterTemplete import M02_MyMachine as mym
|
||||
|
||||
part = next((p for p in batch if p.get("file") == FILE), None)
|
||||
if part is None:
|
||||
return
|
||||
rows = _rows()
|
||||
gone = {str(c.get("key")) for c in part.get("changes") or [] if c.get("op") == "delete"}
|
||||
add: dict[str, list[str]] = {}
|
||||
drop: set[str] = set()
|
||||
for ch in part.get("changes") or []:
|
||||
row = ch.get("row") if ch.get("op") == "add" else None
|
||||
code = str((row or {}).get("원문번호") or "").strip()
|
||||
if row and code and not mh.listed(code) and not mh._own(code):
|
||||
key = mym.logic_key({**row, "값": store._dec(row.get("값") or {})})
|
||||
if key and code not in add.get(key, []):
|
||||
add.setdefault(key, []).append(code)
|
||||
old = next((r for r in rows if r.get("키") == ch.get("key")), None)
|
||||
if (
|
||||
ch.get("op") == "delete"
|
||||
and old
|
||||
and set((old.get("출처") or {}).values()) == {OWN_SOURCE}
|
||||
):
|
||||
code = str(old.get("원문번호") or "")
|
||||
if code and not any(
|
||||
str(r.get("원문번호")) == code and r.get("키") not in gone for r in rows
|
||||
):
|
||||
drop.add(code)
|
||||
if not add and not drop:
|
||||
return
|
||||
files = _family_files()
|
||||
for name in dict.fromkeys(files.values()):
|
||||
changes = []
|
||||
for logic in store.read(name)[0].get("줄") or []:
|
||||
ins = logic.get("입력") or []
|
||||
pick = next((i for i in ins if i.get("이름") == "기계" and "고르기" in i), None)
|
||||
if pick is None:
|
||||
continue
|
||||
codes = [c for c in pick["고르기"] if str(c) not in drop]
|
||||
codes += [c for c in add.get(str(logic["키"]), []) if c not in codes]
|
||||
if codes != pick["고르기"]:
|
||||
new = copy.deepcopy(logic)
|
||||
next(i for i in new["입력"] if i.get("이름") == "기계")["고르기"] = codes
|
||||
changes.append({"op": "edit", "key": logic["키"], "row": new})
|
||||
if changes:
|
||||
batch.append({"file": name, "version": store.read(name)[1], "changes": changes})
|
||||
|
||||
|
||||
# ── 쓰는 곳 ─────────────────────────────────────────────────────────
|
||||
def _logic_index() -> tuple[dict[str, list[str]], dict[str, list[str]]]:
|
||||
"""(원문번호 → 로직 「키 이름」 · 기계 키 → 로직) — 기계 고르기 · 식 안 EQ 키."""
|
||||
@@ -218,5 +293,9 @@ def fix(part: dict) -> None:
|
||||
values.update(got)
|
||||
was_unit = (old or {}).get("단위") or {}
|
||||
was_src = (old or {}).get("출처") or {}
|
||||
row["단위"] = {k: was_unit.get(k, units.get(k, "")) for k in values}
|
||||
row["출처"] = {k: was_src.get(k, OWN_SOURCE) for k in values}
|
||||
unit, src = (
|
||||
row.get("단위") or {},
|
||||
row.get("출처") or {},
|
||||
) # 보낸 칸이 있으면 그 글(822-2 빌더)
|
||||
row["단위"] = {k: unit.get(k) or was_unit.get(k, units.get(k, "")) for k in values}
|
||||
row["출처"] = {k: src.get(k) or was_src.get(k, OWN_SOURCE) for k in values}
|
||||
|
||||
@@ -53,5 +53,25 @@ export const fetchMachineUses = async (key: string): Promise<string[]> =>
|
||||
export const findMachines = async (q: string): Promise<Row[]> =>
|
||||
(await get<{ rows: Row[] }>("/find", { q })).rows;
|
||||
|
||||
/** 쓰는 계산식(822-2) — 방법 = 목록 · 꼴 · 그 기계 식 · 까닭 = 값이 모자란 칸 */
|
||||
export interface MachineFormula {
|
||||
키?: string;
|
||||
이름?: string;
|
||||
방법: "목록" | "꼴" | "그 기계 식";
|
||||
까닭: string;
|
||||
}
|
||||
|
||||
export async function fetchMachineFormula(row: Row): Promise<MachineFormula> {
|
||||
const res = await fetch(`${API_BASE_URL}/m01/machine/formula`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(row),
|
||||
});
|
||||
const body = (await res.json()) as MachineFormula & { detail?: unknown };
|
||||
if (!res.ok) throw new Error(String(body.detail ?? `HTTP ${res.status}`));
|
||||
return body;
|
||||
}
|
||||
|
||||
export const fetchMachineRow = (key: string): Promise<{ version: string; row: Row }> =>
|
||||
get("/row", { key });
|
||||
|
||||
@@ -288,6 +288,12 @@ def get_machine_row(key: str) -> dict:
|
||||
return _call(machine.row, key)
|
||||
|
||||
|
||||
@router.post("/machine/formula")
|
||||
def post_machine_formula(row: dict[str, Any]) -> dict:
|
||||
"""기계 줄(저장 전 고친 값도) → 쓰는 계산식 {키 · 이름 · 방법 · 까닭}(822-2)."""
|
||||
return _call(machine.formula, row)
|
||||
|
||||
|
||||
@router.post("/calc")
|
||||
def post_calc(body: CalcBody) -> dict:
|
||||
with store.cm.mf.mp.choosing(body.고름):
|
||||
|
||||
@@ -294,6 +294,7 @@ def save(batch: list[dict], confirmed: bool = False) -> dict:
|
||||
row.update(별칭=text) if text else row.pop("별칭")
|
||||
machine.fix(part) # 기계 줄 = 계수 서버 재계산 · 단위 · 출처 채움(821-2)
|
||||
_keep_same(part)
|
||||
machine.register(batch) # [새 기계] = 꼴 식 목록 등록(822-2 · 개정확인 밖 — 자동 고침)
|
||||
fresh = False
|
||||
for part in batch:
|
||||
if part.get("file") != OWN:
|
||||
|
||||
@@ -132,7 +132,8 @@ export function renderMachines(
|
||||
if (!want.length) return;
|
||||
try {
|
||||
const got = await fetchMachineHourly(want);
|
||||
for (const [k, h] of Object.entries(got)) hourly.set(k, h.계 === undefined ? "—" : num(h.계));
|
||||
for (const [k, h] of Object.entries(got))
|
||||
hourly.set(k, h.계 === undefined ? (h.reason ?? "—") : num(h.계));
|
||||
} catch {
|
||||
for (const k of want) hourly.set(k, "—");
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* =============================================================================
|
||||
* M01_MasterData_UI_MachineDetail.ts
|
||||
* M01 기계 상세 페이지(PLAN 821-2 · 요구 790-2 · 791) — 기계 양식 부품 + 원문번호 · 원문 · 구분 ·
|
||||
* 상세구분 · 별칭 · 비고 · 쓰는 곳 · 지우기(쓰는 곳 보이고 확인).
|
||||
* 상세구분 · 별칭 · 비고 · 쓰는 계산식(822-2 · 서버 식 고름) · 쓰는 곳 · 지우기(쓰는 곳 보이고 확인).
|
||||
* 고침은 초안(sessionStorage)에 바로 쌓임 → 페이지 [저장] 한 번에 서버로(자동저장 없음) ·
|
||||
* 서버가 계수를 계수 짝으로 다시 셈 · 단위 · 출처 칸을 채움(`M01_MasterData_Machine.fix`).
|
||||
* 대상 = 키(EQ…) · 저장 전 새 줄 `add:<차례>` · 새 기계 `new`(비슷한 기계에서 시작이 펼쳐짐).
|
||||
@@ -22,6 +22,7 @@ import { setLeaveGuard } from "../A00_Common/router";
|
||||
import type { Row } from "./M01_MasterData_Api_Fetch";
|
||||
import { addRow, editRow, peek, removeAdd, setAdd, toggleDelete } from "./M01_MasterData_Draft";
|
||||
import {
|
||||
fetchMachineFormula,
|
||||
fetchMachineLists,
|
||||
fetchMachineRow,
|
||||
fetchMachineUses,
|
||||
@@ -154,6 +155,29 @@ async function build(host: HTMLElement, opts: MachineDetailOptions, alive: () =>
|
||||
}
|
||||
cur = ordered;
|
||||
checkSame(s.name, s.spec);
|
||||
paintFormula();
|
||||
};
|
||||
|
||||
/* --- 쓰는 계산식(서버 식 고름 · 고친 값으로) --- */
|
||||
const formulaBox = el("section", { className: "m01-machine-detail__uses" });
|
||||
let formulaTimer: number | undefined;
|
||||
const paintFormula = (): void => {
|
||||
window.clearTimeout(formulaTimer);
|
||||
formulaTimer = window.setTimeout(async () => {
|
||||
const got = await fetchMachineFormula(cur).catch(() => null);
|
||||
if (!got || !alive()) return;
|
||||
const how =
|
||||
got.방법 === "목록"
|
||||
? L("M01_MachineFormulaListed")
|
||||
: got.방법 === "그 기계 식"
|
||||
? L("M01_MachineFormulaOwn")
|
||||
: L("M01_MachineFormulaShape");
|
||||
formulaBox.replaceChildren(
|
||||
el("strong", { text: L("M01_MachineFormula") }),
|
||||
createText(got.키 ? `${got.키} ${got.이름 ?? ""} · ${how}` : L("M01_MachineFormulaNone")),
|
||||
...(got.까닭 ? [createText(got.까닭, "warning")] : []),
|
||||
);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
/* --- 같은 이름 · 규격 알림 --- */
|
||||
@@ -275,10 +299,12 @@ async function build(host: HTMLElement, opts: MachineDetailOptions, alive: () =>
|
||||
notice,
|
||||
metaBox,
|
||||
form.root,
|
||||
formulaBox,
|
||||
usesBox,
|
||||
],
|
||||
}),
|
||||
);
|
||||
paintFormula();
|
||||
if (opts.target === "new")
|
||||
host.querySelector<HTMLDetailsElement>("details")?.setAttribute("open", "");
|
||||
}
|
||||
|
||||
@@ -258,59 +258,32 @@ def _user(uid: str, local: list[dict]) -> dict:
|
||||
|
||||
MACHINE_SEP = "#" # 입력 판(sub3) 기계 요소 ref 「EQ키#칸」
|
||||
HOURLY = "시간당 경비" # 기계 칸 이름 — 기계 시간당 경비 로직으로 셈(기종 → 로직 짝)
|
||||
_MACHINE_PLAIN = {"기계", "지역", "보정작업", "조종원직종"} # 이 밖의 입력 = 부착 장비 전용
|
||||
|
||||
|
||||
def _machine_family() -> list[dict]:
|
||||
"""기계 시간당 경비 로직 — 「건설기계」 장 파일 안 · 입력 「기계」 고르기가 있는 돈 로직."""
|
||||
files = store.loaded()[0]
|
||||
return [
|
||||
row
|
||||
for name, data in files.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 _machine_rank(row: dict) -> tuple:
|
||||
"""짝 차례(옛 EasyCalc `pickMachine` 와 같음) — 부착 전용 · 손료만 · 보정 · 기종 수 · 키."""
|
||||
names = [i.get("이름") for i in row.get("입력") or []]
|
||||
codes = next(i.get("고르기") for i in row["입력"] if i.get("이름") == "기계")
|
||||
attach = any(n not in _MACHINE_PLAIN for n in names)
|
||||
loss = "지역" not in names
|
||||
return (attach, loss, loss and "보정작업" in names, len(codes), str(row.get("키")))
|
||||
|
||||
|
||||
def _machine_hourly(key: str, inputs: dict) -> dict:
|
||||
"""기계 한 시간 값 — 기종을 받는 기계경비 로직 가운데 짝 차례 첫째 · 빈 입력은 첫 고르기."""
|
||||
"""기계 한 시간 값 — 식 고름 = `M02_Machine_Hourly.pick`(목록 › 꼴 · 822-2) · 빈 입력은 첫 고르기."""
|
||||
from M02_MasterTemplete import M02_Machine_Hourly as mh
|
||||
|
||||
row, why = _brief(key, "기계")
|
||||
if row is None:
|
||||
return {"ok": False, "reason": why}
|
||||
code = str(row.get("원문번호") or "")
|
||||
fit = [r for r in _machine_family() if code in [str(c) for c in _codes(r)]]
|
||||
if not fit:
|
||||
return {"ok": False, "reason": f"「{row.get('이름')}」 은 시간당 경비를 셀 자료가 없음"}
|
||||
logic = min(fit, key=_machine_rank)
|
||||
logic = mh.pick(row)
|
||||
if lack := mh.why(row, logic):
|
||||
return {"ok": False, "reason": f"「{row.get('이름')}」 — {lack}"}
|
||||
given = {}
|
||||
for spec in logic.get("입력") or []:
|
||||
name = spec.get("이름")
|
||||
if name != "기계":
|
||||
given[name] = inputs.get(name, (spec.get("고르기") or [None])[0])
|
||||
args = "".join(f", {n}='{v}'" for n, v in given.items())
|
||||
ref = f"로직({logic['키']}, 기계='{code}'{args})"
|
||||
args = "".join(f", {n if n.isidentifier() else repr(n)}='{v}'" for n, v in given.items())
|
||||
mine = f", 기계='{code}'" if mh.takes_machine(logic) else ""
|
||||
ref = f"로직({logic['키']}{mine}{args})"
|
||||
line = {"종류": "로직", "요소": ref, "이름": "기계", "단위": "시간", "수량": "1"}
|
||||
got = _money(_calc({}, _row(line, ())), "계")
|
||||
return {**got, "name": row.get("이름"), "unit": "원/시간"} if got["ok"] else got
|
||||
|
||||
|
||||
def _codes(row: dict) -> list:
|
||||
return next(
|
||||
(i.get("고르기") or [] for i in row.get("입력") or [] if i.get("이름") == "기계"), []
|
||||
)
|
||||
|
||||
|
||||
def one_value(item: dict, local: list[dict] | None = None) -> dict:
|
||||
"""물음 한 줄 `CfQuery {id, group, ref? · table? · unit? · field? · inputs?}` → `CfAnswer`.
|
||||
|
||||
|
||||
@@ -186,10 +186,11 @@ class _Collector:
|
||||
return
|
||||
self.add(base)
|
||||
if field == dv.HOURLY:
|
||||
code = str((self.whole.index.get(base[:2], {}).get(base) or {}).get("원문번호") or "")
|
||||
for fit in dv._machine_family():
|
||||
if code in [str(c) for c in dv._codes(fit)]:
|
||||
self.logic(str(fit.get("키")))
|
||||
from M02_MasterTemplete import M02_Machine_Hourly as mh
|
||||
|
||||
row = self.whole.index.get(base[:2], {}).get(base) or {}
|
||||
if got := mh.pick(row): # 식 고름 한 곳(822-2)
|
||||
self.logic(str(got.get("키")))
|
||||
|
||||
def logic(self, key: str) -> None:
|
||||
if key in self.logics:
|
||||
|
||||
@@ -7,17 +7,30 @@
|
||||
마스터 파일은 읽기만 · 로그인 사용자 모두.
|
||||
기계표 = M01 + 지금 층 내 기계(821-1 · `M02_MyMachine` — 식은 채운 칸으로 고른 같은 GC 식 · 직접 = 그 값) ·
|
||||
층을 모르는 길(`/api/m02/logic-lib/machine-hourly`)은 M01 만.
|
||||
식 고름 한 곳(822-2 · `pick`) = ㉠ 원문번호가 식 「기계」 목록에 있으면 그 식(짝 차례) ㉡ 그 기계만의 식
|
||||
(`_own`) ㉢ 없으면 꼴(채운 칸 · `M02_MyMachine.logic_key`) — M01 [새 기계] · 불러오기 · 데이터 흐름 ·
|
||||
줄 쌓기 · 단가산출 기초가 다 이것을 씀 · 못 고름 · 값 모자람 = 까닭 글(`why`).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
from M01_MasterData import M01_MasterData_Store as store
|
||||
from M02_MasterTemplete import M02_MyMachine as mym
|
||||
|
||||
cm = store.cm
|
||||
_PLAIN = {"기계", "지역", "보정작업", "조종원직종"} # 이 밖의 입력 = 부착 장비 전용
|
||||
_PLAIN = {
|
||||
"기계",
|
||||
"지역",
|
||||
"보정작업",
|
||||
"조종원직종",
|
||||
"전력 계약종별",
|
||||
} # 이 밖의 입력 = 부착 장비 전용
|
||||
_TEXT = {"주연료종류", "조종원직종"} # 글 칸 — 나머지 기계 줄 값 칸은 수
|
||||
_FIELD = re.compile(r"EQ:\{기계\}\.([^\s*/+()\-,]+)")
|
||||
HOUR_UNIT = "10^-7/시간"
|
||||
|
||||
|
||||
def _family() -> list[dict]:
|
||||
@@ -54,12 +67,27 @@ def _operated(code: str) -> bool:
|
||||
|
||||
|
||||
def logic_of(code: str) -> dict | None:
|
||||
"""기계 원문번호 → 그 기계 시간당 경비 로직(짝 차례 첫째) · 없으면 None(813-2 M01 화면 ·
|
||||
불러오기 `M02_Doc_Import.hourly_link` 도 씀). 기계표 조종원 > 0 = 조종원 호표 있는 식 먼저
|
||||
(「조종원 없는 기종」 목록에 겹친 기계 — 진동롤러(핸드가이드식) · 고소작업차 …)."""
|
||||
fit = [r for r in _family() if code in [str(c) for c in _codes(r)]]
|
||||
"""기계 원문번호 → 그 기계 시간당 경비 로직 · 없으면 None(813-2 M01 화면 · 불러오기
|
||||
`M02_Doc_Import.hourly_link` 도 씀) — `pick` 과 같음(그 원문번호 기계 줄로)."""
|
||||
index = mym.whole()
|
||||
row = (index.numbers.get("EQ") or {}).get(code) or {"원문번호": code}
|
||||
return pick(row)
|
||||
|
||||
|
||||
def listed(code: str) -> bool:
|
||||
"""원문번호가 어느 기계경비식 「기계」 목록에 있는지(M01 [새 기계] 식 등록 · 상세 「쓰는 계산식」)."""
|
||||
return bool(code) and any(code in [str(c) for c in _codes(r)] for r in _family())
|
||||
|
||||
|
||||
def pick(row: dict) -> dict | None:
|
||||
"""기계 줄 → 시간당 경비 식 — ㉠ 목록 ㉡ 그 기계만의 식 ㉢ 꼴 · 못 고름 = None(까닭 = `why`)."""
|
||||
code = str(row.get("원문번호") or "")
|
||||
fit = [r for r in _family() if code and code in [str(c) for c in _codes(r)]]
|
||||
if not fit:
|
||||
return _own(code) or mym.logic_for(code)
|
||||
if got := _own(code):
|
||||
return got
|
||||
key = None if _day_loss(row) else mym.logic_key(row)
|
||||
return mym.whole().logic(key) if key else None
|
||||
op = _operated(code)
|
||||
|
||||
def order(row: dict) -> tuple:
|
||||
@@ -84,6 +112,47 @@ def _own(code: str) -> dict | None:
|
||||
return None
|
||||
|
||||
|
||||
def _day_loss(row: dict) -> str:
|
||||
"""손료계수 단위가 시간당(10⁻⁷)이 아님(산림품셈 「1일 1대당」) — 그 단위 글 · 아니면 빈 글."""
|
||||
unit = str((row.get("단위") or {}).get("손료계수") or HOUR_UNIT)
|
||||
return "" if unit == HOUR_UNIT or "손료계수" not in (row.get("값") or {}) else unit
|
||||
|
||||
|
||||
def _is_num(v: Any) -> bool:
|
||||
try:
|
||||
float(v)
|
||||
except (TypeError, ValueError):
|
||||
return False
|
||||
return not isinstance(v, bool)
|
||||
|
||||
|
||||
def why(row: dict, logic: dict | None) -> str:
|
||||
"""시간당 경비를 못 내는 까닭 한 줄(값이 정말 모자람) · 셀 수 있으면 빈 글."""
|
||||
vals = row.get("값") or {}
|
||||
if logic is None:
|
||||
if unit := _day_loss(row):
|
||||
return f"손료계수 단위 「{unit}」 — 시간당 식 없음(일 단위 손료)"
|
||||
if not _is_num(vals.get("주연료")) and vals.get("주연료") not in (None, ""):
|
||||
return f"주연료 「{vals['주연료']}」 — 수 아님"
|
||||
if float(vals.get("조종원") or 0) > 0 and not vals.get("조종원직종"):
|
||||
return "조종원직종 없음"
|
||||
if vals.get("주연료") and vals.get("전력"):
|
||||
return "주연료 · 전력 둘 다 — 식 없음"
|
||||
return "손료 계수 셋(상각 · 정비 · 관리) 없음"
|
||||
text = " ".join(str(x.get(k)) for k in ("식", "수량") for p in ("중간", "호표", "덧줄")
|
||||
for x in logic.get(p) or []) # fmt: skip
|
||||
lost, odd = [], []
|
||||
for name in dict.fromkeys(_FIELD.findall(text)):
|
||||
v = vals.get(name)
|
||||
if v in (None, ""):
|
||||
lost.append(name)
|
||||
elif name not in _TEXT and not _is_num(v):
|
||||
odd.append(f"{name} 「{v}」 — {'범위' if '∼' in str(v) else '수 아님'}")
|
||||
elif name == "주연료종류" and f"{v}:전국평균" not in (mym.whole().numbers.get("MO") or {}):
|
||||
odd.append(f"주연료종류 「{v}」 — 유가 표에 없음")
|
||||
return " · ".join([*([f"{' · '.join(lost)} 없음"] if lost else []), *odd])
|
||||
|
||||
|
||||
def takes_machine(logic: dict) -> bool:
|
||||
"""식이 「기계」 입력(원문번호 고르기)을 받는지 — 안 받는 식(GF000145)엔 기계='…' 를 안 넘김."""
|
||||
return any(i.get("이름") == "기계" for i in logic.get("입력") or [])
|
||||
@@ -100,9 +169,9 @@ def hourly(key: str) -> dict[str, Any]:
|
||||
if mym.mine(key):
|
||||
return mym.hourly(row, whole)
|
||||
code = str(row.get("원문번호") or "")
|
||||
logic = logic_of(code)
|
||||
if not logic:
|
||||
return {"ok": False, "reason": f"「{row.get('이름')}」 은 시간당 경비를 셀 자료가 없음"}
|
||||
logic = pick(row)
|
||||
if lack := why(row, logic):
|
||||
return {"ok": False, "reason": lack, **({"로직": logic["키"]} if logic else {})}
|
||||
args = "".join( # 빈칸 든 입력 이름(「전력 계약종별」 · 820-1 파워트로웰)은 따옴표로
|
||||
f", {n if (n := i['이름']).isidentifier() else repr(n)}='{(i.get('고르기') or [''])[0]}'"
|
||||
for i in logic.get("입력") or []
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* · (785-3) `oil` = M01 유가전력(MO · `/logic-lib/elements?group=재료` 의 MO 줄) 고름 · 고정 줄 꼴 = 이음 유가 MO ·
|
||||
* 재료비 = 지금 값(셈은 M01 값) · 「M01 전체」 탭 재료 아래
|
||||
* · (821-3) `mine` = 개인 층 내 기계 묶음(품셈 기계 위 · 구분 「내 기계」 · 출처 「개인 키」 · 금액 = 서버 시간당) ·
|
||||
* 머리 [새 기계 만들기](양식 창 → 저장하면 그 기계로 고름) · 「시간당 값 직접」 내 기계 = 줄 쌓기 식 없음 → 회색
|
||||
* 머리 [새 기계 만들기](양식 창 → 저장하면 그 기계로 고름) · 「시간당 값 직접」 내 기계 = 직접 값 식 GC001199(822-2) · 식 없는 내 기계 = 회색
|
||||
* ========================================================================== */
|
||||
|
||||
import { createDataTable } from "@ui/ui_template_data_table";
|
||||
@@ -288,7 +288,7 @@ export function openFindPicker(opt: FindPickOptions): void {
|
||||
: take(() => put(e)),
|
||||
};
|
||||
});
|
||||
/** 821-3 내 기계 줄 — 금액 = 서버 시간당 · 직접 = 회색(줄 쌓기 식 없음) */
|
||||
/** 821-3 내 기계 줄 — 금액 = 서버 시간당 · 식 없음(서버 로직 없음) = 회색 · 직접 = GC001199(822-2) */
|
||||
const mineLines = (q: string): Line[] => {
|
||||
const words = q.toLowerCase().split(/\s+/).filter(Boolean);
|
||||
return mines
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
내 기계 없는 층 = M01 그대로. 단가산출 사본 · [단가 갱신] · 「단가새값」(`M02_Sangeun_Copy`) ·
|
||||
기계 찾기(`M02_Machine_Find`) · 시간당(`M02_Machine_Hourly`) · 사본 모으기(`M02_Item_Prices.collect`)가
|
||||
이 색인을 읽음 — 층을 모르는 길(`/api/m02/logic-lib/machine-hourly` 등)은 M01 만.
|
||||
식 고름(채운 칸) = 연료 · 조종원 둘 다 GC000268 · 연료만 GC000272 · 조종원만 GC000276 · 없음 GC000273.
|
||||
전력 칸은 담기만(M01 기계경비 식에 전력 줄 없음).
|
||||
식 고름(채운 칸 · `logic_key` — M01 기계 목록 밖 줄도 같은 규칙 · 822-2) = 연료 + 조종원 GC000268(직종 없음
|
||||
GC000275) · 연료만 GC000272(손료계수 한 칸 GC001198) · 조종원만 GC000276 · 전력 GC001196(+ 조종원 GC001197) ·
|
||||
없음 GC000273 · 직접 GC001199(시간당 값 = 셈 꼴 값 칸 노무비 · 재료비 · 경비).
|
||||
권한(본인 개인 층 · 맡은 회사 관리자)은 길(`M02_MyMachine_Router`) 몫.
|
||||
"""
|
||||
|
||||
@@ -43,6 +44,8 @@ UNITS = {
|
||||
} # fmt: skip
|
||||
LOGIC = {(True, True): "GC000268", (True, False): "GC000272",
|
||||
(False, True): "GC000276", (False, False): "GC000273"} # fmt: skip
|
||||
JOB_IN, ONE_FUEL = "GC000275", "GC001198" # 직종 입력 · 손료계수 한 칸 연료
|
||||
POWER, POWER_CREW, DIRECT_KEY = "GC001196", "GC001197", "GC001199"
|
||||
|
||||
|
||||
def mine(key: Any) -> bool:
|
||||
@@ -80,6 +83,8 @@ def rows(folder: Path | None = None) -> list[dict]:
|
||||
def engine(row: dict) -> dict:
|
||||
"""셈 꼴 — 바로 = 상각비계수 ← 손료계수 · 정비 · 관리 0 · 빈 연료 · 조종원 칸 = 0 · 수 = Decimal."""
|
||||
vals = dict(row.get("값") or {})
|
||||
if row.get("방식") == DIRECT: # 직접 식(GC001199)이 읽는 칸
|
||||
vals = {k: (row.get("시간당") or {}).get(k) or 0 for k in COSTS}
|
||||
if row.get("방식") == EASY:
|
||||
vals |= {"상각비계수": vals.get("손료계수") or 0, "정비비계수": 0, "관리비계수": 0}
|
||||
if row.get("방식") != DIRECT:
|
||||
@@ -123,18 +128,39 @@ def keys_in(doc: Any) -> list[str]:
|
||||
return sorted(set(FIND.findall(json.dumps(doc, ensure_ascii=False, default=str))))
|
||||
|
||||
|
||||
def logic_key(row: dict) -> str:
|
||||
def _pos(v: Any) -> bool:
|
||||
try:
|
||||
return not isinstance(v, bool) and float(v) > 0
|
||||
except (TypeError, ValueError):
|
||||
return False
|
||||
|
||||
|
||||
def logic_key(row: dict) -> str | None:
|
||||
"""꼴(채운 칸) → 시간당 경비 식 키 · 못 고름(직종 없는 조종원만 · 연료 + 전력 · 수 아닌 연료 글) = None ·
|
||||
계수 셋(상각 · 정비 · 관리) 없음 = 손료계수 한 칸 식(연료만) · 그 밖은 그 식 + 모자란 칸 까닭."""
|
||||
if row.get("방식") == DIRECT:
|
||||
return DIRECT_KEY
|
||||
vals = row.get("값") or {}
|
||||
return LOGIC[(float(vals.get("주연료") or 0) > 0, float(vals.get("조종원") or 0) > 0)]
|
||||
fuel, crew, power = (_pos(vals.get(k)) for k in ("주연료", "조종원", "전력"))
|
||||
job = bool(vals.get("조종원직종"))
|
||||
three = all(vals.get(k) is not None for k in COEFS)
|
||||
if vals.get("주연료") not in (None, "", 0) and not fuel or fuel and power:
|
||||
return None
|
||||
if power:
|
||||
return POWER_CREW if crew and job else None if crew else POWER
|
||||
if fuel and not crew:
|
||||
return LOGIC[(True, False)] if three else ONE_FUEL
|
||||
if crew:
|
||||
return LOGIC[(fuel, True)] if job else JOB_IN if fuel else None
|
||||
return LOGIC[(False, False)]
|
||||
|
||||
|
||||
def logic_for(code: str) -> dict | None:
|
||||
"""내 기계 원문번호 → 시간당 경비 식(채운 칸으로 고름) · 내 기계 아님 = None."""
|
||||
index = whole()
|
||||
row = (index.numbers.get("EQ") or {}).get(code)
|
||||
if row is None or not mine(row.get("키")) or row.get("방식") == DIRECT:
|
||||
return None
|
||||
return index.logic(logic_key(row))
|
||||
key = logic_key(row) if row is not None and mine(row.get("키")) else None
|
||||
return index.logic(key) if key else None
|
||||
|
||||
|
||||
def hourly(row: dict, index: Any) -> dict[str, Any]:
|
||||
@@ -142,11 +168,21 @@ def hourly(row: dict, index: Any) -> dict[str, Any]:
|
||||
head = {"이름": row.get("이름"), "규격": row.get("규격"), "원문번호": row.get("원문번호")}
|
||||
if row.get("방식") == DIRECT:
|
||||
sums = {k: float((row.get("시간당") or {}).get(k) or 0) for k in COSTS}
|
||||
return {"ok": True, **head, "로직": None, "직접": True, **sums, "계": sum(sums.values())}
|
||||
return {
|
||||
"ok": True,
|
||||
**head,
|
||||
"로직": DIRECT_KEY,
|
||||
"직접": True,
|
||||
**sums,
|
||||
"계": sum(sums.values()),
|
||||
}
|
||||
import master_cut as mcut
|
||||
|
||||
mf = m01.cm.mf
|
||||
logic = index.logic(logic_key(row))
|
||||
key = logic_key(row)
|
||||
if key is None:
|
||||
return {"ok": False, **head, "reason": "식 없음 — 연료 · 전력은 하나만"}
|
||||
logic = index.logic(key)
|
||||
given = {i["이름"]: (i.get("고르기") or [""])[0] for i in logic.get("입력") or []}
|
||||
given["기계"] = str(row.get("원문번호"))
|
||||
try:
|
||||
@@ -203,6 +239,8 @@ def clean(raw: Any) -> dict[str, Any]:
|
||||
need = ("가격", "손료계수") if how == EASY else ("가격", *RATIOS)
|
||||
if lost := [k for k in need if not vals.get(k)]:
|
||||
raise _bad(f"빈 칸 — {' · '.join(lost)}")
|
||||
if vals.get("주연료") and vals.get("전력"):
|
||||
raise _bad("주연료 · 전력은 하나만(원문 운전경비 표 한 칸)")
|
||||
drop = (*RATIOS, *COEFS) if how == EASY else ()
|
||||
vals = {k: v for k, v in vals.items() if k not in drop}
|
||||
if how == BOOK:
|
||||
|
||||
@@ -51,7 +51,7 @@ const TEXT = {
|
||||
// 기계 고르기 창 · 줄 쌓기
|
||||
Pick_Group: "내 기계",
|
||||
Pick_New: "새 기계 만들기",
|
||||
Pick_Direct: "시간당 값 직접 기계 — 줄 쌓기 식이 없어 못 넣음",
|
||||
Pick_Direct: "시간당 경비 식이 없는 기계 — 줄 쌓기에 못 넣음",
|
||||
To_Mine: "복사해 내 기계로",
|
||||
// 내 품목
|
||||
Items_Note:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* ⚠ 짝: `resources/master_data/scripts/master_machine_coef.py` — 같은 셈 · 같은 차례
|
||||
* (거울 시험 `resources/tester/test_821_2_machine_coef.py`). 한쪽만 고치면 화면과 저장이 갈림.
|
||||
* 계수 = 건설품셈 공통 8-1-5(계수마다 정수 반올림 · 손료계수 = 합) · 미리보기 끝수 = 서버
|
||||
* 기계경비식(줄 0.1 원 아래 버림 · 잡품 = 버린 주연료 × % · 비목 합 원 미만 버림) · 정본은 서버 식.
|
||||
* 기계경비식(줄 0.1 원 아래 버림 · 잡품 = 버린 (주연료 + 전력) × % · 비목 합 원 미만 버림) · 정본은 서버 식.
|
||||
* ========================================================================== */
|
||||
|
||||
export const MACHINE_INPUTS = [
|
||||
@@ -73,8 +73,8 @@ export function machineHourly(
|
||||
): MachineHourly {
|
||||
const loss = Math.floor((num(values["가격"]) * 1000 * num(values["손료계수"])) / 1e7 + E);
|
||||
const oil = tenth(num(values["주연료"]) * num(fuel));
|
||||
const misc = tenth((oil * num(values["잡재료율"])) / 100);
|
||||
const elec = tenth(num(values["전력"]) * num(power));
|
||||
const misc = tenth(((oil + elec) * num(values["잡재료율"])) / 100);
|
||||
const crew = tenth(num(values["조종원"]) * hour * num(wage));
|
||||
const labor = Math.floor(crew + E);
|
||||
const material = Math.floor(oil + misc + elec + E);
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1,310 @@
|
||||
"""기계 시간당 경비 식 완성(PLAN 822-2 · 요구 797 · 798 · 799) — 기계표 · 08장 로직 고침(정본 저장 길).
|
||||
|
||||
한 번만 돎(두 번째는 바뀐 것 없음):
|
||||
기계.json
|
||||
· 주연료 칸에 ㎾ 글이 든 전동 기계 → 숫자 칸 `전력`(㎾ · 전동기 부하율 규정 없음 → 그대로) · 주연료 비움
|
||||
(원문 글은 `값원문` 그대로 · 비고에 한 줄) · 원문 잡재료 「-」 = 잡재료율 0
|
||||
· 조종원직종 13 대 = 사용자 확정(요구 799) · 아스팔트 믹싱플랜트 잡재료 「-」 = 0
|
||||
· EQ000534 이름 오자 「POWER TLOWEL」 → 「POWER TROWEL」(원문 8-4-8 표기 · `옛이름` 보존)
|
||||
로직_건설품셈_08장_건설기계.json
|
||||
· 새 식 넷 — 전력 기종 · 전력 + 조종원 · 손료계수 한 칸 연료 기종 · 시간당 값 직접
|
||||
· 손료만 식(GC000273) 목록에서 옮긴 기계 뺌 → 맞는 식 목록에 더함(보정 식 GC000274 는 그대로)
|
||||
저장 = `M01_MasterData_Store_Make.save`(검사 · 키 대장 · 줄 모양 그대로 · 개정확인).
|
||||
수식 문서는 뒤에 `build_수식문서_802_2.py` 로 다시.
|
||||
|
||||
venv python resources/master_data/scripts/build_기계시간당_822_2.py [--check]
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
from M01_MasterData import M01_MasterData_Store as store # noqa: E402
|
||||
from M01_MasterData import M01_MasterData_Store_Make as make # noqa: E402
|
||||
|
||||
MACHINE = "기계.json"
|
||||
LOGIC = "로직_건설품셈_08장_건설기계.json"
|
||||
JOB_SRC = "건설품셈 공통 8-1-3 5 · 건설노임 {}"
|
||||
JOBS = { # 요구 799 — (직종, 까닭)
|
||||
**{f"EQ00016{i}": ("1048", "건설기계관리법상 건설기계") for i in range(5, 10)},
|
||||
**{
|
||||
k: ("1048", "원문 8-1-3 5 표의 「쇄석기」")
|
||||
for k in ("EQ000249", "EQ000250", "EQ000251", "EQ000252")
|
||||
},
|
||||
"EQ000347": ("1048", "원문 8-1-3 5 표의 「천공기」"),
|
||||
"EQ000348": ("1048", "원문 8-1-3 5 표의 「천공기」"),
|
||||
"EQ000309": ("1050", "두 법에 없는 기계"),
|
||||
"EQ000433": ("1050", "두 법에 없는 기계"),
|
||||
}
|
||||
POWER = { # 주연료 칸 ㎾ 글 → 전력(원문 값 그대로)
|
||||
"EQ000345": 330, "EQ000347": 135, "EQ000348": 239, "EQ000426": 15.1, "EQ000427": 15.1,
|
||||
"EQ000529": 3.73, "EQ000530": 7.46, "EQ000531": 37, "EQ000533": 1.49, "EQ000532": 1.87,
|
||||
} # fmt: skip
|
||||
MISC_DASH = ("EQ000426", "EQ000427", "EQ000529", "EQ000530", "EQ000531", "EQ000533",
|
||||
*(f"EQ0001{n}" for n in range(87, 92))) # fmt: skip
|
||||
TYPO = ("EQ000534", "POWER TLOWEL", "POWER TROWEL")
|
||||
|
||||
P1, P2, N3, DIRECT = "전력", "전력조종원", "손료한칸연료", "직접"
|
||||
MOVE = { # 식 → 더할 원문번호(손료만 식 GC000273 에서는 뺌)
|
||||
"GC000276": ["2208-5008", "2208-5010", "2208-5012", "2208-5016", "2208-5020", "5105-0050",
|
||||
"5105-0100", "5105-0150", "5105-0200", "5119-0625", "7205-0125"],
|
||||
"GC000268": ["3108-0060", "3108-0080", "3108-0100", "3108-0120", "9010-0120",
|
||||
"9010-0200"],
|
||||
P1: ["7991-0050", "7202-0008", "7202-0010", "7991-0100", "7991-0500",
|
||||
"7992-0001", "7993-0020"],
|
||||
P2: ["5805-0002", "5805-0003"],
|
||||
N3: ["7994-0050"],
|
||||
} # fmt: skip
|
||||
LOSS_ONLY = "GC000273"
|
||||
#: 손료만 식에서 빼기만 — 주연료 「73.7+ 휘발유54.5」 를 풀지 않음(꼴로 고름 → 까닭 글)
|
||||
DROP_ONLY = ["3450-0642"]
|
||||
#: 목록 밖(꼴로 고름 → 값 모자람 까닭 글) — 가격 없는 기계를 목록에 두면 식 기본 · 옵션 대조가 갈림(802-2):
|
||||
#: 아스팔트 스프레어 둘(가격 · 손료 없음 → 직종 입력 식 꼴) · TBM 4.5m(가격 없음 → 전력 식 꼴)
|
||||
#: 3108-0040 = 주연료 중유 — 유가 표에 중유 없음(검사가 막음) → 목록 밖 · 꼴로 고름 → 까닭 글
|
||||
LABEL = {P1: "전력", P2: "전력 조종원", N3: "손료계수 한 칸", DIRECT: "직접 값"}
|
||||
|
||||
_HEAD = {
|
||||
"원문번호": "8",
|
||||
"구분": "건설품셈 공통",
|
||||
"상세구분": "08장 건설기계",
|
||||
"결과단위": "원/시간",
|
||||
}
|
||||
_SRC = "건설품셈 공통 8-1-5 · 8-1-6"
|
||||
_LOSS_ONE = {
|
||||
"이름": "손료",
|
||||
"식": "버림(EQ:{기계}.가격 * 1000 * EQ:{기계}.손료계수 / 10000000, 0)",
|
||||
"출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4",
|
||||
}
|
||||
_HOUR = {
|
||||
"이름": "시간환산",
|
||||
"식": "찾기(CC000336, 구분='시간환산').분자 / 찾기(CC000336, 구분='시간환산').분모",
|
||||
"출처": "건설품셈 공통 1-1-3 2(일일 작업시간 8시간)",
|
||||
}
|
||||
_JOB = {"이름": "직종", "식": "EQ:{기계}.조종원직종", "출처": "건설품셈 공통 8-1-3 5"}
|
||||
_CREW = {
|
||||
"종류": "인력",
|
||||
"요소": "LB:{직종}",
|
||||
"이름": "조종원",
|
||||
"단위": "인",
|
||||
"수량": "EQ:{기계}.조종원 * 시간환산",
|
||||
"비목": "노무비",
|
||||
"출처": "건설품셈 공통 8-1-3 6",
|
||||
"비고": "하루 노임 × 1/8(1일 8시간 · 건설품셈 공통 1-1-3 2)",
|
||||
}
|
||||
_ELEC_IN = {
|
||||
"이름": "전력 계약종별",
|
||||
"고르기": ["일반용(갑)Ⅰ 저압", "주택용 저압"],
|
||||
"출처": "유가전력 한전 전기요금표 2025-01-01",
|
||||
"비고": "품셈·계약예규에 계약종별 규정 없음(전력비는 실비 계상) — 기본 = 불러오기 기본값",
|
||||
}
|
||||
_ELEC = {
|
||||
"종류": "재료",
|
||||
"요소": {"이름": "전력량요금", "계약종별": "입력"},
|
||||
"이름": "전력",
|
||||
"단위": "㎾h",
|
||||
"수량": "EQ:{기계}.전력",
|
||||
"비목": "재료비",
|
||||
"출처": "건설품셈 공통 8-1-6 3 가",
|
||||
"비고": "기계 줄 전력(㎾) 그대로 — 전동기 부하율 규정 없음",
|
||||
}
|
||||
_FUEL = {"이름": "연료", "식": "EQ:{기계}.주연료종류", "출처": "건설품셈 공통 8-4 주①㉰"}
|
||||
_FUEL_LINE = {
|
||||
"종류": "재료",
|
||||
"요소": "MO:{연료}:{지역}",
|
||||
"이름": "주연료",
|
||||
"단위": "ℓ",
|
||||
"수량": "EQ:{기계}.주연료",
|
||||
"비목": "재료비",
|
||||
"출처": "건설품셈 공통 8-4-8",
|
||||
}
|
||||
_REGION = {"이름": "지역", "고르기": None, "출처": "건설품셈 공통 8-1-7 5"}
|
||||
_MISC = {
|
||||
"이름": "잡재료비",
|
||||
"식": "재료비 * EQ:{기계}.잡재료율 / 100",
|
||||
"비목": "재료비",
|
||||
"출처": "건설품셈 공통 8-4 주②",
|
||||
}
|
||||
_LOSS_ADD = {"이름": "기계손료", "식": "손료", "비목": "경비", "출처": "건설품셈 공통 8-1-6 2"}
|
||||
_CUT = "손료 원 미만 버림(건설품셈 공통 8-1-5 12) · 합계 원문 규정 없음"
|
||||
_S = {"기호": "S"}
|
||||
|
||||
|
||||
def _vars(*names: str) -> dict:
|
||||
sign = {"손료": "C", "시간환산": "Q"}
|
||||
return {
|
||||
n: {"기호": sign.get(n, "S"), "아래": n.replace("전력 계약종별", "전력계약종별")}
|
||||
for n in names
|
||||
}
|
||||
|
||||
|
||||
def _machine_in(codes: list[str]) -> dict:
|
||||
return {"이름": "기계", "고르기": codes}
|
||||
|
||||
|
||||
def new_rows(regions: list) -> dict[str, dict]:
|
||||
"""새 식 넷(키 없음 — 저장이 대장 다음 번호)."""
|
||||
region = {**_REGION, "고르기": regions}
|
||||
return {
|
||||
P1: {
|
||||
**_HEAD,
|
||||
"이름": "기계 시간당 기계경비(전력 기종)",
|
||||
"출처": f"{_SRC} · 8-1-6 3 가",
|
||||
"부품": {"갈래": "기계경비식"},
|
||||
"소유": "공용",
|
||||
"비고": "원문 운전경비 표 주연료 칸에 ㎾ 가 찍힌 전동 기종 — 전력비 = 전력(㎾) × 전력량요금 · 잡재료 = 전력비의 %(8-4 주②)",
|
||||
"입력": [_machine_in(MOVE[P1]), _ELEC_IN],
|
||||
"중간": [_LOSS_ONE],
|
||||
"호표": [_ELEC],
|
||||
"덧줄": [_MISC, _LOSS_ADD],
|
||||
"끝수": _CUT,
|
||||
"변수표": _vars("기계", "전력 계약종별", "손료"),
|
||||
},
|
||||
P2: {
|
||||
**_HEAD,
|
||||
"이름": "기계 시간당 기계경비(전력 · 조종원 기종)",
|
||||
"출처": f"{_SRC} · 8-1-6 3 가",
|
||||
"부품": {"갈래": "기계경비식"},
|
||||
"소유": "공용",
|
||||
"비고": "원문 운전경비 표 주연료 칸에 ㎾ 가 찍히고 조종원이 있는 전동 기종(점보드릴) — 전력비 + 잡재료(전력비의 %) + 조종원",
|
||||
"입력": [_machine_in(MOVE[P2]), _ELEC_IN],
|
||||
"중간": [_LOSS_ONE, _JOB, _HOUR],
|
||||
"호표": [_ELEC, _CREW],
|
||||
"덧줄": [_MISC, _LOSS_ADD],
|
||||
"끝수": _CUT,
|
||||
"변수표": _vars("기계", "전력 계약종별", "손료", "직종", "시간환산"),
|
||||
},
|
||||
N3: {
|
||||
**_HEAD,
|
||||
"이름": "기계 시간당 기계경비(조종원 없는 기종 · 손료계수 한 칸)",
|
||||
"출처": _SRC,
|
||||
"부품": {"갈래": "기계경비식"},
|
||||
"소유": "공용",
|
||||
"비고": "원문 손료 표가 시간당 손료계수 하나만 준 기종(8-3-8 기타기계 등) 가운데 주연료가 있고 조종원이 없는 것",
|
||||
"입력": [_machine_in(MOVE[N3]), region],
|
||||
"중간": [_LOSS_ONE, _FUEL],
|
||||
"호표": [_FUEL_LINE],
|
||||
"덧줄": [_MISC, _LOSS_ADD],
|
||||
"끝수": _CUT,
|
||||
"변수표": _vars("기계", "지역", "손료", "연료"),
|
||||
},
|
||||
DIRECT: {
|
||||
**_HEAD,
|
||||
"이름": "기계 시간당 기계경비(직접 값)",
|
||||
"출처": "자체",
|
||||
"부품": {"갈래": "기계경비식"},
|
||||
"소유": "공용",
|
||||
"비고": "자체 — 구성 없는 기계 · 구성(손료 · 연료 · 조종원) 없이 시간당 노무비 · 재료비 · 경비를 바로 둔 기계(내 기계 「시간당 값 직접」) — 기계 줄 값 그대로",
|
||||
"입력": [{"이름": "기계", "고르기": []}],
|
||||
"중간": [],
|
||||
"호표": [],
|
||||
"덧줄": [
|
||||
{
|
||||
"이름": "시간당 노무비",
|
||||
"식": "EQ:{기계}.노무비",
|
||||
"비목": "노무비",
|
||||
"출처": "자체",
|
||||
},
|
||||
{
|
||||
"이름": "시간당 재료비",
|
||||
"식": "EQ:{기계}.재료비",
|
||||
"비목": "재료비",
|
||||
"출처": "자체",
|
||||
},
|
||||
{"이름": "시간당 경비", "식": "EQ:{기계}.경비", "비목": "경비", "출처": "자체"},
|
||||
], # fmt: skip
|
||||
"끝수": None,
|
||||
"변수표": _vars("기계"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _note(row: dict, text: str) -> None:
|
||||
was = str(row.get("비고") or "")
|
||||
if text not in was:
|
||||
row["비고"] = f"{was} · {text}" if was else text
|
||||
|
||||
|
||||
def machine_changes() -> list[dict]:
|
||||
rows = {r["키"]: r for r in store.read(MACHINE)[0]["줄"]}
|
||||
out = []
|
||||
for key, row in rows.items():
|
||||
new = copy.deepcopy(row)
|
||||
vals, unit, src = new["값"], new.setdefault("단위", {}), new.setdefault("출처", {})
|
||||
if key in POWER and vals.get("전력") is None:
|
||||
text = str(vals.get("주연료"))
|
||||
text += "㎾" if unit.get("주연료") == "㎾" else "" # 모르타르 믹서 = 단위 칸에 ㎾
|
||||
got = re.search(r"([\d.]+)\s*㎾", text)
|
||||
assert got and float(got.group(1)) == POWER[key], (key, text)
|
||||
vals["주연료"], vals["전력"] = None, POWER[key]
|
||||
unit["주연료"], unit["전력"] = "ℓ/hr", "kWh/hr"
|
||||
src["전력"] = src.get("주연료")
|
||||
_note(new, f"전력 = 원문 주연료 칸 「{text}」(㎾ · 전동기 부하율 규정 없음 → 그대로)")
|
||||
if key == "EQ000532":
|
||||
_note(new, "원문 「휘발유1.3」 갈래는 주연료2 칸 · 시간당 식은 전력")
|
||||
if key in MISC_DASH and vals.get("잡재료율") is None:
|
||||
vals["잡재료율"] = 0
|
||||
_note(new, "잡재료율 0 = 원문 잡재료 「-」")
|
||||
if key in JOBS and not vals.get("조종원직종"):
|
||||
job, why = JOBS[key]
|
||||
vals["조종원직종"] = job
|
||||
src["조종원직종"] = JOB_SRC.format(job)
|
||||
_note(new, f"직종 = 사용자 확정(요구 799) — {why}")
|
||||
if key == TYPO[0] and new.get("이름") == TYPO[1]:
|
||||
items = list(new.items())
|
||||
at = [k for k, _ in items].index("이름") + 1
|
||||
items.insert(at, ("옛이름", TYPO[1]))
|
||||
new = dict(items)
|
||||
new["이름"] = TYPO[2]
|
||||
if new.get("상세구분") == TYPO[1]:
|
||||
new["상세구분"] = TYPO[2]
|
||||
if new != row:
|
||||
out.append({"op": "edit", "key": key, "row": new})
|
||||
return out
|
||||
|
||||
|
||||
def logic_changes() -> list[dict]:
|
||||
data = store.read(LOGIC)[0]
|
||||
rows = {r["키"]: r for r in data["줄"]}
|
||||
if any(r.get("이름") == "기계 시간당 기계경비(직접 값)" for r in rows.values()):
|
||||
return []
|
||||
moved = {c for codes in MOVE.values() for c in codes} | set(DROP_ONLY)
|
||||
out = []
|
||||
for key in (LOSS_ONLY, *[k for k in MOVE if k.startswith("GC")]):
|
||||
new = copy.deepcopy(rows[key])
|
||||
pick = next(i for i in new["입력"] if i.get("이름") == "기계")
|
||||
if key == LOSS_ONLY:
|
||||
pick["고르기"] = [c for c in pick["고르기"] if str(c) not in moved]
|
||||
else:
|
||||
pick["고르기"] += [c for c in MOVE[key] if c not in pick["고르기"]]
|
||||
out.append({"op": "edit", "key": key, "row": new})
|
||||
regions = next(i["고르기"] for i in rows["GC000268"]["입력"] if i["이름"] == "지역")
|
||||
out += [{"op": "add", "row": row} for row in new_rows(regions).values()]
|
||||
return out
|
||||
|
||||
|
||||
def main(check: bool) -> None:
|
||||
parts = []
|
||||
for file, changes in ((MACHINE, machine_changes()), (LOGIC, logic_changes())):
|
||||
print(file, len(changes), [c.get("key") or c["row"]["이름"] for c in changes])
|
||||
if changes:
|
||||
parts.append({"file": file, "version": store.read(file)[1], "changes": changes})
|
||||
if check or not parts:
|
||||
return
|
||||
# 대장 열쇠 = 원문번호 — 넷 다 「8」 이면 한 키로 겹침 → 옛 기계경비식처럼 이름 붙은 열쇠(줄은 「8」)
|
||||
labels = {r["이름"]: f"공통 8 기계 시간당 경비({LABEL[t]})" for t, r in new_rows([]).items()}
|
||||
plain = store.ledger_label
|
||||
store.ledger_label = lambda book, tid, no, row: (
|
||||
labels.get(row.get("이름")) or plain(book, tid, no, row)
|
||||
)
|
||||
got = make.save(parts, confirmed=True)
|
||||
print("저장", got["added"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main("--check" in sys.argv)
|
||||
@@ -10,7 +10,8 @@
|
||||
계수마다 정수로 반올림 · 손료계수 = 셋의 합.
|
||||
미리보기 = 서버 기계경비식(GC000267 ~)을 기본 옵션(보정 없음)으로 부른 값과 같은 끝수 —
|
||||
손료 = 가격(천원) × 1000 × 손료계수 ÷ 10^7 원 미만 버림 · 줄 금액은 0.1 원 아래 버림 ·
|
||||
잡품 = 버린 주연료 금액 × 잡재료율 % · 비목 합은 원 미만 버림(B09 끝수 `master_cut.engine`).
|
||||
잡품 = 버린 (주연료 + 전력) 금액 × 잡재료율 %(전력 기종 = 전력비의 % · 822-2 GC001196 · 7) ·
|
||||
비목 합은 원 미만 버림(B09 끝수 `master_cut.engine`).
|
||||
정본은 서버 식(`M02_Machine_Hourly`) — 이것은 화면 즉시 셈용.
|
||||
"""
|
||||
|
||||
@@ -61,8 +62,8 @@ def preview(
|
||||
"""값 묶음 + 유가(원/ℓ) · 노임(원/일) · 전력(원/kWh) · 시간환산 → 시간당 줄 · 비목 · 계."""
|
||||
loss = math.floor(_num(values.get("가격")) * 1000 * _num(values.get("손료계수")) / 1e7 + _E)
|
||||
oil = _tenth(_num(values.get("주연료")) * _num(fuel))
|
||||
misc = _tenth(oil * _num(values.get("잡재료율")) / 100)
|
||||
elec = _tenth(_num(values.get("전력")) * _num(power))
|
||||
misc = _tenth((oil + elec) * _num(values.get("잡재료율")) / 100)
|
||||
crew = _tenth(_num(values.get("조종원")) * hour * _num(wage))
|
||||
labor, material = math.floor(crew + _E), math.floor(oil + misc + elec + _E)
|
||||
return {
|
||||
|
||||
+146
-127
@@ -10907,7 +10907,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-3",
|
||||
@@ -10924,9 +10924,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-3",
|
||||
"잡재료율": "건설품셈 공통 8-4-3",
|
||||
"조종원": "건설품셈 공통 8-4-3",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (m×ton)"
|
||||
"비고": "규격 단위: (m×ton) · 직종 = 사용자 확정(요구 799) — 건설기계관리법상 건설기계"
|
||||
},
|
||||
{
|
||||
"키": "EQ000166",
|
||||
@@ -10968,7 +10968,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-3",
|
||||
@@ -10985,9 +10985,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-3",
|
||||
"잡재료율": "건설품셈 공통 8-4-3",
|
||||
"조종원": "건설품셈 공통 8-4-3",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (m×ton)"
|
||||
"비고": "규격 단위: (m×ton) · 직종 = 사용자 확정(요구 799) — 건설기계관리법상 건설기계"
|
||||
},
|
||||
{
|
||||
"키": "EQ000167",
|
||||
@@ -11029,7 +11029,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-3",
|
||||
@@ -11046,9 +11046,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-3",
|
||||
"잡재료율": "건설품셈 공통 8-4-3",
|
||||
"조종원": "건설품셈 공통 8-4-3",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (m×ton)"
|
||||
"비고": "규격 단위: (m×ton) · 직종 = 사용자 확정(요구 799) — 건설기계관리법상 건설기계"
|
||||
},
|
||||
{
|
||||
"키": "EQ000168",
|
||||
@@ -11090,7 +11090,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-3",
|
||||
@@ -11107,9 +11107,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-3",
|
||||
"잡재료율": "건설품셈 공통 8-4-3",
|
||||
"조종원": "건설품셈 공통 8-4-3",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (m×ton)"
|
||||
"비고": "규격 단위: (m×ton) · 직종 = 사용자 확정(요구 799) — 건설기계관리법상 건설기계"
|
||||
},
|
||||
{
|
||||
"키": "EQ000169",
|
||||
@@ -11151,7 +11151,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-3",
|
||||
@@ -11168,9 +11168,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-3",
|
||||
"잡재료율": "건설품셈 공통 8-4-3",
|
||||
"조종원": "건설품셈 공통 8-4-3",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (m×ton)"
|
||||
"비고": "규격 단위: (m×ton) · 직종 = 사용자 확정(요구 799) — 건설기계관리법상 건설기계"
|
||||
},
|
||||
{
|
||||
"키": "EQ000170",
|
||||
@@ -12251,7 +12251,7 @@
|
||||
"손료계수": 2501,
|
||||
"주연료": 487.2,
|
||||
"주연료종류": "중유",
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": 2,
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
@@ -12272,10 +12272,8 @@
|
||||
"조종원": "건설품셈 공통 8-4-4",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름",
|
||||
"값원문": {
|
||||
"8-4-4 주연료": "중유487.2"
|
||||
}
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름 · 잡재료율 0 = 원문 잡재료 「-」",
|
||||
"값원문": { "8-4-4 주연료": "중유487.2" }
|
||||
},
|
||||
{
|
||||
"키": "EQ000188",
|
||||
@@ -12315,7 +12313,7 @@
|
||||
"손료계수": 2159,
|
||||
"주연료": 614.7,
|
||||
"주연료종류": "경유",
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": 2,
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
@@ -12336,7 +12334,7 @@
|
||||
"조종원": "건설품셈 공통 8-4-4",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름"
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름 · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000189",
|
||||
@@ -12376,7 +12374,7 @@
|
||||
"손료계수": 2159,
|
||||
"주연료": 678.4,
|
||||
"주연료종류": "경유",
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": 2,
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
@@ -12397,7 +12395,7 @@
|
||||
"조종원": "건설품셈 공통 8-4-4",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름"
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름 · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000190",
|
||||
@@ -12437,7 +12435,7 @@
|
||||
"손료계수": 2159,
|
||||
"주연료": 746.7,
|
||||
"주연료종류": "경유",
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": 2,
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
@@ -12458,7 +12456,7 @@
|
||||
"조종원": "건설품셈 공통 8-4-4",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름"
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름 · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000191",
|
||||
@@ -12498,7 +12496,7 @@
|
||||
"손료계수": 2159,
|
||||
"주연료": 819.6,
|
||||
"주연료종류": "경유",
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": 2,
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
@@ -12519,7 +12517,7 @@
|
||||
"조종원": "건설품셈 공통 8-4-4",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름"
|
||||
"비고": "조종원직종 원문 이름: 건설기계운전사 · 규격 단위: (ton/hr) · 주연료종류: 원문 글을 가름 · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000192",
|
||||
@@ -16081,7 +16079,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-6",
|
||||
@@ -16098,9 +16096,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (ton/hr)(㎾)"
|
||||
"비고": "규격 단위: (ton/hr)(㎾) · 직종 = 사용자 확정(요구 799) — 원문 8-1-3 5 표의 「쇄석기」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000250",
|
||||
@@ -16142,7 +16140,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-6",
|
||||
@@ -16159,9 +16157,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (ton/hr)(㎾)"
|
||||
"비고": "규격 단위: (ton/hr)(㎾) · 직종 = 사용자 확정(요구 799) — 원문 8-1-3 5 표의 「쇄석기」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000251",
|
||||
@@ -16203,7 +16201,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-6",
|
||||
@@ -16220,9 +16218,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (ton/hr)(㎾)"
|
||||
"비고": "규격 단위: (ton/hr)(㎾) · 직종 = 사용자 확정(요구 799) — 원문 8-1-3 5 표의 「쇄석기」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000252",
|
||||
@@ -16264,7 +16262,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-6",
|
||||
@@ -16281,9 +16279,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048"
|
||||
},
|
||||
"비고": "규격 단위: (ton/hr)(㎾)"
|
||||
"비고": "규격 단위: (ton/hr)(㎾) · 직종 = 사용자 확정(요구 799) — 원문 8-1-3 5 표의 「쇄석기」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000253",
|
||||
@@ -19689,7 +19687,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1050"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-6",
|
||||
@@ -19706,8 +19704,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
}
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1050"
|
||||
},
|
||||
"비고": "직종 = 사용자 확정(요구 799) — 두 법에 없는 기계"
|
||||
},
|
||||
{
|
||||
"키": "EQ000310",
|
||||
@@ -21858,7 +21857,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": null,
|
||||
@@ -21871,11 +21871,12 @@
|
||||
"정비비계수": 167,
|
||||
"관리비계수": 328,
|
||||
"손료계수": 870,
|
||||
"주연료": "동력330㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": 10,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 330
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5",
|
||||
@@ -21892,11 +21893,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-6"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-6 주연료": "동력330㎾"
|
||||
}
|
||||
"값원문": { "8-4-6 주연료": "동력330㎾" },
|
||||
"비고": "전력 = 원문 주연료 칸 「동력330㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로)"
|
||||
},
|
||||
{
|
||||
"키": "EQ000346",
|
||||
@@ -21981,7 +21982,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 605472,
|
||||
@@ -21994,11 +21996,12 @@
|
||||
"정비비계수": 777,
|
||||
"관리비계수": 738,
|
||||
"손료계수": 2515,
|
||||
"주연료": "135㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": 6,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048",
|
||||
"전력": 135
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-6",
|
||||
@@ -22015,11 +22018,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048",
|
||||
"전력": "건설품셈 공통 8-4-6"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-6 주연료": "135㎾"
|
||||
}
|
||||
"값원문": { "8-4-6 주연료": "135㎾" },
|
||||
"비고": "전력 = 원문 주연료 칸 「135㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 직종 = 사용자 확정(요구 799) — 원문 8-1-3 5 표의 「천공기」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000348",
|
||||
@@ -22044,7 +22047,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 1153045,
|
||||
@@ -22057,11 +22061,12 @@
|
||||
"정비비계수": 777,
|
||||
"관리비계수": 738,
|
||||
"손료계수": 2515,
|
||||
"주연료": "239㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": 10,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1048",
|
||||
"전력": 239
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-6",
|
||||
@@ -22078,11 +22083,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-6",
|
||||
"잡재료율": "건설품셈 공통 8-4-6",
|
||||
"조종원": "건설품셈 공통 8-4-6",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1048",
|
||||
"전력": "건설품셈 공통 8-4-6"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-6 주연료": "239㎾"
|
||||
}
|
||||
"값원문": { "8-4-6 주연료": "239㎾" },
|
||||
"비고": "전력 = 원문 주연료 칸 「239㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 직종 = 사용자 확정(요구 799) — 원문 8-1-3 5 표의 「천공기」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000349",
|
||||
@@ -26768,7 +26773,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 16828,
|
||||
@@ -26781,11 +26787,12 @@
|
||||
"정비비계수": 2333,
|
||||
"관리비계수": 1169,
|
||||
"손료계수": 6502,
|
||||
"주연료": "동력 15.1㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 15.1
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -26802,12 +26809,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-8"
|
||||
},
|
||||
"비고": "규격 단위: (W×L×H)",
|
||||
"값원문": {
|
||||
"8-4-8 주연료": "동력 15.1㎾"
|
||||
}
|
||||
"비고": "규격 단위: (W×L×H) · 전력 = 원문 주연료 칸 「동력 15.1㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 잡재료율 0 = 원문 잡재료 「-」",
|
||||
"값원문": { "8-4-8 주연료": "동력 15.1㎾" }
|
||||
},
|
||||
{
|
||||
"키": "EQ000427",
|
||||
@@ -26832,7 +26838,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 21722,
|
||||
@@ -26845,11 +26852,12 @@
|
||||
"정비비계수": 2333,
|
||||
"관리비계수": 1169,
|
||||
"손료계수": 6502,
|
||||
"주연료": "동력 15.1㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 15.1
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -26866,12 +26874,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-8"
|
||||
},
|
||||
"비고": "규격 단위: (W×L×H)",
|
||||
"값원문": {
|
||||
"8-4-8 주연료": "동력 15.1㎾"
|
||||
}
|
||||
"비고": "규격 단위: (W×L×H) · 전력 = 원문 주연료 칸 「동력 15.1㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 잡재료율 0 = 원문 잡재료 「-」",
|
||||
"값원문": { "8-4-8 주연료": "동력 15.1㎾" }
|
||||
},
|
||||
{
|
||||
"키": "EQ000428",
|
||||
@@ -27218,7 +27225,7 @@
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"조종원": 1,
|
||||
"조종원직종": null
|
||||
"조종원직종": "1050"
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -27235,8 +27242,9 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
}
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5 · 건설노임 1050"
|
||||
},
|
||||
"비고": "직종 = 사용자 확정(요구 799) — 두 법에 없는 기계"
|
||||
},
|
||||
{
|
||||
"키": "EQ000434",
|
||||
@@ -33047,7 +33055,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 16913,
|
||||
@@ -33060,11 +33069,12 @@
|
||||
"정비비계수": null,
|
||||
"관리비계수": null,
|
||||
"손료계수": 4677,
|
||||
"주연료": "3.73㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 3.73
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -33081,11 +33091,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-8"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-8 주연료": "3.73㎾"
|
||||
}
|
||||
"값원문": { "8-4-8 주연료": "3.73㎾" },
|
||||
"비고": "전력 = 원문 주연료 칸 「3.73㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000530",
|
||||
@@ -33110,7 +33120,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 21887,
|
||||
@@ -33123,11 +33134,12 @@
|
||||
"정비비계수": null,
|
||||
"관리비계수": null,
|
||||
"손료계수": 4677,
|
||||
"주연료": "7.46㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 7.46
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -33144,11 +33156,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-8"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-8 주연료": "7.46㎾"
|
||||
}
|
||||
"값원문": { "8-4-8 주연료": "7.46㎾" },
|
||||
"비고": "전력 = 원문 주연료 칸 「7.46㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000531",
|
||||
@@ -33173,7 +33185,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 40769,
|
||||
@@ -33186,11 +33199,12 @@
|
||||
"정비비계수": null,
|
||||
"관리비계수": null,
|
||||
"손료계수": 4677,
|
||||
"주연료": "37㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 37
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -33207,11 +33221,11 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-8"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-8 주연료": "37㎾"
|
||||
}
|
||||
"값원문": { "8-4-8 주연료": "37㎾" },
|
||||
"비고": "전력 = 원문 주연료 칸 「37㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000532",
|
||||
@@ -33232,13 +33246,14 @@
|
||||
"정비비계수": "10^-7/시간",
|
||||
"관리비계수": "10^-7/시간",
|
||||
"손료계수": "10^-7/시간",
|
||||
"주연료": "㎾",
|
||||
"주연료": "ℓ/hr",
|
||||
"주연료종류": "",
|
||||
"주연료2": "ℓ/hr",
|
||||
"주연료2종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 5696,
|
||||
@@ -33251,13 +33266,14 @@
|
||||
"정비비계수": null,
|
||||
"관리비계수": null,
|
||||
"손료계수": 3708,
|
||||
"주연료": 1.87,
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"주연료2": 1.3,
|
||||
"주연료2종류": "휘발유",
|
||||
"잡재료율": 2,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 1.87
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -33276,11 +33292,11 @@
|
||||
"주연료2종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-8"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-8 주연료": "1.87㎾ 휘발유1.3"
|
||||
}
|
||||
"값원문": { "8-4-8 주연료": "1.87㎾ 휘발유1.3" },
|
||||
"비고": "전력 = 원문 주연료 칸 「1.87㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 원문 「휘발유1.3」 갈래는 주연료2 칸 · 시간당 식은 전력"
|
||||
},
|
||||
{
|
||||
"키": "EQ000533",
|
||||
@@ -33305,7 +33321,8 @@
|
||||
"주연료종류": "",
|
||||
"잡재료율": "주연료의 %",
|
||||
"조종원": "인/일",
|
||||
"조종원직종": ""
|
||||
"조종원직종": "",
|
||||
"전력": "kWh/hr"
|
||||
},
|
||||
"값": {
|
||||
"가격": 38,
|
||||
@@ -33318,11 +33335,12 @@
|
||||
"정비비계수": null,
|
||||
"관리비계수": null,
|
||||
"손료계수": 3375,
|
||||
"주연료": "1.49㎾",
|
||||
"주연료": null,
|
||||
"주연료종류": null,
|
||||
"잡재료율": null,
|
||||
"잡재료율": 0,
|
||||
"조종원": null,
|
||||
"조종원직종": null
|
||||
"조종원직종": null,
|
||||
"전력": 1.49
|
||||
},
|
||||
"출처": {
|
||||
"가격": "건설품셈 공통 8-5-8",
|
||||
@@ -33339,19 +33357,20 @@
|
||||
"주연료종류": "건설품셈 공통 8-4-8",
|
||||
"잡재료율": "건설품셈 공통 8-4-8",
|
||||
"조종원": "건설품셈 공통 8-4-8",
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5"
|
||||
"조종원직종": "건설품셈 공통 8-1-3 5",
|
||||
"전력": "건설품셈 공통 8-4-8"
|
||||
},
|
||||
"값원문": {
|
||||
"8-4-8 주연료": "1.49㎾"
|
||||
}
|
||||
"값원문": { "8-4-8 주연료": "1.49㎾" },
|
||||
"비고": "전력 = 원문 주연료 칸 「1.49㎾」(㎾ · 전동기 부하율 규정 없음 → 그대로) · 잡재료율 0 = 원문 잡재료 「-」"
|
||||
},
|
||||
{
|
||||
"키": "EQ000534",
|
||||
"원문번호": "7994-0050",
|
||||
"원문": "건설품셈",
|
||||
"구분": "[70]기타기계",
|
||||
"상세구분": "POWER TLOWEL",
|
||||
"이름": "POWER TLOWEL",
|
||||
"상세구분": "POWER TROWEL",
|
||||
"이름": "POWER TROWEL",
|
||||
"옛이름": "POWER TLOWEL",
|
||||
"규격": "3.73㎾",
|
||||
"단위": {
|
||||
"가격": "천원",
|
||||
|
||||
@@ -284,7 +284,13 @@
|
||||
"9090-1300",
|
||||
"9090-1400",
|
||||
"9090-1500",
|
||||
"9090-1600"
|
||||
"9090-1600",
|
||||
"3108-0060",
|
||||
"3108-0080",
|
||||
"3108-0100",
|
||||
"3108-0120",
|
||||
"9010-0120",
|
||||
"9010-0200"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -853,11 +859,6 @@
|
||||
"2104-0220",
|
||||
"2104-0250",
|
||||
"2104-0300",
|
||||
"2208-5008",
|
||||
"2208-5010",
|
||||
"2208-5012",
|
||||
"2208-5016",
|
||||
"2208-5020",
|
||||
"2105-0002",
|
||||
"2105-0003",
|
||||
"2105-0005",
|
||||
@@ -921,7 +922,6 @@
|
||||
"2118-0010",
|
||||
"2210-0145",
|
||||
"3430-0300",
|
||||
"3450-0642",
|
||||
"4115-0100",
|
||||
"4115-0150",
|
||||
"4115-0200",
|
||||
@@ -929,10 +929,6 @@
|
||||
"4505-0015",
|
||||
"4505-0026",
|
||||
"4611-0075",
|
||||
"5105-0050",
|
||||
"5105-0100",
|
||||
"5105-0150",
|
||||
"5105-0200",
|
||||
"5111-0040",
|
||||
"5111-0050",
|
||||
"5111-0060",
|
||||
@@ -989,15 +985,12 @@
|
||||
"5118-0005",
|
||||
"5118-0006",
|
||||
"5118-0007",
|
||||
"5119-0625",
|
||||
"5203-1800",
|
||||
"5203-2200",
|
||||
"5203-2700",
|
||||
"5203-3500",
|
||||
"5203-4500",
|
||||
"5330-0074",
|
||||
"5805-0002",
|
||||
"5805-0003",
|
||||
"5901-0006",
|
||||
"5901-0010",
|
||||
"5901-0016",
|
||||
@@ -1018,9 +1011,6 @@
|
||||
"6550-0130",
|
||||
"7103-0010",
|
||||
"7104-0010",
|
||||
"7202-0008",
|
||||
"7202-0010",
|
||||
"7205-0125",
|
||||
"7206-0020",
|
||||
"7206-0070",
|
||||
"7206-0100",
|
||||
@@ -1058,10 +1048,6 @@
|
||||
"7930-0075",
|
||||
"7930-0100",
|
||||
"7935-0180",
|
||||
"7991-0050",
|
||||
"7991-0100",
|
||||
"7991-0500",
|
||||
"7993-0020",
|
||||
"8201-0100",
|
||||
"8202-0100",
|
||||
"8203-0019",
|
||||
@@ -1370,7 +1356,30 @@
|
||||
"소유": "공용",
|
||||
"비고": "원문 운전경비 표에 주연료가 빈 기종(공기식 크롤러드릴 등 — 동력은 공기압축기) — 손료 + 조종원",
|
||||
"입력": [
|
||||
{ "이름": "기계", "고르기": ["5401-0017", "4108-0060", "4108-0090", "4108-0120", "4108-0150", "4108-0180", "4108-0210", "5401-0015"] },
|
||||
{
|
||||
"이름": "기계",
|
||||
"고르기": [
|
||||
"5401-0017",
|
||||
"4108-0060",
|
||||
"4108-0090",
|
||||
"4108-0120",
|
||||
"4108-0150",
|
||||
"4108-0180",
|
||||
"4108-0210",
|
||||
"5401-0015",
|
||||
"2208-5008",
|
||||
"2208-5010",
|
||||
"2208-5012",
|
||||
"2208-5016",
|
||||
"2208-5020",
|
||||
"5105-0050",
|
||||
"5105-0100",
|
||||
"5105-0150",
|
||||
"5105-0200",
|
||||
"5119-0625",
|
||||
"7205-0125"
|
||||
]
|
||||
},
|
||||
{
|
||||
"이름": "지역",
|
||||
"고르기": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"],
|
||||
@@ -3456,6 +3465,140 @@
|
||||
"조건": { "기호": "S", "아래": "조건" },
|
||||
"유속": { "기호": "v", "아래": "유속" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"키": "GC001196",
|
||||
"원문번호": "8",
|
||||
"구분": "건설품셈 공통",
|
||||
"상세구분": "08장 건설기계",
|
||||
"결과단위": "원/시간",
|
||||
"이름": "기계 시간당 기계경비(전력 기종)",
|
||||
"출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가",
|
||||
"부품": { "갈래": "기계경비식" },
|
||||
"소유": "공용",
|
||||
"비고": "원문 운전경비 표 주연료 칸에 ㎾ 가 찍힌 전동 기종 — 전력비 = 전력(㎾) × 전력량요금 · 잡재료 = 전력비의 %(8-4 주②)",
|
||||
"입력": [
|
||||
{ "이름": "기계", "고르기": ["7991-0050", "7202-0008", "7202-0010", "7991-0100", "7991-0500", "7992-0001", "7993-0020"] },
|
||||
{ "이름": "전력 계약종별", "고르기": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "출처": "유가전력 한전 전기요금표 2025-01-01", "비고": "품셈·계약예규에 계약종별 규정 없음(전력비는 실비 계상) — 기본 = 불러오기 기본값" }
|
||||
],
|
||||
"중간": [{ "이름": "손료", "식": "버림(EQ:{기계}.가격 * 1000 * EQ:{기계}.손료계수 / 10000000, 0)", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4" }],
|
||||
"호표": [
|
||||
{
|
||||
"종류": "재료",
|
||||
"요소": { "이름": "전력량요금", "계약종별": "입력" },
|
||||
"이름": "전력",
|
||||
"단위": "㎾h",
|
||||
"수량": "EQ:{기계}.전력",
|
||||
"비목": "재료비",
|
||||
"출처": "건설품셈 공통 8-1-6 3 가",
|
||||
"비고": "기계 줄 전력(㎾) 그대로 — 전동기 부하율 규정 없음"
|
||||
}
|
||||
],
|
||||
"덧줄": [{ "이름": "잡재료비", "식": "재료비 * EQ:{기계}.잡재료율 / 100", "비목": "재료비", "출처": "건설품셈 공통 8-4 주②" }, { "이름": "기계손료", "식": "손료", "비목": "경비", "출처": "건설품셈 공통 8-1-6 2" }],
|
||||
"끝수": "손료 원 미만 버림(건설품셈 공통 8-1-5 12) · 합계 원문 규정 없음",
|
||||
"변수표": { "기계": { "기호": "S", "아래": "기계" }, "전력 계약종별": { "기호": "S", "아래": "전력계약종별" }, "손료": { "기호": "C", "아래": "손료" } }
|
||||
},
|
||||
{
|
||||
"키": "GC001197",
|
||||
"원문번호": "8",
|
||||
"구분": "건설품셈 공통",
|
||||
"상세구분": "08장 건설기계",
|
||||
"결과단위": "원/시간",
|
||||
"이름": "기계 시간당 기계경비(전력 · 조종원 기종)",
|
||||
"출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가",
|
||||
"부품": { "갈래": "기계경비식" },
|
||||
"소유": "공용",
|
||||
"비고": "원문 운전경비 표 주연료 칸에 ㎾ 가 찍히고 조종원이 있는 전동 기종(점보드릴) — 전력비 + 잡재료(전력비의 %) + 조종원",
|
||||
"입력": [
|
||||
{ "이름": "기계", "고르기": ["5805-0002", "5805-0003"] },
|
||||
{ "이름": "전력 계약종별", "고르기": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "출처": "유가전력 한전 전기요금표 2025-01-01", "비고": "품셈·계약예규에 계약종별 규정 없음(전력비는 실비 계상) — 기본 = 불러오기 기본값" }
|
||||
],
|
||||
"중간": [
|
||||
{ "이름": "손료", "식": "버림(EQ:{기계}.가격 * 1000 * EQ:{기계}.손료계수 / 10000000, 0)", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4" },
|
||||
{ "이름": "직종", "식": "EQ:{기계}.조종원직종", "출처": "건설품셈 공통 8-1-3 5" },
|
||||
{ "이름": "시간환산", "식": "찾기(CC000336, 구분='시간환산').분자 / 찾기(CC000336, 구분='시간환산').분모", "출처": "건설품셈 공통 1-1-3 2(일일 작업시간 8시간)" }
|
||||
],
|
||||
"호표": [
|
||||
{
|
||||
"종류": "재료",
|
||||
"요소": { "이름": "전력량요금", "계약종별": "입력" },
|
||||
"이름": "전력",
|
||||
"단위": "㎾h",
|
||||
"수량": "EQ:{기계}.전력",
|
||||
"비목": "재료비",
|
||||
"출처": "건설품셈 공통 8-1-6 3 가",
|
||||
"비고": "기계 줄 전력(㎾) 그대로 — 전동기 부하율 규정 없음"
|
||||
},
|
||||
{
|
||||
"종류": "인력",
|
||||
"요소": "LB:{직종}",
|
||||
"이름": "조종원",
|
||||
"단위": "인",
|
||||
"수량": "EQ:{기계}.조종원 * 시간환산",
|
||||
"비목": "노무비",
|
||||
"출처": "건설품셈 공통 8-1-3 6",
|
||||
"비고": "하루 노임 × 1/8(1일 8시간 · 건설품셈 공통 1-1-3 2)"
|
||||
}
|
||||
],
|
||||
"덧줄": [{ "이름": "잡재료비", "식": "재료비 * EQ:{기계}.잡재료율 / 100", "비목": "재료비", "출처": "건설품셈 공통 8-4 주②" }, { "이름": "기계손료", "식": "손료", "비목": "경비", "출처": "건설품셈 공통 8-1-6 2" }],
|
||||
"끝수": "손료 원 미만 버림(건설품셈 공통 8-1-5 12) · 합계 원문 규정 없음",
|
||||
"변수표": {
|
||||
"기계": { "기호": "S", "아래": "기계" },
|
||||
"전력 계약종별": { "기호": "S", "아래": "전력계약종별" },
|
||||
"손료": { "기호": "C", "아래": "손료" },
|
||||
"직종": { "기호": "S", "아래": "직종" },
|
||||
"시간환산": { "기호": "Q", "아래": "시간환산" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"키": "GC001198",
|
||||
"원문번호": "8",
|
||||
"구분": "건설품셈 공통",
|
||||
"상세구분": "08장 건설기계",
|
||||
"결과단위": "원/시간",
|
||||
"이름": "기계 시간당 기계경비(조종원 없는 기종 · 손료계수 한 칸)",
|
||||
"출처": "건설품셈 공통 8-1-5 · 8-1-6",
|
||||
"부품": { "갈래": "기계경비식" },
|
||||
"소유": "공용",
|
||||
"비고": "원문 손료 표가 시간당 손료계수 하나만 준 기종(8-3-8 기타기계 등) 가운데 주연료가 있고 조종원이 없는 것",
|
||||
"입력": [
|
||||
{ "이름": "기계", "고르기": ["7994-0050"] },
|
||||
{
|
||||
"이름": "지역",
|
||||
"고르기": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"],
|
||||
"출처": "건설품셈 공통 8-1-7 5"
|
||||
}
|
||||
],
|
||||
"중간": [
|
||||
{ "이름": "손료", "식": "버림(EQ:{기계}.가격 * 1000 * EQ:{기계}.손료계수 / 10000000, 0)", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4" },
|
||||
{ "이름": "연료", "식": "EQ:{기계}.주연료종류", "출처": "건설품셈 공통 8-4 주①㉰" }
|
||||
],
|
||||
"호표": [{ "종류": "재료", "요소": "MO:{연료}:{지역}", "이름": "주연료", "단위": "ℓ", "수량": "EQ:{기계}.주연료", "비목": "재료비", "출처": "건설품셈 공통 8-4-8" }],
|
||||
"덧줄": [{ "이름": "잡재료비", "식": "재료비 * EQ:{기계}.잡재료율 / 100", "비목": "재료비", "출처": "건설품셈 공통 8-4 주②" }, { "이름": "기계손료", "식": "손료", "비목": "경비", "출처": "건설품셈 공통 8-1-6 2" }],
|
||||
"끝수": "손료 원 미만 버림(건설품셈 공통 8-1-5 12) · 합계 원문 규정 없음",
|
||||
"변수표": { "기계": { "기호": "S", "아래": "기계" }, "지역": { "기호": "S", "아래": "지역" }, "손료": { "기호": "C", "아래": "손료" }, "연료": { "기호": "S", "아래": "연료" } }
|
||||
},
|
||||
{
|
||||
"키": "GC001199",
|
||||
"원문번호": "8",
|
||||
"구분": "건설품셈 공통",
|
||||
"상세구분": "08장 건설기계",
|
||||
"결과단위": "원/시간",
|
||||
"이름": "기계 시간당 기계경비(직접 값)",
|
||||
"출처": "자체",
|
||||
"부품": { "갈래": "기계경비식" },
|
||||
"소유": "공용",
|
||||
"비고": "자체 — 구성 없는 기계 · 구성(손료 · 연료 · 조종원) 없이 시간당 노무비 · 재료비 · 경비를 바로 둔 기계(내 기계 「시간당 값 직접」) — 기계 줄 값 그대로",
|
||||
"입력": [{ "이름": "기계", "고르기": [] }],
|
||||
"중간": [],
|
||||
"호표": [],
|
||||
"덧줄": [
|
||||
{ "이름": "시간당 노무비", "식": "EQ:{기계}.노무비", "비목": "노무비", "출처": "자체" },
|
||||
{ "이름": "시간당 재료비", "식": "EQ:{기계}.재료비", "비목": "재료비", "출처": "자체" },
|
||||
{ "이름": "시간당 경비", "식": "EQ:{기계}.경비", "비목": "경비", "출처": "자체" }
|
||||
],
|
||||
"끝수": null,
|
||||
"변수표": { "기계": { "기호": "S", "아래": "기계" } }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
"갈래": "기계경비식"
|
||||
},
|
||||
"변수": [
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["1730-0015", "7204-0055", "0602-0150", "2702-0020", "0101-0007", "0101-0010", "0101-0012", "0101-0019", "0101-0032", "2105-0005", "2104-0010", "2104-0015", "2104-0020", "2104-0025", "2104-0030", "2104-0035", "2104-0040", "2104-0045", "2104-0050", "2104-0060", "2104-0070", "2104-0080", "2104-0100", "2104-0130", "2104-0160", "2104-0200", "2104-0220", "2104-0250", "2104-0300", "4504-0032", "4504-0036", "4504-0041", "4504-0043", "4504-0047", "4504-0052", "4205-0010", "4205-0017", "4205-0020", "4205-0030", "4205-0040", "4205-0045", "2105-0002", "2105-0003", "2105-0010", "2105-0015", "2105-0018", "2502-0025", "0602-0025", "2502-0050", "2101-0010", "2101-0015", "2101-0020", "2101-0025", "2101-0030", "2101-0035", "2101-0040", "2101-0050", "2101-0070", "2101-0080", "2101-0100", "2101-0150", "2101-0220", "2101-0280", "2101-0300", "7204-0018", "7204-0160", "5205-0210", "5405-0110", "7505-0450", "5205-0255", "7505-0150", "5205-0103", "6701-0147", "6701-0184", "5205-0170", "7505-0350", "0302-0134", "7505-0100", "7505-0050", "5205-0071", "7505-0025", "0502-0036", "1306-0100", "1506-0032", "0121-0004", "1305-0007", "7204-0038", "7204-0065", "0302-0057", "5701-0020", "0302-0095", "3201-0003", "1106-0012", "1406-0015", "1206-0008", "3601-0102", "1306-0025", "0211-0018", "0602-0045", "0602-0060", "0602-0105", "1630-0080", "3901-0300", "7505-0250", "2502-0035", "1306-0120", "1106-0010", "3201-0001", "1406-0008", "3601-0202", "3601-0402", "3611-0142", "2502-0020", "2502-0075", "5205-0035", "2702-0030", "2702-0060", "0211-0060", "0211-0080", "0211-0100", "0221-0040", "0221-0070", "0302-0025", "0302-0172", "0302-0229", "0302-0287", "0302-0350", "0302-0500", "0406-0054", "0406-0115", "0406-0161", "0406-0206", "0503-0036", "0602-0200", "0602-0240", "0602-0320", "1106-0015", "1206-0010", "1206-0014", "1209-0001", "1209-0002", "1209-0004", "1209-0006", "1209-0007", "1209-0008", "1209-0013", "1306-0044", "1306-0060", "1406-0025", "1506-0011", "1506-0012", "1506-0015", "1506-0019", "1506-0025", "1506-0030", "1506-0037", "2602-0015", "2602-0025", "2602-0035", "2602-0045", "2702-0040", "3530-0015", "3530-0036", "3601-0204", "3601-0302", "3701-0200", "3805-0120", "4504-0021", "4504-0028", "5405-0150", "5701-0010", "7106-0035", "7505-0125", "7505-0200", "7505-0500", "7505-0700", "9010-0003", "9010-0006", "9010-0010", "9010-0012", "9010-0020", "9010-0022", "9010-0033", "9010-0040", "9010-0044", "9010-0060", "9010-0080", "9020-0010", "9020-0015", "9020-0016", "9020-0022", "9020-0035", "9020-0050", "9020-0072", "9020-0160", "9020-0180", "9020-0200", "9050-0075", "9050-0150", "9050-0450", "9050-0750", "9050-0850", "9090-0800", "9090-1000", "9090-1200", "9090-1300", "9090-1400", "9090-1500", "9090-1600"], "값": "1730-0015"}},
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["1730-0015", "7204-0055", "0602-0150", "2702-0020", "0101-0007", "0101-0010", "0101-0012", "0101-0019", "0101-0032", "2105-0005", "2104-0010", "2104-0015", "2104-0020", "2104-0025", "2104-0030", "2104-0035", "2104-0040", "2104-0045", "2104-0050", "2104-0060", "2104-0070", "2104-0080", "2104-0100", "2104-0130", "2104-0160", "2104-0200", "2104-0220", "2104-0250", "2104-0300", "4504-0032", "4504-0036", "4504-0041", "4504-0043", "4504-0047", "4504-0052", "4205-0010", "4205-0017", "4205-0020", "4205-0030", "4205-0040", "4205-0045", "2105-0002", "2105-0003", "2105-0010", "2105-0015", "2105-0018", "2502-0025", "0602-0025", "2502-0050", "2101-0010", "2101-0015", "2101-0020", "2101-0025", "2101-0030", "2101-0035", "2101-0040", "2101-0050", "2101-0070", "2101-0080", "2101-0100", "2101-0150", "2101-0220", "2101-0280", "2101-0300", "7204-0018", "7204-0160", "5205-0210", "5405-0110", "7505-0450", "5205-0255", "7505-0150", "5205-0103", "6701-0147", "6701-0184", "5205-0170", "7505-0350", "0302-0134", "7505-0100", "7505-0050", "5205-0071", "7505-0025", "0502-0036", "1306-0100", "1506-0032", "0121-0004", "1305-0007", "7204-0038", "7204-0065", "0302-0057", "5701-0020", "0302-0095", "3201-0003", "1106-0012", "1406-0015", "1206-0008", "3601-0102", "1306-0025", "0211-0018", "0602-0045", "0602-0060", "0602-0105", "1630-0080", "3901-0300", "7505-0250", "2502-0035", "1306-0120", "1106-0010", "3201-0001", "1406-0008", "3601-0202", "3601-0402", "3611-0142", "2502-0020", "2502-0075", "5205-0035", "2702-0030", "2702-0060", "0211-0060", "0211-0080", "0211-0100", "0221-0040", "0221-0070", "0302-0025", "0302-0172", "0302-0229", "0302-0287", "0302-0350", "0302-0500", "0406-0054", "0406-0115", "0406-0161", "0406-0206", "0503-0036", "0602-0200", "0602-0240", "0602-0320", "1106-0015", "1206-0010", "1206-0014", "1209-0001", "1209-0002", "1209-0004", "1209-0006", "1209-0007", "1209-0008", "1209-0013", "1306-0044", "1306-0060", "1406-0025", "1506-0011", "1506-0012", "1506-0015", "1506-0019", "1506-0025", "1506-0030", "1506-0037", "2602-0015", "2602-0025", "2602-0035", "2602-0045", "2702-0040", "3530-0015", "3530-0036", "3601-0204", "3601-0302", "3701-0200", "3805-0120", "4504-0021", "4504-0028", "5405-0150", "5701-0010", "7106-0035", "7505-0125", "7505-0200", "7505-0500", "7505-0700", "9010-0003", "9010-0006", "9010-0010", "9010-0012", "9010-0020", "9010-0022", "9010-0033", "9010-0040", "9010-0044", "9010-0060", "9010-0080", "9020-0010", "9020-0015", "9020-0016", "9020-0022", "9020-0035", "9020-0050", "9020-0072", "9020-0160", "9020-0180", "9020-0200", "9050-0075", "9050-0150", "9050-0450", "9050-0750", "9050-0850", "9090-0800", "9090-1000", "9090-1200", "9090-1300", "9090-1400", "9090-1500", "9090-1600", "3108-0060", "3108-0080", "3108-0100", "3108-0120", "9010-0120", "9010-0200"], "값": "1730-0015"}},
|
||||
{"열쇠": "지역", "기호": "S", "아래": "지역", "위": "", "이름": "지역", "단위": "", "출처": "건설품셈 공통 8-1-7 5", "연결": {"갈래": "선택", "목록": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"], "값": "전국평균"}},
|
||||
{"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}},
|
||||
{"열쇠": "연료", "기호": "S", "아래": "연료", "위": "", "이름": "연료", "단위": "", "출처": "건설품셈 공통 8-4 주①㉰", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "주연료종류"}},
|
||||
@@ -306,7 +306,7 @@
|
||||
"결과단위": "원/시간",
|
||||
"출처": "건설품셈 공통 8-1-5 · 8-1-6",
|
||||
"변수": [
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["7620-0003", "7621-0100", "7995-0050", "5210-0013", "5210-0027", "5220-0015", "7730-0150", "6516-0060", "6516-0120", "6516-0250", "6516-0300", "6105-0190", "6202-0060", "0230-0002", "6410-0080", "6410-0100", "6410-0120", "6410-0150", "6410-0200", "6901-0010", "6530-0090", "6530-0120", "6517-0100", "6517-0150", "6517-0200", "6517-0250", "6517-0300", "6510-0100", "6510-0150", "6510-0200", "6510-0250", "6510-0300", "6518-0100", "6518-0150", "6518-0200", "6518-0250", "6518-0300", "5501-0080", "7750-0016", "7750-0025", "7730-0050", "5401-0017", "5202-0127", "5202-0240", "5202-0300", "7611-0200", "7612-0200", "5204-0200", "5204-0300", "5204-0400", "5204-0500", "5204-0600", "5702-0095", "3430-0400", "7431-1300", "7740-0080", "7740-0150", "2101-0010", "2101-0015", "2101-0020", "2101-0025", "2101-0030", "2101-0035", "2101-0040", "2101-0050", "2101-0070", "2101-0080", "2101-0100", "2101-0150", "2101-0220", "2101-0280", "2101-0300", "2104-0010", "2104-0015", "2104-0020", "2104-0025", "2104-0030", "2104-0035", "2104-0040", "2104-0045", "2104-0050", "2104-0060", "2104-0070", "2104-0080", "2104-0100", "2104-0130", "2104-0160", "2104-0200", "2104-0220", "2104-0250", "2104-0300", "2208-5008", "2208-5010", "2208-5012", "2208-5016", "2208-5020", "2105-0002", "2105-0003", "2105-0005", "2105-0010", "2105-0015", "2105-0018", "0201-0012", "0201-0020", "0201-0040", "0201-0060", "0201-0070", "0201-0080", "0201-0100", "0201-0120", "0201-0200", "6105-0390", "6202-0125", "7830-0081", "7950-0149", "7951-0066", "7952-0246", "7953-3400", "7954-1119", "7611-0300", "7431-1100", "7431-2300", "7431-2500", "7611-0400", "7611-0500", "7614-0300", "0250-0100", "5210-0010", "5210-0019", "0103-0016", "0103-0019", "0103-0023", "0103-0027", "0103-0032", "0230-0004", "0230-0006", "0230-0007", "0230-0008", "0230-0010", "0240-0007", "0250-0080", "0407-0054", "0407-0092", "0407-0107", "0407-0161", "0407-0206", "0610-0150", "0610-0200", "0610-0240", "2115-0024", "2115-0031", "2115-0036", "2116-0031", "2116-0036", "2117-0022", "2117-0027", "2118-0010", "2210-0145", "3430-0300", "3450-0642", "4115-0100", "4115-0150", "4115-0200", "4115-0300", "4505-0015", "4505-0026", "4611-0075", "5105-0050", "5105-0100", "5105-0150", "5105-0200", "5111-0040", "5111-0050", "5111-0060", "5111-0076", "5111-0091", "5112-0001", "5112-0002", "5112-0003", "5112-0004", "5112-0005", "5113-0001", "5113-0002", "5113-0003", "5113-0004", "5113-0005", "5113-0006", "5113-0007", "5113-0008", "5113-0009", "5113-0010", "5113-0011", "5114-0001", "5114-0002", "5114-0003", "5114-0004", "5114-0005", "5114-0006", "5114-0007", "5114-0008", "5115-0030", "5115-0055", "5115-0075", "5115-0095", "5116-0001", "5116-0002", "5116-0003", "5116-0004", "5116-0005", "5116-0006", "5116-0007", "5116-0008", "5117-0001", "5117-0002", "5117-0003", "5117-0004", "5117-0005", "5117-0006", "5117-0007", "5117-0008", "5118-0001", "5118-0002", "5118-0003", "5118-0004", "5118-0005", "5118-0006", "5118-0007", "5119-0625", "5203-1800", "5203-2200", "5203-2700", "5203-3500", "5203-4500", "5330-0074", "5805-0002", "5805-0003", "5901-0006", "5901-0010", "5901-0016", "6202-0200", "6408-0015", "6408-0020", "6408-0030", "6408-0040", "6408-0050", "6408-0085", "6408-0100", "6515-0090", "6530-0030", "6530-0040", "6530-0045", "6530-0060", "6532-0220", "6550-0130", "7103-0010", "7104-0010", "7202-0008", "7202-0010", "7205-0125", "7206-0020", "7206-0070", "7206-0100", "7430-1100", "7430-1300", "7430-1500", "7430-2300", "7430-2500", "7612-0300", "7612-0400", "7613-0075", "7613-0150", "7613-0300", "7613-0400", "7613-0600", "7613-0900", "7620-0002", "7730-0080", "7730-0100", "7730-0125", "7740-0100", "7770-0004", "7930-0001", "7930-0002", "7930-0003", "7930-0005", "7930-0007", "7930-0010", "7930-0015", "7930-0020", "7930-0025", "7930-0030", "7930-0040", "7930-0050", "7930-0075", "7930-0100", "7935-0180", "7991-0050", "7991-0100", "7991-0500", "7993-0020", "8201-0100", "8202-0100", "8203-0019", "8204-0100", "8205-0100", "9060-0060", "9060-0100", "9060-0200", "9060-0300", "9060-0500", "9060-0600", "9080-0050", "9080-0080", "9080-0100", "9080-0120", "9080-0150", "9080-0200", "9080-0300", "9080-0500", "9080-0700", "9080-1000", "9080-1100", "9080-1400", "9080-1500", "9080-1750", "9080-2000", "9080-3000"], "값": "7620-0003"}},
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["7620-0003", "7621-0100", "7995-0050", "5210-0013", "5210-0027", "5220-0015", "7730-0150", "6516-0060", "6516-0120", "6516-0250", "6516-0300", "6105-0190", "6202-0060", "0230-0002", "6410-0080", "6410-0100", "6410-0120", "6410-0150", "6410-0200", "6901-0010", "6530-0090", "6530-0120", "6517-0100", "6517-0150", "6517-0200", "6517-0250", "6517-0300", "6510-0100", "6510-0150", "6510-0200", "6510-0250", "6510-0300", "6518-0100", "6518-0150", "6518-0200", "6518-0250", "6518-0300", "5501-0080", "7750-0016", "7750-0025", "7730-0050", "5401-0017", "5202-0127", "5202-0240", "5202-0300", "7611-0200", "7612-0200", "5204-0200", "5204-0300", "5204-0400", "5204-0500", "5204-0600", "5702-0095", "3430-0400", "7431-1300", "7740-0080", "7740-0150", "2101-0010", "2101-0015", "2101-0020", "2101-0025", "2101-0030", "2101-0035", "2101-0040", "2101-0050", "2101-0070", "2101-0080", "2101-0100", "2101-0150", "2101-0220", "2101-0280", "2101-0300", "2104-0010", "2104-0015", "2104-0020", "2104-0025", "2104-0030", "2104-0035", "2104-0040", "2104-0045", "2104-0050", "2104-0060", "2104-0070", "2104-0080", "2104-0100", "2104-0130", "2104-0160", "2104-0200", "2104-0220", "2104-0250", "2104-0300", "2105-0002", "2105-0003", "2105-0005", "2105-0010", "2105-0015", "2105-0018", "0201-0012", "0201-0020", "0201-0040", "0201-0060", "0201-0070", "0201-0080", "0201-0100", "0201-0120", "0201-0200", "6105-0390", "6202-0125", "7830-0081", "7950-0149", "7951-0066", "7952-0246", "7953-3400", "7954-1119", "7611-0300", "7431-1100", "7431-2300", "7431-2500", "7611-0400", "7611-0500", "7614-0300", "0250-0100", "5210-0010", "5210-0019", "0103-0016", "0103-0019", "0103-0023", "0103-0027", "0103-0032", "0230-0004", "0230-0006", "0230-0007", "0230-0008", "0230-0010", "0240-0007", "0250-0080", "0407-0054", "0407-0092", "0407-0107", "0407-0161", "0407-0206", "0610-0150", "0610-0200", "0610-0240", "2115-0024", "2115-0031", "2115-0036", "2116-0031", "2116-0036", "2117-0022", "2117-0027", "2118-0010", "2210-0145", "3430-0300", "4115-0100", "4115-0150", "4115-0200", "4115-0300", "4505-0015", "4505-0026", "4611-0075", "5111-0040", "5111-0050", "5111-0060", "5111-0076", "5111-0091", "5112-0001", "5112-0002", "5112-0003", "5112-0004", "5112-0005", "5113-0001", "5113-0002", "5113-0003", "5113-0004", "5113-0005", "5113-0006", "5113-0007", "5113-0008", "5113-0009", "5113-0010", "5113-0011", "5114-0001", "5114-0002", "5114-0003", "5114-0004", "5114-0005", "5114-0006", "5114-0007", "5114-0008", "5115-0030", "5115-0055", "5115-0075", "5115-0095", "5116-0001", "5116-0002", "5116-0003", "5116-0004", "5116-0005", "5116-0006", "5116-0007", "5116-0008", "5117-0001", "5117-0002", "5117-0003", "5117-0004", "5117-0005", "5117-0006", "5117-0007", "5117-0008", "5118-0001", "5118-0002", "5118-0003", "5118-0004", "5118-0005", "5118-0006", "5118-0007", "5203-1800", "5203-2200", "5203-2700", "5203-3500", "5203-4500", "5330-0074", "5901-0006", "5901-0010", "5901-0016", "6202-0200", "6408-0015", "6408-0020", "6408-0030", "6408-0040", "6408-0050", "6408-0085", "6408-0100", "6515-0090", "6530-0030", "6530-0040", "6530-0045", "6530-0060", "6532-0220", "6550-0130", "7103-0010", "7104-0010", "7206-0020", "7206-0070", "7206-0100", "7430-1100", "7430-1300", "7430-1500", "7430-2300", "7430-2500", "7612-0300", "7612-0400", "7613-0075", "7613-0150", "7613-0300", "7613-0400", "7613-0600", "7613-0900", "7620-0002", "7730-0080", "7730-0100", "7730-0125", "7740-0100", "7770-0004", "7930-0001", "7930-0002", "7930-0003", "7930-0005", "7930-0007", "7930-0010", "7930-0015", "7930-0020", "7930-0025", "7930-0030", "7930-0040", "7930-0050", "7930-0075", "7930-0100", "7935-0180", "8201-0100", "8202-0100", "8203-0019", "8204-0100", "8205-0100", "9060-0060", "9060-0100", "9060-0200", "9060-0300", "9060-0500", "9060-0600", "9080-0050", "9080-0080", "9080-0100", "9080-0120", "9080-0150", "9080-0200", "9080-0300", "9080-0500", "9080-0700", "9080-1000", "9080-1100", "9080-1400", "9080-1500", "9080-1750", "9080-2000", "9080-3000"], "값": "7620-0003"}},
|
||||
{"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}},
|
||||
{"열쇠": "P_기계", "기호": "P", "아래": "기계", "위": "", "이름": "EQ:{기계}.가격", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격"}},
|
||||
{"열쇠": "k_기계손료", "기호": "k", "아래": "기계손료", "위": "", "이름": "EQ:{기계}.손료계수", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "손료계수"}}
|
||||
@@ -412,7 +412,7 @@
|
||||
"갈래": "기계경비식"
|
||||
},
|
||||
"변수": [
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["5401-0017", "4108-0060", "4108-0090", "4108-0120", "4108-0150", "4108-0180", "4108-0210", "5401-0015"], "값": "5401-0017"}},
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["5401-0017", "4108-0060", "4108-0090", "4108-0120", "4108-0150", "4108-0180", "4108-0210", "5401-0015", "2208-5008", "2208-5010", "2208-5012", "2208-5016", "2208-5020", "5105-0050", "5105-0100", "5105-0150", "5105-0200", "5119-0625", "7205-0125"], "값": "5401-0017"}},
|
||||
{"열쇠": "지역", "기호": "S", "아래": "지역", "위": "", "이름": "지역", "단위": "", "출처": "건설품셈 공통 8-1-7 5", "연결": {"갈래": "선택", "목록": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"], "값": "전국평균"}},
|
||||
{"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}},
|
||||
{"열쇠": "직종", "기호": "S", "아래": "직종", "위": "", "이름": "직종", "단위": "", "출처": "건설품셈 공통 8-1-3 5", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "조종원직종"}},
|
||||
@@ -2213,6 +2213,145 @@
|
||||
"비목": {"방법": "버림", "자리": 0},
|
||||
"끝전": "비목버림"
|
||||
}
|
||||
},
|
||||
{
|
||||
"꼴": "수식문서",
|
||||
"판": 1,
|
||||
"키": "GC001196",
|
||||
"이름": "기계 시간당 기계경비(전력 기종)",
|
||||
"결과단위": "원/시간",
|
||||
"출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가",
|
||||
"부품": {
|
||||
"갈래": "기계경비식"
|
||||
},
|
||||
"변수": [
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["7991-0050", "7202-0008", "7202-0010", "7991-0100", "7991-0500", "7992-0001", "7993-0020"], "값": "7991-0050"}},
|
||||
{"열쇠": "전력 계약종별", "기호": "S", "아래": "전력계약종별", "위": "", "이름": "전력 계약종별", "단위": "", "출처": "유가전력 한전 전기요금표 2025-01-01", "연결": {"갈래": "선택", "목록": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "값": "일반용(갑)Ⅰ 저압"}},
|
||||
{"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}},
|
||||
{"열쇠": "P_기계", "기호": "P", "아래": "기계", "위": "", "이름": "EQ:{기계}.가격", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "k_기계손료", "기호": "k", "아래": "기계손료", "위": "", "이름": "EQ:{기계}.손료계수", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "손료계수", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "P_기계전력", "기호": "P", "아래": "기계전력", "위": "", "이름": "EQ:{기계}.전력", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "전력", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "P_전력", "기호": "P", "아래": "전력", "위": "", "이름": "전력단가", "단위": "", "연결": {"갈래": "요소", "재료": {"이름": "전력량요금", "계약종별": "입력"}, "단위": "㎾h", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "r_기계잡재료", "기호": "r", "아래": "기계잡재료", "위": "", "이름": "EQ:{기계}.잡재료율", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "잡재료율", "계약종별": "S_전력계약종별"}}
|
||||
],
|
||||
"식": [
|
||||
{"기호": "C_손료", "식": "버림(P_기계 × 1000 × k_기계손료 ÷ 10000000, 0)"}
|
||||
],
|
||||
"금액": [
|
||||
{"이름": "전력", "단위": "㎾h", "비목": "재료비", "수량": "P_기계전력", "단가": "P_전력", "출처": "건설품셈 공통 8-1-6 3 가"},
|
||||
{"이름": "잡재료비", "단위": "식", "비목": "재료비", "단가": "재료비 × r_기계잡재료 ÷ 100", "출처": "건설품셈 공통 8-4 주②"},
|
||||
{"이름": "기계손료", "단위": "식", "비목": "경비", "단가": "C_손료", "출처": "건설품셈 공통 8-1-6 2"}
|
||||
],
|
||||
"끝수": {
|
||||
"줄": {"방법": "버림", "자리": 1},
|
||||
"비목": {"방법": "버림", "자리": 0},
|
||||
"끝전": "비목버림"
|
||||
}
|
||||
},
|
||||
{
|
||||
"꼴": "수식문서",
|
||||
"판": 1,
|
||||
"키": "GC001197",
|
||||
"이름": "기계 시간당 기계경비(전력 · 조종원 기종)",
|
||||
"결과단위": "원/시간",
|
||||
"출처": "건설품셈 공통 8-1-5 · 8-1-6 · 8-1-6 3 가",
|
||||
"부품": {
|
||||
"갈래": "기계경비식"
|
||||
},
|
||||
"변수": [
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["5805-0002", "5805-0003"], "값": "5805-0002"}},
|
||||
{"열쇠": "전력 계약종별", "기호": "S", "아래": "전력계약종별", "위": "", "이름": "전력 계약종별", "단위": "", "출처": "유가전력 한전 전기요금표 2025-01-01", "연결": {"갈래": "선택", "목록": ["일반용(갑)Ⅰ 저압", "주택용 저압"], "값": "일반용(갑)Ⅰ 저압"}},
|
||||
{"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}},
|
||||
{"열쇠": "직종", "기호": "S", "아래": "직종", "위": "", "이름": "직종", "단위": "", "출처": "건설품셈 공통 8-1-3 5", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "조종원직종", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "시간환산", "기호": "Q", "아래": "시간환산", "위": "", "이름": "시간환산", "단위": "", "출처": "건설품셈 공통 1-1-3 2(일일 작업시간 8시간)", "연결": {"갈래": "식"}},
|
||||
{"열쇠": "P_기계", "기호": "P", "아래": "기계", "위": "", "이름": "EQ:{기계}.가격", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "k_기계손료", "기호": "k", "아래": "기계손료", "위": "", "이름": "EQ:{기계}.손료계수", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "손료계수", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "Q_분자^표", "기호": "Q", "아래": "분자", "위": "표", "이름": "건설기계 조종원 노임 시간 환산 계수.분자", "단위": "", "연결": {"갈래": "표", "표": "CC000336", "조건": {"구분": "'시간환산'"}, "칸": "분자"}},
|
||||
{"열쇠": "Q_분모^표", "기호": "Q", "아래": "분모", "위": "표", "이름": "건설기계 조종원 노임 시간 환산 계수.분모", "단위": "", "연결": {"갈래": "표", "표": "CC000336", "조건": {"구분": "'시간환산'"}, "칸": "분모"}},
|
||||
{"열쇠": "P_기계전력", "기호": "P", "아래": "기계전력", "위": "", "이름": "EQ:{기계}.전력", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "전력", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "P_전력", "기호": "P", "아래": "전력", "위": "", "이름": "전력단가", "단위": "", "연결": {"갈래": "요소", "재료": {"이름": "전력량요금", "계약종별": "입력"}, "단위": "㎾h", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "Q_기계조종원", "기호": "Q", "아래": "기계조종원", "위": "", "이름": "EQ:{기계}.조종원", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "조종원", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "w_기계운전사", "기호": "w", "아래": "기계운전사", "위": "", "이름": "건설기계운전사노임", "단위": "", "연결": {"갈래": "요소", "키": "LB:{S_직종}", "계약종별": "S_전력계약종별"}},
|
||||
{"열쇠": "r_기계잡재료", "기호": "r", "아래": "기계잡재료", "위": "", "이름": "EQ:{기계}.잡재료율", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "잡재료율", "계약종별": "S_전력계약종별"}}
|
||||
],
|
||||
"식": [
|
||||
{"기호": "C_손료", "식": "버림(P_기계 × 1000 × k_기계손료 ÷ 10000000, 0)"},
|
||||
{"기호": "Q_시간환산", "식": "Q_분자^표 ÷ Q_분모^표"}
|
||||
],
|
||||
"금액": [
|
||||
{"이름": "전력", "단위": "㎾h", "비목": "재료비", "수량": "P_기계전력", "단가": "P_전력", "출처": "건설품셈 공통 8-1-6 3 가"},
|
||||
{"이름": "조종원", "단위": "인", "비목": "노무비", "수량": "Q_기계조종원 × Q_시간환산", "단가": "w_기계운전사", "출처": "건설품셈 공통 8-1-3 6"},
|
||||
{"이름": "잡재료비", "단위": "식", "비목": "재료비", "단가": "재료비 × r_기계잡재료 ÷ 100", "출처": "건설품셈 공통 8-4 주②"},
|
||||
{"이름": "기계손료", "단위": "식", "비목": "경비", "단가": "C_손료", "출처": "건설품셈 공통 8-1-6 2"}
|
||||
],
|
||||
"끝수": {
|
||||
"줄": {"방법": "버림", "자리": 1},
|
||||
"비목": {"방법": "버림", "자리": 0},
|
||||
"끝전": "비목버림"
|
||||
}
|
||||
},
|
||||
{
|
||||
"꼴": "수식문서",
|
||||
"판": 1,
|
||||
"키": "GC001198",
|
||||
"이름": "기계 시간당 기계경비(조종원 없는 기종 · 손료계수 한 칸)",
|
||||
"결과단위": "원/시간",
|
||||
"출처": "건설품셈 공통 8-1-5 · 8-1-6",
|
||||
"부품": {
|
||||
"갈래": "기계경비식"
|
||||
},
|
||||
"변수": [
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": ["7994-0050"], "값": "7994-0050"}},
|
||||
{"열쇠": "지역", "기호": "S", "아래": "지역", "위": "", "이름": "지역", "단위": "", "출처": "건설품셈 공통 8-1-7 5", "연결": {"갈래": "선택", "목록": ["전국평균", "전국", "서울", "경기", "강원", "충북", "충남", "전북", "경북", "경남", "부산", "제주", "대구", "인천", "대전", "울산", "세종", "전남광주"], "값": "전국평균"}},
|
||||
{"열쇠": "손료", "기호": "C", "아래": "손료", "위": "", "이름": "손료", "단위": "", "출처": "건설품셈 공통 8-1-5 12 · 8-1-6 4", "연결": {"갈래": "식"}},
|
||||
{"열쇠": "연료", "기호": "S", "아래": "연료", "위": "", "이름": "연료", "단위": "", "출처": "건설품셈 공통 8-4 주①㉰", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "주연료종류"}},
|
||||
{"열쇠": "P_기계", "기호": "P", "아래": "기계", "위": "", "이름": "EQ:{기계}.가격", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "가격"}},
|
||||
{"열쇠": "k_기계손료", "기호": "k", "아래": "기계손료", "위": "", "이름": "EQ:{기계}.손료계수", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "손료계수"}},
|
||||
{"열쇠": "P_기계주연료", "기호": "P", "아래": "기계주연료", "위": "", "이름": "EQ:{기계}.주연료", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "주연료"}},
|
||||
{"열쇠": "P_휘발유", "기호": "P", "아래": "휘발유", "위": "", "이름": "휘발유단가", "단위": "", "연결": {"갈래": "요소", "키": "MO:{S_연료}:{S_지역}"}},
|
||||
{"열쇠": "r_기계잡재료", "기호": "r", "아래": "기계잡재료", "위": "", "이름": "EQ:{기계}.잡재료율", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "잡재료율"}}
|
||||
],
|
||||
"식": [
|
||||
{"기호": "C_손료", "식": "버림(P_기계 × 1000 × k_기계손료 ÷ 10000000, 0)"}
|
||||
],
|
||||
"금액": [
|
||||
{"이름": "주연료", "단위": "ℓ", "비목": "재료비", "수량": "P_기계주연료", "단가": "P_휘발유", "출처": "건설품셈 공통 8-4-8"},
|
||||
{"이름": "잡재료비", "단위": "식", "비목": "재료비", "단가": "재료비 × r_기계잡재료 ÷ 100", "출처": "건설품셈 공통 8-4 주②"},
|
||||
{"이름": "기계손료", "단위": "식", "비목": "경비", "단가": "C_손료", "출처": "건설품셈 공통 8-1-6 2"}
|
||||
],
|
||||
"끝수": {
|
||||
"줄": {"방법": "버림", "자리": 1},
|
||||
"비목": {"방법": "버림", "자리": 0},
|
||||
"끝전": "비목버림"
|
||||
}
|
||||
},
|
||||
{
|
||||
"꼴": "수식문서",
|
||||
"판": 1,
|
||||
"키": "GC001199",
|
||||
"이름": "기계 시간당 기계경비(직접 값)",
|
||||
"결과단위": "원/시간",
|
||||
"출처": "자체",
|
||||
"부품": {
|
||||
"갈래": "기계경비식"
|
||||
},
|
||||
"변수": [
|
||||
{"열쇠": "기계", "기호": "S", "아래": "기계", "위": "", "이름": "기계", "단위": "", "연결": {"갈래": "선택", "목록": [], "값": 0}},
|
||||
{"열쇠": "P_EQ기계", "기호": "P", "아래": "EQ기계", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "노무비"}},
|
||||
{"열쇠": "P_EQ기계2", "기호": "P", "아래": "EQ기계2", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "재료비"}},
|
||||
{"열쇠": "P_EQ기계3", "기호": "P", "아래": "EQ기계3", "위": "", "이름": "EQ:{기계}", "단위": "", "연결": {"갈래": "요소", "키": "EQ:{S_기계}", "칸": "경비"}}
|
||||
],
|
||||
"식": [],
|
||||
"금액": [
|
||||
{"이름": "시간당 노무비", "단위": "식", "비목": "노무비", "단가": "P_EQ기계", "출처": "자체"},
|
||||
{"이름": "시간당 재료비", "단위": "식", "비목": "재료비", "단가": "P_EQ기계2", "출처": "자체"},
|
||||
{"이름": "시간당 경비", "단위": "식", "비목": "경비", "단가": "P_EQ기계3", "출처": "자체"}
|
||||
],
|
||||
"끝수": {
|
||||
"줄": {"방법": "버림", "자리": 1},
|
||||
"비목": {"방법": "버림", "자리": 0},
|
||||
"끝전": "비목버림"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -116,7 +116,9 @@ def _hourly_inputs(logic_key: str) -> dict:
|
||||
|
||||
|
||||
def _kind(row: dict) -> tuple:
|
||||
return (*mh._rank(row)[:3], any(x.get("이름") == "조종원" for x in row.get("호표") or []))
|
||||
"""갈래 = 부착 · 손료만 · 보정 · 조종원 줄 · 전력 줄(822-2 전력 기종 식 — 손료만 식과 갈림)."""
|
||||
lines = {x.get("이름") for x in row.get("호표") or []}
|
||||
return (*mh._rank(row)[:3], "조종원" in lines, "전력" in lines)
|
||||
|
||||
|
||||
# 기계표 조종원 1 인 · 「조종원 없는 기종」 GC000272 목록에도 겹친 기계(815-3) — 조종원 든 식
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
||||
"""822-2 기계 시간당 경비 식 완성 — 지킴 시험(정본 고침은 임시 사본 폴더 · 임시 storage 만).
|
||||
|
||||
① 모든 기계 = 식 있음 또는 까닭 글(「셀 자료가 없음」 0) ② 식 고름 = 목록 › 꼴(채운 칸) 한 함수
|
||||
③ M01 [새 기계] 저장 = 꼴 식 목록 등록 · 지우면 목록에서 뺌 · 로직 파일 글 그대로(임시 마스터)
|
||||
④ 직접 값 식(GC001199) — 내 기계 「직접」 시간당 · 줄 쌓기 식 ⑤ 전력 줄 — 점보드릴 135㎾ × 전력 단가 +
|
||||
잡재료 6 % + 손료 + 조종원 · 계약종별 바꿈 · 내 기계 전력 ⑥ 옮긴 기계 견본(아스팔트 믹싱플랜트 · 타워크레인 ·
|
||||
직종 입력 = 아스팔트 스프레어) ⑦ 미리보기 = 서버 값 ⑧ 안 옮긴 기계 금액 그대로 ⑨ POWER TROWEL 이름.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import sys
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from common_util import common_util_auth as auth
|
||||
from M01_MasterData import M01_MasterData_Router as router_module
|
||||
from M01_MasterData import M01_MasterData_Store as m01
|
||||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||||
from M02_MasterTemplete import M02_Machine_Hourly as mh
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
from M02_MasterTemplete import M02_MyMachine as mym
|
||||
from M02_MasterTemplete import M02_Sangeun_Calc as calc
|
||||
from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(ROOT / "resources" / "master_data" / "scripts"))
|
||||
import master_machine_coef as mc # noqa: E402
|
||||
|
||||
MACHINE, LOGIC = "기계.json", "로직_건설품셈_08장_건설기계.json"
|
||||
POWER, POWER_CREW, ONE_FUEL, DIRECT = "GC001196", "GC001197", "GC001198", "GC001199"
|
||||
NAME = "sub1임시기계822"
|
||||
# 안 옮긴 기계 — 822-2 전 금액(전국평균 · 기본 옵션)
|
||||
KEEP = {"EQ000001": 68550, "EQ000022": 108958}
|
||||
|
||||
|
||||
def _rows() -> dict[str, dict]:
|
||||
return {r["키"]: r for r in m01.read(MACHINE)[0]["줄"]}
|
||||
|
||||
|
||||
def _wage(job: str) -> Decimal:
|
||||
return Decimal(str(m01.loaded()[1].get(f"LB:{job}")["값"]))
|
||||
|
||||
|
||||
def _codes(key: str) -> list[str]:
|
||||
row = next(r for r in m01.read(LOGIC)[0]["줄"] if r["키"] == key)
|
||||
return [str(c) for c in next(i for i in row["입력"] if i["이름"] == "기계").get("고르기", [])]
|
||||
|
||||
|
||||
# ① · ② ───────────────────────────────────────────────────────────────
|
||||
def test_every_machine_has_formula_or_reason():
|
||||
"""모든 기계 — 식을 고르고 값이 다 있음 · 아니면 까닭 글(빈 답 0)."""
|
||||
silent = []
|
||||
for key, row in _rows().items():
|
||||
row = m01.loaded()[1].get(key)
|
||||
logic = mh.pick(row)
|
||||
if not logic and not mh.why(row, logic):
|
||||
silent.append(key)
|
||||
assert silent == []
|
||||
assert mh.hourly("EQ000343")["reason"] == "가격 없음" # TBM 3.0m
|
||||
assert "일 단위" in mh.hourly("EQ000621")["reason"] # 산림품셈 예취기(1일 1대당)
|
||||
assert mh.hourly("EQ000202")["reason"] == "주연료 「73.7+」 — 수 아님" # 표층재생기 · 안 풂
|
||||
assert "범위" in mh.hourly("EQ000552")["reason"] # 펌프 준설선 잡재료 13∼18
|
||||
assert (
|
||||
"중유" in mh.hourly("EQ000187")["reason"]
|
||||
) # 아스팔트 믹싱플랜트 40t — 유가 표에 중유 없음
|
||||
|
||||
|
||||
def test_pick_listed_then_shape():
|
||||
"""목록에 있으면 그 식(짝 차례) · 없으면 꼴 — 내 기계와 같은 규칙."""
|
||||
assert mh.logic_of("0101-0007")["키"] in {"GC000268", "GC000269"} # 목록
|
||||
shape = mym.logic_key
|
||||
full = {"가격": 1, "손료계수": 3, "상각비계수": 1, "정비비계수": 1, "관리비계수": 1}
|
||||
assert shape({"값": {**full, "주연료": 1, "조종원": 1, "조종원직종": "1048"}}) == "GC000268"
|
||||
assert shape({"값": {**full, "주연료": 1, "조종원": 1}}) == "GC000275"
|
||||
assert shape({"값": {**full, "주연료": 1}}) == "GC000272"
|
||||
assert shape({"값": {"가격": 1, "손료계수": 3, "주연료": 1}}) == ONE_FUEL
|
||||
assert shape({"값": {**full, "조종원": 1, "조종원직종": "1048"}}) == "GC000276"
|
||||
assert shape({"값": {**full, "전력": 5}}) == POWER
|
||||
assert shape({"값": {**full, "전력": 5, "조종원": 1, "조종원직종": "1048"}}) == POWER_CREW
|
||||
assert shape({"값": full}) == "GC000273"
|
||||
assert shape({"방식": "직접", "값": {}}) == DIRECT
|
||||
assert shape({"값": {**full, "주연료": 1, "전력": 5}}) is None
|
||||
assert shape({"값": {**full, "조종원": 1}}) is None # 직종 없는 조종원만 — 까닭
|
||||
assert shape({"값": {**full, "주연료": "73.7+"}}) is None
|
||||
|
||||
|
||||
# ③ M01 [새 기계] 식 등록 ──────────────────────────────────────────────
|
||||
@pytest.fixture
|
||||
def copy(tmp_path: Path, monkeypatch) -> Path:
|
||||
for path in m01.FOLDER.glob("*.json"):
|
||||
if not path.name.startswith("_") or path.name == m01.mk.BOOK.name:
|
||||
shutil.copy(path, tmp_path / path.name)
|
||||
monkeypatch.setattr(m01, "FOLDER", tmp_path)
|
||||
return tmp_path
|
||||
|
||||
|
||||
def _app() -> TestClient:
|
||||
app = FastAPI()
|
||||
app.dependency_overrides[auth.verify_session] = lambda: {
|
||||
"user_id": 1, "name": "시험", "role": "SYSTEM_ADMIN", "company_id": 1,
|
||||
} # fmt: skip
|
||||
deps = [Depends(auth.verify_session), Depends(auth.require_system_admin)]
|
||||
app.include_router(router_module.router, dependencies=deps)
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
def _save(client: TestClient, changes: list[dict]) -> None:
|
||||
version = client.get("/api/m01/machine/row", params={"key": "EQ000022"}).json()["version"]
|
||||
body = {"files": [{"file": MACHINE, "version": version, "changes": changes}]}
|
||||
res = client.post("/api/m01/save", json=body)
|
||||
assert res.status_code == 200, res.text
|
||||
|
||||
|
||||
def test_new_machine_registers_and_unregisters(copy: Path):
|
||||
client = _app()
|
||||
logic_text = (copy / LOGIC).read_text(encoding="utf-8")
|
||||
seed = json.loads(json.dumps(_rows()["EQ000022"], default=float))
|
||||
row = {**seed, "키": "", "원문번호": "9999-0822", "이름": NAME, "출처": {}, "단위": {}}
|
||||
del row["별칭"]
|
||||
draft = client.post("/api/m01/machine/formula", json=row).json()
|
||||
assert draft["키"] == "GC000268" and draft["방법"] == "꼴" and not draft["까닭"]
|
||||
_save(client, [{"op": "add", "row": row}])
|
||||
assert "9999-0822" in _codes("GC000268")
|
||||
key = next(k for k, r in _rows().items() if r["원문번호"] == "9999-0822")
|
||||
hour = client.get("/api/m01/machine/hourly", params={"keys": key}).json()[key]
|
||||
assert hour["로직"] == "GC000268" and hour["계"] == mh.hourly("EQ000022")["계"]
|
||||
saved = json.loads(json.dumps(_rows()[key], default=float))
|
||||
got = client.post("/api/m01/machine/formula", json=saved).json()
|
||||
assert got["방법"] == "목록" and got["키"] == "GC000268"
|
||||
_save(client, [{"op": "delete", "key": key}])
|
||||
assert "9999-0822" not in _codes("GC000268")
|
||||
assert (copy / LOGIC).read_text(encoding="utf-8") == logic_text
|
||||
|
||||
|
||||
# ④ 직접 값 식 ─────────────────────────────────────────────────────────
|
||||
def _at(folder, fn, *args):
|
||||
with store.at(folder):
|
||||
return fn(*args)
|
||||
|
||||
|
||||
def test_direct_formula_my_machine(world):
|
||||
me = world["personal"]
|
||||
body = {
|
||||
"이름": NAME,
|
||||
"규격": "직접",
|
||||
"방식": "직접",
|
||||
"시간당": {"노무비": 10, "재료비": 20, "경비": 30},
|
||||
}
|
||||
made = _at(me, mym.create, body)
|
||||
assert made["시간당"]["로직"] == DIRECT and made["시간당"]["계"] == 60
|
||||
no = made["줄"]["원문번호"]
|
||||
line = {"종류": "로직", "로직": DIRECT, "입력값": {"기계": no}, "수량": "2"}
|
||||
name = _at(
|
||||
me, lambda: refs.create("sangeun", {"이름": NAME, "단위": "시간", "더한줄": [line]})["이름"]
|
||||
)
|
||||
doc = _at(me, lambda: store.read("sangeun", name)["문서"])
|
||||
got = _at(me, calc.calc_doc, doc, None, False)["기준"]
|
||||
assert (got["노무비"], got["재료비"], got["경비"]) == (20, 40, 60)
|
||||
|
||||
|
||||
# ⑤ 전력 줄 ────────────────────────────────────────────────────────────
|
||||
def _preview(key: str) -> dict:
|
||||
v = json.loads(json.dumps(_rows()[key]["값"], default=float))
|
||||
fuel = m01.loaded()[1].numbers["MO"].get(f"{v.get('주연료종류')}:전국평균")
|
||||
wage = float(_wage(v["조종원직종"])) if v.get("조종원직종") else 0
|
||||
return mc.preview(v, float((fuel or {}).get("값") or 0), wage, 114.4)
|
||||
|
||||
|
||||
def test_power_line_jumbo_drill():
|
||||
h = mh.hourly("EQ000347") # 점보드릴 2붐 135㎾ · 잡재료 6 % · 조종원 1(건설기계운전사)
|
||||
assert h["로직"] == POWER_CREW
|
||||
loss = 605472 * 1000 * 2515 // 10**7
|
||||
elec = Decimal("135") * Decimal("114.4")
|
||||
misc = int(elec * 6) / Decimal(100)
|
||||
assert h["경비"] == loss and h["재료비"] == int(elec + misc)
|
||||
assert h["노무비"] == int(_wage("1048") / 8)
|
||||
p = _preview("EQ000347")
|
||||
assert (p["노무비"], p["재료비"], p["경비"], p["계"]) == (
|
||||
h["노무비"],
|
||||
h["재료비"],
|
||||
h["경비"],
|
||||
h["계"],
|
||||
)
|
||||
home = m01.calc(POWER_CREW, {"기계": "5805-0002", "전력 계약종별": "주택용 저압"})
|
||||
assert home["ok"] and float(home["sums"]["재료비"]) > h["재료비"] # 120 원/kWh > 114.4
|
||||
|
||||
|
||||
def test_power_my_machine(world):
|
||||
me = world["personal"]
|
||||
body = {
|
||||
"이름": NAME,
|
||||
"규격": "전력",
|
||||
"방식": "바로",
|
||||
"값": {"가격": 1000, "손료계수": 2000, "전력": 10, "잡재료율": 5},
|
||||
}
|
||||
hour = _at(me, mym.create, body)["시간당"]
|
||||
assert hour["로직"] == POWER
|
||||
want = mc.preview({"가격": 1000, "손료계수": 2000, "전력": 10, "잡재료율": 5}, 0, 0, 114.4)
|
||||
assert (hour["재료비"], hour["경비"]) == (want["재료비"], want["경비"]) == (1201, 200)
|
||||
with pytest.raises(store.StoreError):
|
||||
_at(me, mym.create, {**body, "값": {**body["값"], "주연료": 1, "주연료종류": "경유"}})
|
||||
|
||||
|
||||
# ⑥ · ⑦ 옮긴 기계 견본 ─────────────────────────────────────────────────
|
||||
def test_moved_samples():
|
||||
plant = mh.hourly("EQ000188") # 아스팔트 믹싱플랜트 60t — 연료 + 조종원 2 인
|
||||
assert plant["로직"] == "GC000268" and plant["노무비"] == int(_wage("1048") * 2 / 8)
|
||||
assert plant["재료비"] > 0
|
||||
tower = mh.hourly("EQ000165") # 타워크레인 — 건설기계운전사 조종원 줄(요구 799)
|
||||
assert tower["로직"] == "GC000276" and tower["노무비"] == int(_wage("1048") / 8)
|
||||
spray = m01.loaded()[1].get("EQ000198") # 아스팔트 스프레어 — 직종 빈 칸 = 직종 입력 식
|
||||
assert mh.pick(spray)["키"] == "GC000275" and "조종원직종" in json.dumps(
|
||||
mh.pick(spray)["입력"], ensure_ascii=False
|
||||
)
|
||||
assert "가격" in mh.hourly("EQ000198")["reason"]
|
||||
assert "3450-0642" not in _codes("GC000273") # 손료만 식에서 뺌
|
||||
for key, logic in (
|
||||
("EQ000529", POWER),
|
||||
("EQ000534", ONE_FUEL),
|
||||
("EQ000532", POWER),
|
||||
("EQ000426", POWER),
|
||||
):
|
||||
h = mh.hourly(key)
|
||||
p = _preview(key)
|
||||
assert h["로직"] == logic and (p["재료비"], p["경비"], p["계"]) == (
|
||||
h["재료비"],
|
||||
h["경비"],
|
||||
h["계"],
|
||||
), key
|
||||
for key in ("EQ000188", "EQ000165"):
|
||||
h, p = mh.hourly(key), _preview(key)
|
||||
assert (p["노무비"], p["재료비"], p["경비"]) == (h["노무비"], h["재료비"], h["경비"]), key
|
||||
|
||||
|
||||
# ⑧ · ⑨ ────────────────────────────────────────────────────────────────
|
||||
def test_unmoved_same_and_name():
|
||||
for key, total in KEEP.items():
|
||||
assert mh.hourly(key)["계"] == total
|
||||
row = _rows()["EQ000534"]
|
||||
assert (row["이름"], row["옛이름"], row["별칭"]) == (
|
||||
"POWER TROWEL",
|
||||
"POWER TLOWEL",
|
||||
"파워트로웰",
|
||||
)
|
||||
@@ -4,7 +4,7 @@
|
||||
* 키보드 — 찾기 칸에서 ↑ ↓ 로 옮기고 Enter 로 고름. 창 겉틀은 부르는 쪽 몫.
|
||||
*
|
||||
* const find = createFindList({ placeholder, filters: [sub.root, detail.root] });
|
||||
* find.setRows([{ key, tag, name, sub, unit, onPick }]);
|
||||
* find.setRows([{ key, tag, name, sub, unit, onPick }]); // 둘째 인자 = 처음 짚을 줄 key(가운데로 보임)
|
||||
* ========================================================================== */
|
||||
|
||||
import "./ui_template_find_list.css";
|
||||
@@ -27,7 +27,8 @@ export interface FindList {
|
||||
root: HTMLElement;
|
||||
search: HTMLInputElement;
|
||||
hint: HTMLElement;
|
||||
setRows: (rows: FindRow[]) => void;
|
||||
/** active = 처음 짚을 줄 key(없으면 첫 줄) — 그 줄이 가운데로 보임 */
|
||||
setRows: (rows: FindRow[], active?: string) => void;
|
||||
}
|
||||
|
||||
export function createFindList(opts: {
|
||||
@@ -42,12 +43,12 @@ export function createFindList(opts: {
|
||||
let rows: FindRow[] = [];
|
||||
let at = -1;
|
||||
|
||||
const mark = (i: number): void => {
|
||||
const mark = (i: number, block: ScrollLogicalPosition = "nearest"): void => {
|
||||
list.children[at]?.classList.remove("is-active");
|
||||
at = i;
|
||||
const row = list.children[at];
|
||||
row?.classList.add("is-active");
|
||||
row?.scrollIntoView({ block: "nearest" });
|
||||
row?.scrollIntoView({ block });
|
||||
};
|
||||
field.input.addEventListener("keydown", (ev) => {
|
||||
if (ev.key === "ArrowDown" || ev.key === "ArrowUp") {
|
||||
@@ -61,7 +62,7 @@ export function createFindList(opts: {
|
||||
}
|
||||
});
|
||||
|
||||
const setRows = (next: FindRow[]): void => {
|
||||
const setRows = (next: FindRow[], active?: string): void => {
|
||||
rows = next;
|
||||
at = -1;
|
||||
list.replaceChildren(
|
||||
@@ -89,7 +90,9 @@ export function createFindList(opts: {
|
||||
return row;
|
||||
}),
|
||||
);
|
||||
if (rows.length) mark(0);
|
||||
const pin = active === undefined ? -1 : rows.findIndex((r) => r.key === active);
|
||||
if (pin >= 0) mark(pin, "center");
|
||||
else if (rows.length) mark(0);
|
||||
};
|
||||
|
||||
const filters = opts.filters?.length
|
||||
|
||||
@@ -40,6 +40,7 @@ export const ui_locales_machine = {
|
||||
"National average · instant · server recalculates on save",
|
||||
],
|
||||
MF_NoPrice: ["단가 없음", "no price"],
|
||||
MF_PickFind: ["글자로 찾기", "Type to filter"],
|
||||
MF_Similar: ["비슷한 기계에서 시작", "Start from a similar machine"],
|
||||
MF_SimilarFind: ["기계 이름 · 규격으로 찾기", "Find by name or spec"],
|
||||
MF_SimilarNone: ["찾은 기계 없음", "No machines found"],
|
||||
@@ -51,6 +52,14 @@ export const ui_locales_machine = {
|
||||
M01_MachineMeta: ["원문 · 구분", "Source · group"],
|
||||
M01_MachineUses: ["쓰는 곳", "Used by"],
|
||||
M01_MachineNoUses: ["쓰는 곳 없음", "Not used"],
|
||||
M01_MachineFormula: ["쓰는 계산식", "Hourly formula"],
|
||||
M01_MachineFormulaListed: ["목록에 있음", "listed"],
|
||||
M01_MachineFormulaShape: [
|
||||
"꼴로 고름(채운 칸) — 저장하면 그 식 목록에 등록",
|
||||
"picked by filled fields — registered on save",
|
||||
],
|
||||
M01_MachineFormulaOwn: ["그 기계만의 식", "machine's own formula"],
|
||||
M01_MachineFormulaNone: ["식 없음", "no formula"],
|
||||
M01_MachineSame: [
|
||||
"같은 이름 · 규격 기계가 있음 — {value}",
|
||||
"A machine with the same name and spec exists — {value}",
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
import { createCalcFormula, createCalcFormulaRow } from "./ui_template_calc_row";
|
||||
import { el, createInputField, createSelectField } from "./ui_template_elements";
|
||||
import { createFindList } from "./ui_template_find_list";
|
||||
import { attachPickSearch } from "./ui_template_pick_search";
|
||||
import { t as L } from "./ui_template_locale";
|
||||
import { createSegment } from "./ui_template_segment";
|
||||
import { createText } from "./ui_template_text";
|
||||
@@ -237,6 +238,7 @@ export function createMachineForm(opts: MachineFormOptions): MachineFormHandle {
|
||||
const field = createSelectField({ label: tr(label), options, value: now, size: 28 });
|
||||
field.select.dataset.key = key;
|
||||
field.select.disabled = Boolean(opts.readOnly);
|
||||
attachPickSearch(field.select, { placeholder: L("MF_PickFind") }); // 항목 많은 고르기(직종) = 찾기 판(801-2)
|
||||
const mark = (): void => {
|
||||
field.root.classList.toggle("is-changed", !same(values[key] ?? null, init[key] ?? null));
|
||||
};
|
||||
@@ -448,11 +450,11 @@ export function createMachineForm(opts: MachineFormOptions): MachineFormHandle {
|
||||
const rows = [
|
||||
line(L("MF_Loss"), `${num("가격")}천원 × 1,000 × ${num("손료계수")} × 10^-7^`, p.손료),
|
||||
line(L("MF_Fuel"), `${num("주연료")}ℓ × ${fmt(fuel)}원`, p.주연료),
|
||||
line(L("MF_Misc"), `${fmt(p.주연료)} × ${num("잡재료율")}%`, p.잡품),
|
||||
line(L("MF_Crew"), `${num("조종원")}인 × ${fmt(wage)}원 × ${fmt(hour)}`, p.조종원),
|
||||
...(values["전력"]
|
||||
? [line(L("MF_Power"), `${num("전력")}kWh × ${fmt(opts.power ?? 0)}원`, p.전력)]
|
||||
: []),
|
||||
line(L("MF_Misc"), `${fmt(p.주연료 + p.전력)} × ${num("잡재료율")}%`, p.잡품),
|
||||
line(L("MF_Crew"), `${num("조종원")}인 × ${fmt(wage)}원 × ${fmt(hour)}`, p.조종원),
|
||||
];
|
||||
side.replaceChildren(
|
||||
...head,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/* 고르기 찾기 판(ui_template_pick_search.ts · 801-2) — 고르기 칸 바로 아래 · 목록 높이 제한 */
|
||||
.ui-pick-search-host {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ui-pick-search .ui-float-panel__body {
|
||||
padding: var(--spacing-8);
|
||||
}
|
||||
|
||||
.ui-pick-search .ui-find__list {
|
||||
max-height: 240px;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* =============================================================================
|
||||
* ui_template_pick_search.ts
|
||||
* 고르기 칸에 찾기 붙이기(요구 801-2) — 항목이 많은 `createSelectField` 고르기를 열면 바로 아래에
|
||||
* 찾기 판(팝오버 `createFloatPanel` + 찾기 목록 `createFindList` · 높이 제한 · 스크롤)이 뜸.
|
||||
* 글자를 치면 이름에 든 것만 · 찾기를 비우면 다시 전부 · 고른 항목이 있으면 그 줄 둘레로 열림
|
||||
* 고름 = select 값 바꿈 + change 알림(부르는 쪽 코드 그대로) · Esc · 바깥 누름 = 닫음
|
||||
* 항목이 적으면(`min` 이하) 아무것도 안 함 — 보통 고르기 그대로
|
||||
* 쓰는 법 = attachPickSearch(field.select, { placeholder: "글자로 찾기" })
|
||||
* ========================================================================== */
|
||||
|
||||
import { createFindList } from "./ui_template_find_list";
|
||||
import { createFloatPanel } from "./ui_template_float_panel";
|
||||
import "./ui_template_pick_search.css";
|
||||
|
||||
const squash = (s: string): string => s.replace(/\s+/g, "").toLowerCase();
|
||||
|
||||
export function attachPickSearch(
|
||||
select: HTMLSelectElement,
|
||||
opts: { placeholder: string; min?: number },
|
||||
): void {
|
||||
if (select.options.length <= (opts.min ?? 12)) return;
|
||||
const host = select.parentElement;
|
||||
if (!host) return;
|
||||
host.classList.add("ui-pick-search-host");
|
||||
let panel: HTMLElement | null = null;
|
||||
|
||||
const close = (): void => {
|
||||
panel?.remove();
|
||||
panel = null;
|
||||
document.removeEventListener("pointerdown", outside, true);
|
||||
};
|
||||
const outside = (ev: PointerEvent): void => {
|
||||
if (panel && !panel.contains(ev.target as Node) && ev.target !== select) close();
|
||||
};
|
||||
|
||||
const open = (): void => {
|
||||
if (panel || select.disabled) return;
|
||||
const fp = createFloatPanel({ popover: true, width: Math.max(select.offsetWidth, 260) });
|
||||
fp.root.classList.add("ui-pick-search");
|
||||
fp.root.style.left = `${select.offsetLeft}px`;
|
||||
fp.root.style.top = `${select.offsetTop + select.offsetHeight + 2}px`;
|
||||
const find = createFindList({ placeholder: opts.placeholder });
|
||||
fp.body.append(find.root);
|
||||
const all = [...select.options].map((o) => ({ value: o.value, text: o.text }));
|
||||
const show = (): void => {
|
||||
const q = squash(find.search.value);
|
||||
const rows = q ? all.filter((o) => squash(o.text).includes(q)) : all;
|
||||
find.setRows(
|
||||
rows.map((o) => ({
|
||||
key: o.value,
|
||||
name: o.text,
|
||||
onPick: () => {
|
||||
select.value = o.value;
|
||||
select.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
close();
|
||||
select.focus();
|
||||
},
|
||||
})),
|
||||
q ? undefined : select.value,
|
||||
);
|
||||
};
|
||||
find.search.addEventListener("input", show);
|
||||
find.search.addEventListener("keydown", (ev) => {
|
||||
if (ev.key === "Escape") {
|
||||
ev.preventDefault();
|
||||
close();
|
||||
select.focus();
|
||||
}
|
||||
});
|
||||
host.append(fp.root);
|
||||
panel = fp.root;
|
||||
show();
|
||||
find.search.focus();
|
||||
document.addEventListener("pointerdown", outside, true);
|
||||
};
|
||||
|
||||
select.addEventListener("mousedown", (ev) => {
|
||||
ev.preventDefault();
|
||||
if (panel) close();
|
||||
else open();
|
||||
});
|
||||
select.addEventListener("keydown", (ev) => {
|
||||
if (["Enter", " ", "ArrowDown"].includes(ev.key)) {
|
||||
ev.preventDefault();
|
||||
open();
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user