- 코드 등록·삭제·변경·병합·데이타병합·일괄변경·검색·동일코드·풀어넣기 끝전 등(ui_code · ui_merge · api_ui_code) - 코드 붙은 % 줄 = 같은 상위 공종 앞 말단 줄 비목 합 × 율(server pct_row_base · calc.js) · 저장 때 다시 셈(stc_save _pct_rows) — 실무 7건 저장값 그대로 - 내역 줄 단가 ≠ 단가목록이면 줄 고정 단가(fixedUnit) - 메뉴 94개 눌러 오류 0 · 시험 502 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
395 lines
21 KiB
JavaScript
395 lines
21 KiB
JavaScript
/**
|
|
* STMATE w 8.0 — 다른 프로젝트 자료 창 끼워 넣기 (scr_ui_merge.js)
|
|
* 프로젝트 DATA검색(wSrch_PL) · 설계예산시스템 코드병합(wM_Stmate_Merge_Code) · 데이타병합(uM_Merge) · 잡비 금액 불러오기(wM_GetAMT)
|
|
* 근거: DFM 원문 — wSrch_PL(wcBx_Type 4택 · 검색결과 내 재검색 · 열: 프로젝트명·코드번호·명칭·규격·단위·분류번호·시설코드·계·노·재·경·
|
|
* 호환규정코드·적용기준일 · 프로젝트 찾아가기) · wM_Stmate_Merge_Code(rg_Set_Sys 4택 · 코드전송시 전송여부 묻기)
|
|
* · uM_Merge(병합기준선택 · 단가목록표 · 병합코드 확인/검토 · 최종확인 신규코드번호부여 · 내역서(Ctrl+N))
|
|
* · wM_GetAMT(공종 추려보기 6택 · 필터 · 복수선택 합산 · 금액전송)
|
|
* 계산 = ui_merge.js · 검색 = /api/ui/search(api_ui_code.py) · 복사원 자료 = /api/load
|
|
*/
|
|
(function (global) {
|
|
"use strict";
|
|
const P = (global.STMATE_PLUGINS = global.STMATE_PLUGINS || {
|
|
screens: {},
|
|
actions: {},
|
|
menus: [],
|
|
});
|
|
const UM = global.STMATE_UI_MERGE;
|
|
const UC = global.STMATE_UI_CODE;
|
|
const B = global.STMATE_UI_BOQ;
|
|
const esc = (s) =>
|
|
String(s == null ? "" : s).replace(
|
|
/[&<>"]/g,
|
|
(c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c],
|
|
);
|
|
const $ = (id) => document.getElementById(id);
|
|
const num = (v) => Number(String(v == null ? "" : v).replace(/,/g, "")) || 0;
|
|
const env = (ctx) => ({
|
|
d: ctx.dbfData,
|
|
state: ctx.state,
|
|
memo: ctx.uiState.editedSmtMap || (ctx.uiState.editedSmtMap = {}),
|
|
});
|
|
const others = (ctx) =>
|
|
(ctx.sourcesData.projects || []).filter((p) => p.path !== ctx.currentSourcePath);
|
|
const prjOpts = (ctx, cur) =>
|
|
others(ctx)
|
|
.map(
|
|
(p) =>
|
|
`<option value="${esc(p.path)}" ${p.path === cur ? "selected" : ""}>${esc(p.name)}</option>`,
|
|
)
|
|
.join("");
|
|
const SRC = {}; // 복사원 자료 — 경로별 한 번
|
|
async function srcData(api, path) {
|
|
if (!SRC[path]) SRC[path] = await api.postJson("/api/load", { source_path: path });
|
|
return SRC[path];
|
|
}
|
|
|
|
// ── 프로젝트 DATA검색 ──
|
|
const TYPES = [
|
|
["LMS", "노무비, 재료비, 경비"],
|
|
["XBD", "중기비, 일위대가, 단가산출"],
|
|
["W", "일식/표준시장"],
|
|
["BOQ", "내역서"],
|
|
];
|
|
function srchHtml(ctx, api) {
|
|
const s = ctx.uiState.srch;
|
|
const rows = s.rows || [];
|
|
const isBoq = s.kind === "BOQ";
|
|
const head = isBoq
|
|
? "<th>No</th><th>프로젝트명</th><th>공종</th><th>명칭</th><th>규격</th><th>수량</th><th>단위</th><th>계금액</th><th>코드</th><th></th>"
|
|
: "<th>No</th><th>프로젝트명</th><th>코드번호</th><th>명칭</th><th>규격</th><th>단위</th><th>분류번호</th><th>시설코드</th><th>계</th><th>노무비</th><th>재료비</th><th>경비</th><th>호환규정코드</th><th>적용기준일</th><th></th>";
|
|
const go = (i) =>
|
|
`<button class="win-btn sp-go" data-i="${i}">찾아가기</button>${isBoq ? "" : `<button class="win-btn sp-get" data-i="${i}">가져오기</button>`}`;
|
|
const body = rows
|
|
.map((r, i) =>
|
|
isBoq
|
|
? `<tr><td class="center">${i + 1}</td><td>${esc(r.project)}</td><td>${esc(r.ITNUM)}</td><td>${esc(r.NAME1)}</td><td>${esc(r.SIZE1)}</td><td class="num">${esc(r.QTY1)}</td><td class="center">${esc(r.UNIT1)}</td><td class="num">${api.fmt(num(r.T_AMT1))}</td><td class="center">${esc(r.BDCODE1)}</td><td>${go(i)}</td></tr>`
|
|
: `<tr><td class="center">${i + 1}</td><td>${esc(r.project)}</td><td class="center">${esc(r.CODE)}</td><td>${esc(r.NAME)}</td><td>${esc(r.SIZE)}</td><td class="center">${esc(r.UNIT)}</td><td>${esc(r.BQCODE)}</td><td>${esc(r.EQCODE)}</td><td class="num">${api.fmt(num(r.TAMT1))}</td><td class="num">${api.fmt(num(r.LAMT1))}</td><td class="num">${api.fmt(num(r.MAMT1))}</td><td class="num">${api.fmt(num(r.SAMT1))}</td><td>${esc(r.JDCODE)}</td><td>${esc(r.EDT_DATE)}</td><td>${go(i)}</td></tr>`,
|
|
)
|
|
.join("");
|
|
return `<div class="stm-form"><div class="stm-row"><select id="sp-kind" class="win-select">${TYPES.map(([k, t]) => `<option value="${k}" ${s.kind === k ? "selected" : ""}>${t}</option>`).join("")}</select>
|
|
<input id="sp-kw" class="win-input" value="${esc(s.kw)}" placeholder="명칭, 규격 (띄어 쓰면 모두 든 것)" style="width:240px;" />
|
|
<label><input type="checkbox" id="sp-re" ${s.re ? "checked" : ""} /> 검색결과 내 재검색</label><button class="win-btn primary" id="sp-go">검 색</button>
|
|
<span class="stm-note">${rows.length}건${s.truncated ? " (앞 500건)" : ""}${s.err ? ` · 못 연 프로젝트 ${s.err}` : ""}</span></div>
|
|
<div class="grid-scroll" style="max-height:60vh;"><table class="dbgrid"><thead><tr>${head}</tr></thead><tbody>${body}</tbody></table></div></div>`;
|
|
}
|
|
function openSrch(ctx, api) {
|
|
const s = (ctx.uiState.srch = ctx.uiState.srch || { kind: "LMS", kw: "", rows: [], re: false });
|
|
api.openModal("프로젝트 DATA검색(명칭, 규격) [wSrch_PL]", srchHtml(ctx, api));
|
|
$("sp-kind").onchange = (e) => (s.kind = e.target.value);
|
|
$("sp-kw").onchange = (e) => (s.kw = e.target.value);
|
|
$("sp-re").onchange = (e) => (s.re = e.target.checked);
|
|
$("sp-go").onclick = async () => {
|
|
s.kw = $("sp-kw").value;
|
|
if (s.re && s.rows.length) {
|
|
const w = s.kw.toLowerCase().split(/\s+/).filter(Boolean);
|
|
const hay = (r) => `${r.NAME || r.NAME1 || ""} ${r.SIZE || r.SIZE1 || ""}`.toLowerCase();
|
|
s.rows = s.rows.filter((r) => w.every((x) => hay(r).includes(x)));
|
|
} else {
|
|
const res = await api.postJson("/api/ui/search", { kind: s.kind, kw: s.kw });
|
|
Object.assign(s, {
|
|
rows: res.rows,
|
|
truncated: res.truncated,
|
|
err: (res.errors || []).length,
|
|
});
|
|
}
|
|
openSrch(ctx, api);
|
|
};
|
|
document.querySelectorAll(".sp-go").forEach(
|
|
(b) =>
|
|
(b.onclick = () => {
|
|
const r = s.rows[Number(b.getAttribute("data-i"))];
|
|
api.closeModal();
|
|
api.loadProjectFromServer(r.path, s.kind === "BOQ" ? "wBoq" : "wM_JabPum").then(() => {
|
|
if (s.kind !== "BOQ")
|
|
ctx.uiState.dan = Object.assign(ctx.uiState.dan || {}, {
|
|
kind: "ALL",
|
|
kw: r.CODE,
|
|
code: r.CODE,
|
|
});
|
|
api.renderWorkspace();
|
|
});
|
|
}),
|
|
);
|
|
document.querySelectorAll(".sp-get").forEach(
|
|
(b) =>
|
|
(b.onclick = () => {
|
|
const r = s.rows[Number(b.getAttribute("data-i"))];
|
|
openMergeCode(ctx, api, { path: r.path, codes: [r.CODE] });
|
|
}),
|
|
);
|
|
}
|
|
|
|
// ── 코드병합 · 데이타병합 ──
|
|
const KINDS = ["L", "M", "S", "B", "X", "D", "W"];
|
|
const POL_KINDS = ["L", "M", "S", "B", "D", "W"];
|
|
function mgHtml(ctx, api, m) {
|
|
const src = m.src;
|
|
const list = src
|
|
? src.costn_rows.filter(
|
|
(r) =>
|
|
UC.codeOf(r)[0] === m.kind &&
|
|
(!m.kw || `${r.CODE} ${r.NAME} ${r.SIZE}`.toLowerCase().includes(m.kw.toLowerCase())),
|
|
)
|
|
: [];
|
|
const tabs = KINDS.map(
|
|
(k) =>
|
|
`<button class="win-btn mg-kind${m.kind === k ? " primary" : ""}" data-k="${k}">${UC.KIND_NAME[k]}</button>`,
|
|
).join("");
|
|
const pol = m.data
|
|
? `<div class="stm-row">${POL_KINDS.map(
|
|
(k) =>
|
|
`<label>${UC.KIND_NAME[k]} <select class="win-select mg-pol" data-k="${k}">${UM.POLICY.map((t, i) => `<option value="${i}" ${Number(m.policy[k] || 0) === i ? "selected" : ""}>${t}</option>`).join("")}</select></label>`,
|
|
).join(" ")}</div>
|
|
<div class="stm-row"><label>동일항목 연결지정 <select id="mg-conn" class="win-select">${["1차:호환,2차:시설,3차:명칭..단위", "1차:호환,2차:명칭+규격+단위", "명칭+규격+단위로 동일항목 검색"].map((t, i) => `<option value="${i}" ${m.conn === i ? "selected" : ""}>${t}</option>`).join("")}${m.byCode ? '<option value="code" selected>코드번호로 인식</option>' : ""}</select></label>
|
|
<label><input type="checkbox" id="mg-bdw" ${m.bdW ? "checked" : ""} /> 대가,산근 → 일식단가(W코드)로 생성</label><label><input type="checkbox" id="mg-xw" ${m.xW ? "checked" : ""} /> 중기비 → 일식단가(W코드)로 생성</label></div>`
|
|
: "";
|
|
const plan = (m.plan || [])
|
|
.map(
|
|
(p) =>
|
|
`<tr><td class="center">${p.src}</td><td class="center">${{ map: "복사처적용", copy: "복사원적용", new: "신규등록", w: "일식단가(W)" }[p.act]}</td><td class="center"><strong>${p.dest}</strong></td><td>${esc((src.costn_rows.find((r) => UC.codeOf(r) === p.src) || {}).NAME)}</td></tr>`,
|
|
)
|
|
.join("");
|
|
return `<div class="stm-form"><div class="stm-row"><label>복사원</label><select id="mg-src" class="win-select" style="max-width:420px;">${prjOpts(ctx, m.path)}</select><button class="win-btn" id="mg-open">불러오기</button><span class="stm-note">복사처 = 지금 프로젝트</span></div>
|
|
${
|
|
src
|
|
? `<div class="stm-row">${tabs}<input id="mg-kw" class="win-input" value="${esc(m.kw || "")}" placeholder="코드·명칭" style="width:140px;" /></div>
|
|
<div class="grid-scroll" style="max-height:30vh;"><table class="dbgrid"><thead><tr><th>선택</th><th>코드</th><th>명칭</th><th>규격</th><th>단위</th><th>계</th><th>호환규정코드</th></tr></thead><tbody>${list
|
|
.map(
|
|
(r) =>
|
|
`<tr><td class="center"><input type="checkbox" class="mg-sel" data-c="${UC.codeOf(r)}" ${m.sel[UC.codeOf(r)] ? "checked" : ""} /></td><td class="center">${UC.codeOf(r)}</td><td>${esc(r.NAME)}</td><td>${esc(r.SIZE)}</td><td class="center">${esc(r.UNIT)}</td><td class="num">${api.fmt(num(r.TAMT1))}</td><td>${esc(r.JDCODE || "")}</td></tr>`,
|
|
)
|
|
.join("")}</tbody></table></div>
|
|
<div class="stm-row"><label>코드병합 내용 선택 <select id="mg-mode" class="win-select">${["선택코드만 병합", "선택코드+하위기초단가코드 병합", "모든코드(하위 산근,대가포함) 병합", "코드병합 취소"].map((t, i) => `<option value="${i}" ${m.mode === i ? "selected" : ""}>${t}</option>`).join("")}</select></label></div>${pol}
|
|
<div class="stm-row"><button class="win-btn" id="mg-check">병합코드 확인/검토</button><button class="win-btn primary" id="mg-ok" ${m.plan ? "" : "disabled"}>확 인(병합)</button><span class="stm-note">※ 단 복사처에 등록되지 않은코드 : 코드번호 생성(병합)</span></div>
|
|
${plan ? `<div class="grid-scroll" style="max-height:24vh;"><table class="dbgrid"><thead><tr><th>복사원코드</th><th>적용방법</th><th>복사처코드</th><th>명칭</th></tr></thead><tbody>${plan}</tbody></table></div>` : ""}`
|
|
: ""
|
|
}</div>`;
|
|
}
|
|
function openMergeCode(ctx, api, o) {
|
|
if (!ctx.dbfData) return alert("열린 프로젝트가 없음");
|
|
const prev = ctx.uiState.mg;
|
|
const m = (ctx.uiState.mg = Object.assign(
|
|
{ kind: "B", sel: {}, mode: 2, conn: 2, policy: {}, data: false, byCode: false },
|
|
prev && !(o && o.reset) ? prev : {},
|
|
o || {},
|
|
));
|
|
if (o && o.codes) o.codes.forEach((c) => ((m.sel[c] = true), (m.kind = c[0])));
|
|
if (o && o.path && (!m.src || m.src.source_path !== o.path))
|
|
return srcData(api, o.path).then(
|
|
(d) => ((m.src = d), (m.path = o.path), openMergeCode(ctx, api)),
|
|
);
|
|
const title = m.data
|
|
? `데이타 병합 【 복사처 <= 복사원 】 [uM_Merge${m.byCode ? " · 코드번호로 인식" : ""}]`
|
|
: "설계예산시스템 코드병합 [wM_Stmate_Merge_Code]";
|
|
api.openModal(title, mgHtml(ctx, api, m));
|
|
const re = () => openMergeCode(ctx, api);
|
|
$("mg-open").onclick = () =>
|
|
openMergeCode(ctx, api, { path: $("mg-src").value, sel: {}, plan: null });
|
|
if (!m.src) return;
|
|
document
|
|
.querySelectorAll(".mg-kind")
|
|
.forEach((b) => (b.onclick = () => ((m.kind = b.getAttribute("data-k")), re())));
|
|
document
|
|
.querySelectorAll(".mg-sel")
|
|
.forEach(
|
|
(i) =>
|
|
(i.onchange = () => ((m.sel[i.getAttribute("data-c")] = i.checked), (m.plan = null))),
|
|
);
|
|
document
|
|
.querySelectorAll(".mg-pol")
|
|
.forEach(
|
|
(s) =>
|
|
(s.onchange = () => (
|
|
(m.policy[s.getAttribute("data-k")] = Number(s.value)),
|
|
(m.plan = null)
|
|
)),
|
|
);
|
|
$("mg-kw").onchange = (e) => ((m.kw = e.target.value), re());
|
|
$("mg-mode").onchange = (e) => ((m.mode = Number(e.target.value)), (m.plan = null));
|
|
if ($("mg-conn"))
|
|
$("mg-conn").onchange = (e) => (
|
|
(m.conn = e.target.value === "code" ? "code" : Number(e.target.value)),
|
|
(m.plan = null)
|
|
);
|
|
if ($("mg-bdw")) $("mg-bdw").onchange = (e) => ((m.bdW = e.target.checked), (m.plan = null));
|
|
if ($("mg-xw")) $("mg-xw").onchange = (e) => ((m.xW = e.target.checked), (m.plan = null));
|
|
$("mg-check").onclick = () => {
|
|
if (m.mode === 3) return ((m.sel = {}), (m.plan = null), re()); // 코드병합 취소
|
|
const codes = Object.keys(m.sel).filter((c) => m.sel[c]);
|
|
if (!codes.length) return alert("병합할 코드를 고르세요");
|
|
m.plan = UM.plan(env(ctx), m.src, {
|
|
codes,
|
|
mode: m.mode,
|
|
conn: m.byCode ? "code" : m.conn,
|
|
policy: m.data ? m.policy : {},
|
|
bdW: m.data && m.bdW,
|
|
xW: m.data && m.xW,
|
|
});
|
|
re();
|
|
};
|
|
$("mg-ok").onclick = () => {
|
|
if (!m.plan) return;
|
|
const res = UM.apply(env(ctx), m.src, m.plan);
|
|
const c = res.count;
|
|
ctx.uiState.danMsg = `병합 — 신규 ${c.new} · 복사원적용 ${c.copy} · 복사처적용 ${c.map} · W ${c.w}${res.unresolved.length ? ` · 못 이은 하위코드 ${res.unresolved.join(",")}` : ""}`;
|
|
Object.assign(m, { plan: null, sel: {} });
|
|
api.closeModal();
|
|
api.cascadeAndRender();
|
|
};
|
|
}
|
|
|
|
// ── 잡비 금액 불러오기 ──
|
|
const LV = [
|
|
" 모두보기",
|
|
" 소 계(+=)",
|
|
" 계(+==)",
|
|
" 합 계(+===)",
|
|
" 총 계(+====)",
|
|
" 총합계(+=====)",
|
|
];
|
|
async function openGetAmt(ctx, api) {
|
|
if (!ctx.dbfData) return alert("열린 프로젝트가 없음");
|
|
const g = (ctx.uiState.getAmt = ctx.uiState.getAmt || { path: "", lv: 0, flt: "", sel: {} });
|
|
const rows = g.path
|
|
? (await srcData(api, g.path)).boq_rows
|
|
: global.STMATE_VIEW_PRJ_BOQ.evaluateFullBoqRows(ctx);
|
|
const words = g.flt.toLowerCase().split(/\s+/).filter(Boolean);
|
|
const list = g.lv
|
|
? B.groupTotals(rows, g.lv).map((x) => ({
|
|
key: `g${x.recno}`,
|
|
it: x.itnum,
|
|
name: x.name,
|
|
size: "",
|
|
qty: "",
|
|
unit: "",
|
|
amt: x.sum.T,
|
|
}))
|
|
: rows
|
|
.filter(B.isLeaf)
|
|
.map((r) => ({
|
|
key: `r${r._recno}`,
|
|
it: r.ITNUM || "",
|
|
name: r.NAME1 || "",
|
|
size: r.SIZE1 || "",
|
|
qty: r.QTY1,
|
|
unit: r.UNIT1 || "",
|
|
amt: num(r.T_AMT1),
|
|
}));
|
|
const shown = list.filter((x) =>
|
|
words.every((w) => `${x.name} ${x.size}`.toLowerCase().includes(w)),
|
|
);
|
|
const sum = list.filter((x) => g.sel[x.key]).reduce((a, x) => a + x.amt, 0);
|
|
const keys = Object.keys((ctx.state.kanjubConfig && ctx.state.kanjubConfig.keys) || {}).filter(
|
|
(k) => /^C_/.test(k),
|
|
);
|
|
api.openModal(
|
|
"잡비 금액 불러오기 [wM_GetAMT]",
|
|
`<div class="stm-form"><div class="stm-row"><select id="ga-prj" class="win-select" style="max-width:380px;"><option value="">(지금 프로젝트)</option>${prjOpts(ctx, g.path)}</select>
|
|
<select id="ga-lv" class="win-select">${LV.map((t, i) => `<option value="${i}" ${g.lv === i ? "selected" : ""}>${t}${i ? " 이상" : ""}</option>`).join("")}</select>
|
|
<input id="ga-flt" class="win-input" value="${esc(g.flt)}" placeholder="필터(명칭, 규격)" style="width:150px;" /></div>
|
|
<div class="grid-scroll" style="max-height:48vh;"><table class="dbgrid"><thead><tr><th></th><th>공종</th><th>명칭</th><th>규격</th><th>수량</th><th>단위</th><th>계금액</th></tr></thead><tbody>${shown
|
|
.map(
|
|
(x) =>
|
|
`<tr><td class="center"><input type="checkbox" class="ga-sel" data-k="${x.key}" ${g.sel[x.key] ? "checked" : ""} /></td><td>${esc(x.it)}</td><td>${esc(x.name)}</td><td>${esc(x.size)}</td><td class="num">${esc(x.qty)}</td><td class="center">${esc(x.unit)}</td><td class="num">${api.fmt(x.amt)}</td></tr>`,
|
|
)
|
|
.join("")}</tbody></table></div>
|
|
<div class="stm-row"><strong>선택 합산 ${api.fmt(sum)}원</strong><label>보낼 잡비 항목(직접입력 금액)</label><select id="ga-key" class="win-select">${keys.map((k) => `<option value="${k}">${k.slice(2)}</option>`).join("")}</select><button class="win-btn primary" id="ga-ok" ${keys.length ? "" : "disabled"}>금액전송</button></div></div>`,
|
|
);
|
|
const re = () => openGetAmt(ctx, api);
|
|
$("ga-prj").onchange = (e) => ((g.path = e.target.value), (g.sel = {}), re());
|
|
$("ga-lv").onchange = (e) => ((g.lv = Number(e.target.value)), (g.sel = {}), re());
|
|
$("ga-flt").onchange = (e) => ((g.flt = e.target.value), re());
|
|
document
|
|
.querySelectorAll(".ga-sel")
|
|
.forEach((i) => (i.onchange = () => ((g.sel[i.getAttribute("data-k")] = i.checked), re())));
|
|
$("ga-ok").onclick = () => {
|
|
const k = $("ga-key").value.slice(2);
|
|
const cfg = ctx.state.kanjubConfig;
|
|
cfg.keys["C_" + k] = Math.trunc(sum);
|
|
cfg.keys["D_" + k] = 1; // 고정(직접입력 금액 사용)
|
|
ctx.uiState.danMsg = `잡비 ${k} ← ${sum}원(금액전송)`;
|
|
api.closeModal();
|
|
api.renderWorkspace();
|
|
};
|
|
}
|
|
|
|
// ── 자료파일 업데이트(wM_Mrg_BSC) — 복사원 = 다른 프로젝트 단가목록(원본 기준자료 BSC 는 암호 자료) ──
|
|
const MKEY = [
|
|
["JD", "호환규정코드"],
|
|
["EQ", "시설코드"],
|
|
["NSU", "명칭/규격/단위"],
|
|
["JNSU", "호환+명+규+단"],
|
|
["NU", "명칭/단위"],
|
|
["", "설정안함"],
|
|
];
|
|
async function openMrgBsc(ctx, api) {
|
|
if (!ctx.dbfData) return alert("열린 프로젝트가 없음");
|
|
const b = (ctx.uiState.mrgBsc = ctx.uiState.mrgBsc || {
|
|
path: "",
|
|
keys: ["JD", "NSU", "NU", "", ""],
|
|
name: 0,
|
|
amt: 1,
|
|
jd: 0,
|
|
});
|
|
const sel = (id, list, cur) =>
|
|
`<select id="${id}" class="win-select">${list.map(([v, t]) => `<option value="${v}" ${String(v) === String(cur) ? "selected" : ""}>${t}</option>`).join("")}</select>`;
|
|
const UPD = [
|
|
[0, "업데이트 안함(복사처적용)"],
|
|
[1, "업데이트 (복사원적용)"],
|
|
];
|
|
api.openModal(
|
|
"자료파일 업데이트 [wM_Mrg_BSC]",
|
|
`<div class="stm-form"><div class="stm-row"><label>복사원</label><select id="mb-src" class="win-select" style="max-width:420px;">${prjOpts(ctx, b.path)}</select></div>
|
|
<div class="stm-row">${[0, 1, 2, 3, 4].map((i) => `<label>${i + 1}차</label>${sel(`mb-k${i}`, MKEY, b.keys[i])}`).join("")}</div>
|
|
<div class="stm-row"><label>명칭</label>${sel("mb-name", UPD, b.name)}<label>단가</label>${sel("mb-amt", UPD, b.amt)}<label>조달코드</label>${sel(
|
|
"mb-jd",
|
|
UPD.concat([
|
|
[2, "복사처 우선적용 업데이트"],
|
|
[3, "복사원 우선적용 업데이트"],
|
|
]),
|
|
b.jd,
|
|
)}</div>
|
|
<p class="stm-note">대상 = 노무·재료·경비·견적(W) · 원본 기준자료(ST_BSC)는 암호 자료라 다른 프로젝트 단가목록을 복사원으로 씀</p>
|
|
<div class="stm-row"><button class="win-btn primary" id="mb-ok">업데이트</button></div></div>`,
|
|
);
|
|
$("mb-ok").onclick = async () => {
|
|
Object.assign(b, {
|
|
path: $("mb-src").value,
|
|
keys: [0, 1, 2, 3, 4].map((i) => $(`mb-k${i}`).value),
|
|
name: Number($("mb-name").value),
|
|
amt: Number($("mb-amt").value),
|
|
jd: Number($("mb-jd").value),
|
|
});
|
|
const src = await srcData(api, b.path);
|
|
const ch = UM.mrgBsc(ctx.dbfData.costn_rows, src.costn_rows, b);
|
|
if (global.STMATE_UI_DAN2)
|
|
global.STMATE_UI_DAN2.syncState(
|
|
ctx,
|
|
ch.filter((x) => x.fields.some((f) => /AMT1$/.test(f))).map((x) => x.code),
|
|
);
|
|
if (ch.some((x) => x.fields.includes("JDCODE"))) ctx.dbfData.ui_dirty = true;
|
|
ctx.uiState.danMsg = `자료파일 업데이트 ${ch.length}건`;
|
|
api.closeModal();
|
|
api.cascadeAndRender();
|
|
};
|
|
}
|
|
|
|
Object.assign(P.actions, {
|
|
Act_UI_MrgBsc: (ctx, api) => openMrgBsc(ctx, api),
|
|
Act_Merge: (ctx, api) => openMergeCode(ctx, api, { data: true, byCode: false, reset: true }),
|
|
Act_Merge_C: (ctx, api) => openMergeCode(ctx, api, { data: true, byCode: true, reset: true }),
|
|
Act_UI_MergeCode: (ctx, api) =>
|
|
openMergeCode(ctx, api, { data: false, byCode: false, reset: true }),
|
|
Act_UI_SrchPL: (ctx, api) => openSrch(ctx, api),
|
|
Act_UI_GetAmt: (ctx, api) => openGetAmt(ctx, api),
|
|
});
|
|
P.menus.push(
|
|
{ menu: "m4", act: "Act_UI_MergeCode", label: "설계예산시스템 코드병합" },
|
|
{ menu: "m4", act: "Act_UI_SrchPL", label: "프로젝트 DATA검색(명칭, 규격)" },
|
|
{ menu: "m3", act: "Act_UI_GetAmt", label: "잡비 금액 불러오기" },
|
|
{ menu: "m2", act: "Act_UI_MrgBsc", label: "단가(명칭,규격, 호환규정코드..) 업데이트" },
|
|
);
|
|
global.STMATE_UI_MERGE_SCR = { openSrch, openMergeCode, openGetAmt, openMrgBsc };
|
|
})(window);
|