/** * STMATE w 8.0 — 단가 성분 검사 (ui_code_check.js) · 화면·DOM 없음(node 시험 가능) * 근거: 지식DB STmate/old/20_분석 10 §3(검증 조건식 `TAMT1 <> MAMT1 + LAMT1 + SAMT1` 세 모듈 · TAMT = 총계) * · 코드종류별 성분 — L → LAMT = TAMT · M → MAMT = TAMT · S → SAMT = TAMT · 복합/W → TAMT = M + L + S * 차수 칸 1~4 마다 · 내역(BOQ) 단가코드 행은 단가 칸(TAMTn)과 금액 칸(T_AMTn) 둘 다 */ (function (global) { "use strict"; const txt = (v) => String(v == null ? "" : v).trim(); const num = (v) => { const n = parseFloat(txt(v).replace(/,/g, "")); return Number.isFinite(n) ? n : 0; }; const OWN = { M: "M", L: "L", S: "S" }; const STRUCT = /^(T\d|E\d|C\d|:)$/; const near = (a, b) => Math.abs(a - b) < 1e-6; // 한 칸 무리 검사 — pre(단가 "" · 금액 "_") function checkSlot(r, code, s, pre, where) { const out = []; const f = (k) => `${k}${pre}AMT${s}`; if (!(f("T") in r)) return out; const v = { M: num(r[f("M")]), L: num(r[f("L")]), S: num(r[f("S")]), T: num(r[f("T")]) }; if (!near(v.T, v.M + v.L + v.S)) out.push({ where, code, slot: s, rule: "sum", msg: `${f("T")} ≠ 재+노+경`, v }); const own = OWN[code[0]]; if (own && ["M", "L", "S"].some((k) => k !== own && v[k] !== 0)) out.push({ where, code, slot: s, rule: "own", msg: `${own} 코드에 다른 비목 금액`, v }); return out; } /** COSTN 행 — 차수 칸 1~4 · [{ where, code, slot, rule: sum|own, msg, v }] */ function checkComponents(rows) { const out = []; for (const r of rows || []) { const c = txt(r.CODE).toUpperCase(); if (!c) continue; for (const s of [1, 2, 3, 4]) out.push(...checkSlot(r, c, s, "", "COSTN")); } return out; } /** 내역 단가코드 행 — 단가(TAMTn) · 금액(T_AMTn) · % 줄은 금액 칸만 */ function checkBoq(rows) { const out = []; for (const r of rows || []) { const c = txt(r.BDCODE1).toUpperCase(); if (!c || STRUCT.test(c)) continue; const pct = txt(r.UNIT1).endsWith("%"); for (const s of [1, 2, 3, 4]) { if (!pct) out.push(...checkSlot(r, c, s, "", `BOQ#${r._recno}`)); out.push(...checkSlot(r, c, s, "_", `BOQ#${r._recno}`)); } } return out; } const api = { checkComponents, checkBoq }; global.STMATE_UI_CODE_CHECK = api; if (typeof module !== "undefined" && module.exports) module.exports = api; })(typeof window !== "undefined" ? window : globalThis);