// 원본 동원인원·자재·장비 「확인」·「내역서」 탭(TfrmDongWon Button1~4 — spec_part §4): 동원 계산이 펼친 중간 결과 보기. // 장비·단산·일위 = 호표마다 1 단위를 동원 항목으로 펼쳐 금액 합을 내고, 호표 금액(TC)과 10원 넘게 어긋나면 표시(1095cdc // Checked := |TC − Trunc(Σ Cost)| > 10). 행을 고르면 당초값(호표 TC·NC·GC·JC)과 계산값(항목 금액을 노무·재료·경비·실적으로 // 나눠 더한 값)·항목 목록. 내역서 = 내역 줄마다 펼친 항목(점검 없음). 웹 동원 계산은 기계경비를 더 쪼개지 않아 장비는 늘 맞음. const EstDongwonCheck = (() => { const num = (v) => Number(v) || 0; const TITLE = { 103: "HeadTitleDat", 104: "CostTitleDat", 105: "MachTitleDat" }; const KIND = { 5: "자재", 6: "노임", 21: "표준", 101: "견적", 105: "기계" }; // 항목 → 비목: 노임·노무비 금액분 = 노무, 자재·견적·재료비 금액분 = 재료, 기계·경비 = 경비, 표준 = 실적 const part = (item) => item.Code === "LZZZZZZZZZZ" || item.kind === 6 ? "NC" : item.Code === "EZZZZZZZZZZ" || item.kind === 105 ? "JC" : item.Code === "SZZZZZZZZZZ" || item.kind === 21 ? "SC" : "GC"; function check(project, kind) { const titles = (project.tables[TITLE[kind]] || []).filter((t) => t.Code); const out = EstResources.calculate( project, true, titles.map((t) => ({ kind, code: t.Code, WorkCode: t.Code, WorkName: t.Name })), ); const items = new Map(); for (const row of out.rows) (items.get(row.WorkCode) || items.set(row.WorkCode, []).get(row.WorkCode)).push(row); return { errors: out.errors, rows: titles.map((t) => { const list = items.get(t.Code) || [], sum = list.reduce((s, r) => s + num(r.amount), 0), calc = { NC: 0, GC: 0, JC: 0, SC: 0 }; for (const r of list) calc[part(r)] += num(r.amount); return { Code: t.Code, Name: t.Name, Size: t.Size, TC: num(t.TC), NC: num(t.NC), GC: num(t.GC), JC: num(t.JC), sum, calc, checked: Math.abs(num(t.TC) - Math.trunc(sum)) > 10, items: list, }; }), }; } function estimate(project) { const out = EstResources.calculate(project, true), groups = new Map(); for (const row of out.rows) { const key = `${row.WorkCode}\u0000${row.WorkName}`; if (!groups.has(key)) groups.set(key, { Code: row.WorkCode, Name: row.WorkName, items: [] }); groups.get(key).items.push(row); } return { errors: out.errors, rows: [...groups.values()] }; } let shown = null; function draw(state) { const { esc, number } = EstApp, { kind, data, pick, only } = shown; const list = data.rows.map((r, i) => [r, i]).filter(([r]) => !only || r.checked); const chosen = data.rows[pick]; const head = kind === "est" ? "코드공종항목 수" : "코드품명규격호표 금액항목 합어긋남"; const body = list .map(([r, i]) => kind === "est" ? `${esc(r.Code)}${esc(r.Name)}${r.items.length}` : `${esc(r.Code)}${esc(r.Name)}${esc(r.Size ?? "")}${number(r.TC)}${number(Math.trunc(r.sum))}${r.checked ? "✔" : ""}`, ) .join(""); const detail = chosen ? (kind === "est" ? "" : `

당초값 계 ${number(chosen.TC)} · 노무 ${number(chosen.NC)} · 재료 ${number(chosen.GC)} · 경비 ${number(chosen.JC)}
계산값 계 ${number(Math.trunc(chosen.sum))} · 노무 ${number(Math.trunc(chosen.calc.NC))} · 재료 ${number(Math.trunc(chosen.calc.GC))} · 경비 ${number(Math.trunc(chosen.calc.JC))}${chosen.calc.SC ? ` · 실적 ${number(Math.trunc(chosen.calc.SC))}` : ""}

`) + `${chosen.items.map((r) => ``).join("")}
종류코드품명규격소요량금액
${esc(KIND[r.kind] || r.kind)}${esc(r.Code)}${esc(r.Name)}${esc(r.Size ?? "")}${number(r.quantity)}${number(r.amount)}
` : "

위에서 행을 고르세요.

"; const title = { 105: "확인 — 장비", 104: "확인 — 단산", 103: "확인 — 일위", est: "내역서" }[ kind ]; EstApp.showDialog( `동원인원,자재,장비 · ${title}`, `${kind === "est" ? "" : ``} ${data.rows.length}건
${head}${body}
${detail}
${data.errors.length ? `

${esc(data.errors.slice(0, 5).join(" / "))}

` : ""}`, ); } function install() { document.addEventListener("click", (event) => { const tr = event.target.closest?.("[data-dw-pick]"); if (!tr || !shown) return; shown.pick = Number(tr.dataset.dwPick); draw(EstApp.state); }); document.addEventListener("change", (event) => { if (event.target.dataset?.dwOnly === undefined || !shown) return; shown.only = event.target.checked; draw(EstApp.state); }); } if (typeof document !== "undefined" && document.addEventListener) install(); function handle(name, state, node) { if (name !== "dongwon-check") return false; const kind = node.dataset.kind === "est" ? "est" : Number(node.dataset.kind); shown = { kind, data: kind === "est" ? estimate(state.project) : check(state.project, kind), pick: -1, only: false, }; draw(state); return true; } return { check, estimate, handle }; })();