/**
* STMATE w 8.0 — 초기값 입력및 수정 화면(wM_Set_Sys) 끼워 넣기 (scr_ui_sys.js)
* 배치 근거: resource-TWM_SET_SYS.dfm.json — 환율/노임계수 · 소수점 적용기준 · 계산방식 · 금액 보정순서
* · 단가의 조사시점 · 재료비 적용단가 일괄적용 · 공사원가호환규정(XML) 계산방식 일괄적용
* 편집 = ctx.uiState.sysDraft(초안) → [전체 재계산후 종료]·[작업 종료] 때 dbfData.start_ini 와 state.sysConfig 에 반영
*/
(function (global) {
"use strict";
const P = (global.STMATE_PLUGINS = global.STMATE_PLUGINS || {
screens: {},
actions: {},
menus: [],
});
const S = global.STMATE_UI_SYS;
const U = global.STMATE_UI_DAN;
const esc = (s) =>
String(s == null ? "" : s).replace(
/[&<>"]/g,
(c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c],
);
function draft(ctx) {
const u = ctx.uiState;
const ini = ctx.dbfData.start_ini || (ctx.dbfData.start_ini = {});
if (!u.sysDraft || u.sysDraftSrc !== ctx.currentSourcePath) {
u.sysDraft = S.draftFromIni(ini);
u.sysDraftSrc = ctx.currentSourcePath;
u.sysRx = u.sysRx || "T";
}
return u.sysDraft;
}
function field(f, d, n) {
const k = S.keyOf(f, n || d.ARENM);
const v = d[k] == null ? "" : d[k];
const title = f.hint ? ` title="${esc(f.hint)}"` : "";
if (f.type === "sel")
return ``;
if (f.type === "codes")
return ``;
return ``;
}
const row = (f, d, n) =>
`
${field(f, d, n)}
`;
function render(ctx) {
if (!ctx.dbfData)
return ``;
const d = draft(ctx),
u = ctx.uiState,
ini = ctx.dbfData.start_ini;
const changed = S.applyDraft(Object.assign({}, ini), d);
const rx = S.RX_SETS.find((s) => s.id === u.sysRx) || S.RX_SETS[0];
const rxv = S.checkFormula(d.RXXNM);
const slots = U.slotNames(ini);
const errs = S.validate(d);
return ``;
}
function commit(ctx, api, recalc) {
const d = draft(ctx);
const errs = S.validate(d);
if (errs.length) return alert("고칠 칸: " + errs.join(" · "));
const changed = S.applyDraft(ctx.dbfData.start_ini, d);
ctx.state.sysConfig = S.sysConfigFromIni(ctx.dbfData.start_ini, ctx.state.sysConfig);
ctx.uiState.sysDraft = null;
ctx.uiState.sysMsg = "";
ctx.uiState.activeScreen = "wPrjList";
if (recalc) api.cascadeAndRender();
else api.renderWorkspace();
if (changed.length)
ctx.uiState.boqMsg = `초기값 ${changed.length}칸 반영(${changed.join(", ")})`;
}
// 직종·노임 설정(wM_Set_JLab) — 노무비 코드 목록에서 고른 코드를 적용코드 목록으로(추가·삭제) · 적용단가 미리보기
function openJLab(ctx, api, conKey, orig) {
const d = draft(ctx),
$ = (id) => document.getElementById(id);
const ev = global.STMATE_SMT_EVAL;
const hourly = ev && ev.hourlyWage;
const ini = Object.assign({}, ctx.dbfData.start_ini, d);
const j = S.jlab(ctx.dbfData.costn_rows, ini, conKey, hourly);
const fmt = api.fmt;
const tr = (r, cls) =>
` | ${esc(r.code)} | ${esc(r.name)} | ${esc(r.size)} | ${esc(r.unit)} | ${cls === "jl-del" ? `${r.hourly == null ? "" : fmt(r.hourly)} | ` : ""}${fmt(r.price)} |
`;
api.openModal(
`시간당 노임산출계수 적용코드 [wM_Set_JLab] — ${conKey} · 환산식 ${j.formula || "(없음)"}`,
``,
);
let cur = String(d[conKey] != null ? d[conKey] : ini[conKey] || "");
const back = orig == null ? cur : orig;
const picked = (cls) => [...document.querySelectorAll(`.${cls}:checked`)].map((x) => x.value);
const apply = (next) => (
(d[conKey] = next),
api.closeModal(),
openJLab(ctx, api, conKey, back)
);
$("jl-add").onclick = () => apply((cur = S.jlabEdit(cur, picked("jl-add"), [])));
$("jl-del").onclick = () => apply((cur = S.jlabEdit(cur, [], picked("jl-del"))));
$("jl-ok").onclick = () => (api.closeModal(), api.renderWorkspace());
$("jl-cancel").onclick = () => ((d[conKey] = back), api.closeModal(), api.renderWorkspace());
}
function bind(ctx, api) {
if (!ctx.dbfData) return;
document
.querySelectorAll("#sys-form .sys-jlab")
.forEach((b) => (b.onclick = () => openJLab(ctx, api, b.getAttribute("data-k"))));
const d = draft(ctx),
u = ctx.uiState,
$ = (id) => document.getElementById(id);
document.querySelectorAll("#sys-form .sys-f").forEach(
(el) =>
(el.onchange = () => {
const k = el.getAttribute("data-k");
d[k] = /^CON/.test(k)
? S.joinCodes(String(el.value).split(/[,\s]+/))
: String(el.value).trim();
api.renderWorkspace();
}),
);
$("sys-rx-sel").onchange = (e) => ((u.sysRx = e.target.value), api.renderWorkspace());
document
.querySelectorAll("#sys-form .sys-opt")
.forEach(
(b) =>
(b.onclick = () => (
(d.OPTNM = S.moveOrder(
d.OPTNM,
Number(b.getAttribute("data-i")),
Number(b.getAttribute("data-dir")),
)),
api.renderWorkspace()
)),
);
$("sys-opt-df").onclick = () => ((d.OPTNM = "SML"), api.renderWorkspace());
$("sys-xml").onclick = () => (S.xmlPreset(d), api.renderWorkspace());
$("sys-cancel").onclick = () => ((u.sysDraft = null), api.renderWorkspace());
$("sys-recalc").onclick = () => commit(ctx, api, true);
$("sys-close").onclick = () => commit(ctx, api, false);
$("sys-selm-ok").onclick = () => {
const how = $("sys-selm").value;
if (how === "none") return;
const ch = U.adoptAll(ctx.dbfData.costn_rows, how, {
kinds: "M",
skipZero: $("sys-skip0").checked,
keepUser: $("sys-keep").checked,
});
ch.forEach((c) => {
const res = (ctx.state.resources || []).find((r) => r.code === c.code);
if (res) Object.assign(res, { adoptMode: `slot${c.slot}`, manualPrice: c.to });
});
u.sysMsg = `재료비 ${ch.length}건 적용단가 바꿈`;
api.cascadeAndRender();
};
}
P.screens.wM_Set_Sys = { render, bind };
})(window);