/** * 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) => `
${esc(f.cap)}${field(f, d, n)}
`; function render(ctx) { if (!ctx.dbfData) return `
초기값 입력및 수정 [wM_Set_Sys]

열린 프로젝트 없음 — 초기값(Start8x.Ini)은 프로젝트를 연 뒤 고칩니다.

`; 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 `
초기값 입력및 수정 [wM_Set_Sys · Start8x.Ini]바뀐 칸 ${changed.length}개${changed.length ? ` (${esc(changed.join(", "))})` : ""}
※ 수정하기 원하는 항목을 고치세요 ※ ${errs.length ? `${esc(errs.join(" · "))}` : ""}
환 율 / 노 임 계 수
환율 칸 ${d.ARENM === "2" ? "2(변경)" : "1(당초)"} 편집
${S.FIELDS.rate.map((f) => row(f, d)).join("")}
노임환산식 값: ${rxv.ok && rxv.value != null ? rxv.value.toFixed(8) : esc(rxv.error || "-")}
${field({ key: rx.rx, type: "text" }, d)}
${field({ key: rx.con, type: "codes" }, d)}
소 수 점 적 용 기 준${S.FIELDS.digits.map((f) => row(f, d)).join("")}
계 산 방 식${S.FIELDS.calc.map((f) => row(f, d)).join("")}
${d.OPTNM.split( "", ) .map( (c, i) => `${i + 1}. ${S.ORDER_NAMES[c]} `, ) .join( "", )}
재료비 적용단가 일괄적용
${esc(u.sysMsg || "")}

직접수정 판정 = 적용단가가 후보 5칸 어디에도 없음

`; } 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(", ")})`; } function bind(ctx, api) { if (!ctx.dbfData) return; 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);