// 「조달청 표준공사코드 적용」 대화 화면 — 왼쪽 조달청 목록(불러온 PPS 표) · 오른쪽 작업데이타 7종 탭. 계산은 native-code-change.js. const EstCodeChangeView = (() => { const PAGE = 100, COLORS = { 1: "#fff59d", 2: "#f8d7e0", 3: "#ffcc80" }; const C = () => EstCodeChange; function open(state, tag) { const view = state.view, guess = { HeadMainDat: 103, CostMainDat: 104, MachMainDat: 105, SilJukDat: 21, EstiMateDat: 101, StuffcDat: 5, LaborcDat: 6, }[view]; const cc = (state.codeChange ||= { pps: {}, word: "", rowWord: "", autoMove: true, nameChange: false, }); cc.tag = tag ?? cc.tag ?? guess ?? 6; cc.rows = C().load(state.project, cc.tag); C().validate(state.project, cc.tag, cc.rows); cc.sel = cc.rows.length ? 0 : undefined; cc.page = 0; cc.dirty = false; cc.pick = undefined; draw(state); } function ppsKind(tag) { return [21, 103, 104].includes(tag) ? "HEAD" : "STUFFC"; } function shownRows(cc) { const w = String(cc.rowWord || "").replace(/[\s|()]/g, ""); return cc.rows .map((r, i) => ({ r, i })) .filter( ({ r }) => !w || (cc.rowMode === "name" ? `${r.Name}${r.Size}`.replace(/[\s|()]/g, "").includes(w) : String(r.OldCode) .replace(/[\s|()]/g, "") .includes(w)), ); } function draw(state) { const { esc } = EstApp, cc = state.codeChange, C2 = C(), list = cc.pps[ppsKind(cc.tag)] || [], found = C2.search(list, cc.word).slice(0, PAGE), rows = shownRows(cc), pages = Math.max(1, Math.ceil(rows.length / PAGE)), page = Math.min(cc.page, pages - 1); const tabs = C2.ORDER.map( (t) => ``, ).join(""); const left = `
조달청코드 목록 (${ppsKind(cc.tag) === "HEAD" ? "단산·일위·표준 = PPS_HEAD" : "노임·자재·장비·견적 = PPS_STUFFC"})
${list.length ? `${found.length}/${list.length}` : "목록 없음 — 원본 System\\MainSys 의 PPS_*.dat 를 고르세요"}
${found .map( (x, i) => ``, ) .join("")}
코드명칭규격단위
${esc(x.Code)}${esc(x.Name)}${esc(x.Size)}${esc(x.Unit)}
`; const body = rows .slice(page * PAGE, page * PAGE + PAGE) .map( ({ r, i }) => `${[ ``, esc(r.Index ?? ""), esc(r.OldCode), ``, esc(r.Name), esc(r.Size), esc(r.Unite), esc(r.Bigo), ] .map((v) => `${v}`) .join("")}`, ) .join(""); const user = cc.pick ? safeUser(state) : ""; const right = `
${tabs}
${rows.length}행 · ${page + 1}/${pages}
${body}
No당초코드변경코드명칭규격단위비고

*조달청호환 코드로 미변경(노랑), 중복코드(연분홍 비고란 참조), 코드자리수틀림(진황색)*

