/* -*- coding: utf-8 -*- */ /** * 자재 후보단가 채택 (scr_edit_price.js) — 가격지 1~5단가(AMT_1n~AMT_5n) 중 최소단가 자동채택 · 지정 단가 · * 보호표시(UC=T) 수동 고정 우선 · 0원 후보 제외 * 근거: 지식DB STmate/old/20_분석 17 §5.5(최저가 채택) · 22 §3.1(보호표시·0원 수정 안 됨) · * ui_form_catalog wM_Boxa RG_MComp(변동없음 · 1~5 단가 · 최소단가) · 13 T10(수동값 우선) */ (function (global) { "use strict"; const num = (v) => Number(v) || 0; /** * rows = COSTN 행 · opts { slot: 차수 1~4, mode: "min" | 1~5 | "keep", kinds: "M" } * 돌려줌 { changed: [{code, from, to, src}], kept: [보호표시 코드] } · rows 는 그대로(적용은 부르는 쪽) */ function adoptCandidates(rows, opts = {}) { const slot = Number(opts.slot) || 1, mode = opts.mode ?? "min", kinds = opts.kinds || "M"; const changed = [], kept = []; if (mode === "keep") return { changed, kept }; for (const r of rows || []) { const code = String(r.CODE || "").trim(); if (!code || !kinds.includes(code[0])) continue; const cand = [1, 2, 3, 4, 5].map((i) => num(r[`AMT_${i}${slot}`])); let to = null, src = 0; if (mode === "min") { cand.forEach((v, i) => v > 0 && (to === null || v < to) && ((to = v), (src = i + 1))); } else if (cand[Number(mode) - 1] > 0) [to, src] = [cand[Number(mode) - 1], Number(mode)]; if (to === null) continue; if (String(r.UC || "").trim() === "T") { kept.push(code); continue; } const from = num(r[`MAMT${slot}`]); if (from !== to) changed.push({ code, from, to, src }); } return { changed, kept }; } const api = { adoptCandidates }; global.STMATE_PRICE_ADOPT = api; if (typeof module !== "undefined" && module.exports) module.exports = api; // 화면 — 단가표 메뉴에 「자재 후보단가 채택」 창 if (typeof document === "undefined") return; const P = (global.STMATE_PLUGINS = global.STMATE_PLUGINS || { screens: {}, actions: {}, menus: [], }); P.actions.Act_Qty_AdoptPrice = (ctx, app) => { if (!ctx.dbfData) return alert("먼저 프로젝트를 여세요."); const opts = [ "min:최소단가(0원 제외)", "1:1 단가", "2:2 단가", "3:3 단가", "4:4 단가", "5:5 단가", "keep:변동없음", ]; app.openModal( "자재 후보단가 채택 (wM_Boxa RG_MComp)", `
가격지 1~5단가 중 고른 단가를 재료비 적용단가로 · 보호표시(UC=T) 자재는 수동값 그대로 · 0원 후보는 제외