Files
Aislo/tools/est-test/native-jungsang.js
T
eomsangdonandClaude Opus 5.5 8c3a3d4267 feat(est-test): 정산원가계산서 작성과 당초금액 초기화
- 원본 처리 근거대로 당초금액 복사, 도급액 고정 연결 해제, (감)/(증) 차액 행
- 작성/해제 토글과 원가 화면 당초금액·정산금액 열, 재계산마다 차액 갱신

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 19:29:23 +09:00

83 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.
// 원본 정산원가계산서(TfrmWongaBase popJunSangCalc 0xd0eb28 → 0xd0f6fc, popJungSangShow 0xd0ea24, 재계산 0xca31c8).
// 당초금액 초기화: 원가 행마다 SC(당초금액) := Cost, LinkIndex 55 → 0, 초기화 표지(JungSangInit), 차액 행 기록.
// 정산원가계산서 작성/해제: JungSangShow 토글 — 켤 때 초기화 전이면 확인 없이 초기화, 끌 때 차액 행(66)만 비움(SC 유지).
// 켜져 있는 동안 재계산마다 차액 행을 다시 쓴다. 차액 d = 마지막 금액 행의 SC − Cost, d>0 「(감)」·d<0 「(증)」.
const EstJungSang = (() => {
const num = (value) => Number(value) || 0;
const blank = (row) => !String(row.Name ?? "").trim() && !num(row.Cost) && !row.VSusic;
function difference(rows) {
let last = -1;
rows.forEach((row, i) => {
if (num(row.LinkIndex) !== 66 && String(row.Name ?? "").trim() && num(row.Cost)) last = i;
});
const d = last < 0 ? 0 : num(rows[last].SC) - num(rows[last].Cost);
const text = d > 0 ? `(감)${Math.abs(d)}` : d < 0 ? `(증)${Math.abs(d)}` : "0";
let at = rows.findIndex((row) => num(row.LinkIndex) === 66);
if (at < 0) {
for (let i = rows.length - 1; i >= 0 && blank(rows[i]); i--) at = i;
}
if (at < 0) {
rows.push({});
at = rows.length - 1;
}
Object.assign(rows[at], {
EndLineIndex: 1,
Name: ".",
VGungu: text,
VSusic: text,
LinkIndex: 66,
});
return text;
}
function init(project) {
const rows = project.tables.Wonga || [];
for (const row of rows) {
row.SC = num(row.Cost);
if (num(row.LinkIndex) === 55) row.LinkIndex = 0;
}
project.options.JungSangInit = 1;
return difference(rows);
}
function clear(project) {
const row = (project.tables.Wonga || []).find((r) => num(r.LinkIndex) === 66);
if (row) Object.assign(row, { Name: "", VGungu: "", VSusic: "", LinkIndex: 0 });
}
function toggle(project) {
project.options.JungSangShow = !project.options.JungSangShow;
if (project.options.JungSangShow) {
if (!num(project.options.JungSangInit)) init(project);
} else clear(project);
return project.options.JungSangShow;
}
// 화면: 정산 모드에서는 원가 표에 당초금액 열을 금액 앞에 보이고 금액 열 이름을 정산금액으로 바꾼다.
function columns(project, base) {
if (!project.options?.JungSangShow) return base;
const out = base.filter((key) => key !== "SC");
out.splice(out.indexOf("Cost"), 0, "SC");
return out;
}
function label(project, key) {
if (!project.options?.JungSangShow) return null;
return { SC: "당초금액", Cost: "정산금액" }[key] || null;
}
function handle(name, state) {
if (name === "jungsang-init") {
if (!confirm("당초금액이 정산금액으로 대체됩니다.")) return true;
EstApp.change((project) => init(project));
} else if (name === "jungsang-toggle") {
let on;
EstApp.change((project) => (on = toggle(project)));
state.notice = on ? "정산원가계산서를 작성합니다." : "정산원가계산서를 해제했습니다.";
} else return false;
return true;
}
return { difference, init, clear, toggle, columns, label, handle };
})();