Files
Aislo/tools/est-test/native-review-auto.js
T
eomsangdonandClaude Opus 5.5 a80101826c feat(est-test): 계약심사 심사평가결과·주요심사내용 자동입력
- 원본 처리 근거대로 설계·심사·절감액·절감율 네 줄과 표별 조정 목록 생성
- 심사 내역 사본에 설계 원가 금액 보존

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:50:58 +09:00

70 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 원본 주요심사내용 창(TfrmInvest) 자동입력 — 심사평가결과(0x10bf3xx)·주요심사내용(0x10bfc98).
// 심사평가결과: 원가계산서에서 이름(빈칸·| 제거)에 「총공사비」가 든 첫 행의 Cost_(설계)·Cost(심사), 절감액 = 심사 − 설계,
// 절감율 = Trunc(절감액 / 설계 × 10000) × 0.01 %(둘 다 0 아닐 때), 숫자는 cp949 바이트 16칸 오른쪽 맞춤, 증액에만 「+」.
// 주요심사내용: 노임·자재·표준시장·견적·기계경비·단가산출·일위대가 차례로 NewItem 행이 있으면
// 「○○ 조정 : 이름(규격) 외N 종」(N = 첫 행을 포함한 전체 개수, 원본 셈 그대로) 한 줄씩.
const EstReviewAuto = (() => {
const num = (value) => Number(value) || 0;
const strip = (text) => String(text ?? "").replace(/[\s|]/g, "");
const bytes = (text) => [...text].reduce((n, ch) => n + (ch.charCodeAt(0) > 0x7f ? 2 : 1), 0);
const right16 = (text) => " ".repeat(Math.max(0, 16 - bytes(text))) + text;
const fmt = (value) =>
Number(value).toLocaleString("en-US", { maximumFractionDigits: 9, useGrouping: true });
function result(project) {
const row = (project.tables.Wonga || []).find((r) => strip(r.Name).includes("총공사비"));
if (!row) return null;
const design = num(row.Cost_),
review = num(row.Cost),
d = review - design,
sign = d > 0 ? "+" : "";
const lines = [
`o 설계금액 : ${right16(fmt(design))} 원`,
`o 심사금액 : ${right16(fmt(review))} 원`,
`o 절 감 액 : ${right16(sign + fmt(d))} 원`,
];
if (d && design) {
const r = Math.trunc((d / design) * 10000) * 0.01;
lines.push(`o 절 감 율 : ${right16(sign + fmt(Number(r.toFixed(2))))} %`);
}
return lines.join("\n");
}
const tables = [
["LaborcDat", "노임단가", false],
["StuffcDat", "자재단가", true],
["SilJukDat", "표준시장단가", true],
["EstiMateDat", "견적단가", true],
["MachTitleDat", "기계경비", true],
["CostTitleDat", "단가산출", true],
["HeadTitleDat", "일위대가", true],
];
function content(project) {
return tables
.map(([table, label, size]) => {
const rows = (project.tables[table] || []).filter((r) => r.NewItem);
if (!rows.length) return "";
const first = rows[0];
return `${label} 조정 : ${strip(first.Name)}${size ? `(${strip(first.Size)})` : ""} 외${rows.length} 종`;
})
.filter(Boolean)
.join("\n");
}
function handle(name, state) {
if (name !== "review-auto-result" && name !== "review-auto-content") return false;
const key = name === "review-auto-result" ? "173-result" : "173",
text = name === "review-auto-result" ? result(state.project) : content(state.project);
if (text == null) throw Error("원가계산서에 총공사비 행이 없습니다.");
const old = state.project.documents?.[key];
if (old && !confirm("기존 내용을 지우고 자동입력하시겠습니까?")) return true;
EstApp.change((project) => {
project.documents ||= {};
project.documents[key] = text;
}, false);
return true;
}
return { result, content, handle };
})();