`; const tools = [ ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, ].join(" "); EstApp.showDialog( `조달청 표준공사코드 적용 — ${C2.NAMES[cc.tag]}`, `${cc.message ? `

${esc(cc.message)}

` : ""}
${left}${right}
${tools}
`, ); cc.message = ""; } function safeUser(state) { const cc = state.codeChange; if (!cc.pick || [21, 105, 101].includes(cc.tag)) return ""; try { return C().userCode(state.project, cc.tag, cc.rows, cc.pick.Code); } catch { return ""; } } async function run(name, state, node) { const cc = state.codeChange; if (name === "code-change") return open(state); if (!cc) return; const C2 = C(); if (name === "code-change-tab") { if (cc.dirty && confirm(`변경된 ${C2.NAMES[cc.tag]} 의 코드를 내역서 전체에 적용할까요?`)) applyNow(state); return open(state, Number(node.dataset.tag)); } if (name === "code-change-search") cc.word = document.querySelector("[data-cc-word]")?.value ?? ""; else if (name === "code-change-all") cc.word = ""; else if (name === "code-change-rowsearch") { cc.rowWord = document.querySelector("[data-cc-rowword]")?.value ?? ""; cc.rowMode = document.querySelector("[data-cc-rowmode]")?.value; cc.page = 0; } else if (name === "code-change-page") cc.page = Math.max(0, cc.page + Number(node.dataset.step)); else if (name === "code-change-input" || name === "code-change-user") { if (!cc.pick) throw Error("조달청코드 목록에서 코드를 고르세요."); const code = name === "code-change-user" ? safeUser(state) : cc.pick.Code; C2.input( state.project, cc.tag, cc.rows, cc.sel, code, name === "code-change-input" && cc.nameChange ? { ...cc.pick, nameChange: true } : null, ); cc.dirty = true; if (cc.autoMove && cc.sel < cc.rows.length - 1) cc.sel++; } else if (name === "code-change-cancel") C2.cancel(cc.rows, cc.sel); else if (name === "code-change-auto") { C2.auto(cc.rows); cc.dirty = true; } else if (name === "code-change-dasan") { if (!confirm("코드를 일련번호로 새로 부여하시겠습니까?")) return; C2.dasan(cc.rows, cc.tag); cc.dirty = true; } else if (name === "code-change-bulk") return pickEstx(state); else if (name === "code-change-apply") { if (!confirm(`변경된 ${C2.NAMES[cc.tag]} 의 코드를 내역서 전체에 적용할까요?`)) return; applyNow(state); } else if (name === "code-change-close") { if ( cc.dirty && !confirm("내역서에 변경된 코드를 적용하지 않았습니다.코드변경작업을 종료하시겠습니까?") ) return; EstApp.byId("dialog").close(); state.codeChange = { ...cc, rows: [], dirty: false }; return; } draw(state); } function applyNow(state) { const cc = state.codeChange, C2 = C(); if ( C2.validate(state.project, cc.tag, cc.rows) && !confirm("조달청코드로 변경안된 데이타가 있습니다.그래도 적용하시겠습니까??") ) return; let count = 0; EstApp.change((project) => (count = C2.apply(project, cc.tag, cc.rows))); cc.dirty = false; state.notice = `${C2.NAMES[cc.tag]}의 코드변경이 완료 되었습니다. (${count}행)`; } function pickEstx(state) { const cc = state.codeChange, picker = document.createElement("input"); picker.type = "file"; picker.accept = ".estx"; picker.addEventListener("change", async () => { try { const file = picker.files[0]; if (!file) return; if ( !confirm( `현재 작업데이타의 ${C().NAMES[cc.tag]} 코드를 "${file.name}"의 코드로 변경하시겠습니까?`, ) ) return; const source = await EstApp.api(`/api/import?name=${encodeURIComponent(file.name)}`, { method: "POST", body: file, }); const n = C().bulk(state.project, cc.tag, cc.rows, source); if (n) cc.dirty = true; cc.message = n ? `${n}개 코드를 바꿨습니다. 적용을 누르세요.` : "코드가 변경된 항목이 없습니다."; } catch (error) { cc.message = error.message; } draw(state); }); picker.click(); } function install() { document.addEventListener("change", async (event) => { const t = event.target, state = EstApp.state, cc = state.codeChange; if (!cc?.rows) return; try { if (t.dataset.ccRow !== undefined) cc.sel = Number(t.dataset.ccRow); else if (t.dataset.ccPick !== undefined) cc.pick = EstCodeChange.search(cc.pps[ppsKind(cc.tag)] || [], cc.word)[ Number(t.dataset.ccPick) ]; else if (t.dataset.ccOpt !== undefined) cc[t.dataset.ccOpt] = t.checked; else if (t.dataset.ccCode !== undefined) { const i = Number(t.dataset.ccCode); C().input(state.project, cc.tag, cc.rows, i, t.value); cc.dirty = true; } else if (t.dataset.ccPps !== undefined) { const file = t.files[0]; if (!file) return; const rows = await EstApp.api("/api/pps-table", { method: "POST", body: file }); const kind = rows.some((r) => /공사$/.test(r.Gubun ?? "")) ? "HEAD" : "STUFFC"; cc.pps[kind] = rows; cc.message = `조달청 ${kind === "HEAD" ? "공종" : "물품"} 코드 ${rows.length}개를 불러왔습니다.`; } else return; } catch (error) { cc.message = error.message; } draw(state); }); } const names = new Set([ "code-change", "code-change-tab", "code-change-search", "code-change-all", "code-change-rowsearch", "code-change-page", "code-change-input", "code-change-user", "code-change-cancel", "code-change-auto", "code-change-dasan", "code-change-bulk", "code-change-apply", "code-change-close", ]); function handle(name, state, node) { if (!names.has(name)) return false; run(name, state, node).catch((error) => { if (!state.codeChange?.rows) return void (state.notice = error.message); state.codeChange.message = error.message; draw(state); }); return true; } if (typeof document !== "undefined" && document.addEventListener) install(); return { open, handle }; })();