diff --git a/tools/est-test/native-progress-wonga.js b/tools/est-test/native-progress-wonga.js new file mode 100644 index 000000000..4bcb77edc --- /dev/null +++ b/tools/est-test/native-progress-wonga.js @@ -0,0 +1,250 @@ +// 원본 기성 원가계산서(TfrmWongaAccomH 0xd48408 / V 0xd46914) 편집 — 회차별 원가 서식 사본(round.wonga)에만 적용. +// 한줄 삽입·추가(0xd49758: 새 행 Index 0·CalcIndex 0·Checked 끔, 앞 행 끝줄 표지 이어받기), 한줄 삭제(확인 뒤, 재계산 없음), +// 내용 삭제(LinkIndex·Cost·Biul·Youl·VSusic·Diget 비움), 선택항목 절하(0xd094dc, 기성은 도급액 행도 허용), +// 선택데이타 절하(popupTrunc: 직전 자리수를 그대로, CalcBase 행 제외), 공사비역산 자리수(목표 = 10^n 미만 절하 → 이윤 역산), +// 초기화(사본 지움 = 도급 원가 서식), 되살리기(직전 조작 전), 산출근거 약어로 표시(A8: 수식칸 편집 잠금만). +// 원본의 번호·참조 재작성(0xc97398·0xc971e8)은 하지 않는다 — 웹 수식은 Gubun·이름으로 찾으므로 새 행은 기호를 직접 적는다. +const EstProgressWonga = (() => { + const num = (value) => Number(value) || 0; + + function template(project, round) { + return round.contract?.wonga || project.tables.Wonga || []; + } + function edit(project, round, mutate) { + if (round.locked) throw Error("확정한 회차는 고칠 수 없습니다."); + round.wongaUndo = round.wonga ? structuredClone(round.wonga) : null; + round.wonga ||= structuredClone(template(project, round)); + return mutate(round.wonga); + } + function blank(list, at) { + const row = { Index: 0, Gubun: "", Name: "", Youl: "", VSusic: "", Cost: 0, CalcIndex: 0 }; + const prev = list[at - 1], + end = num(prev?.EndLineIndex); + row.EndLineIndex = end === 1 ? 1 : end === 3 ? 3 : 0; + if (end === 3) prev.EndLineIndex = 0; + row.Checked = false; + return row; + } + + const ops = { + insert(project, round, at) { + edit(project, round, (list) => list.splice(at, 0, blank(list, at))); + }, + append(project, round) { + edit(project, round, (list) => list.push(blank(list, list.length))); + }, + remove(project, round, at) { + edit(project, round, (list) => { + if (!list[at]) throw Error("삭제할 줄을 고르세요."); + list.splice(at, 1); + }); + }, + clear(project, round, at) { + edit(project, round, (list) => { + if (!list[at]) throw Error("내용을 지울 줄을 고르세요."); + Object.assign(list[at], { + LinkIndex: 0, + Cost: 0, + Biul: "", + Youl: "", + VSusic: "", + Diget: 0, + Checked: false, + }); + }); + }, + position(project, round, at, method, digits) { + edit(project, round, (list) => + EstWongaTools.position( + { tables: { Wonga: list }, options: project.options }, + [at], + method, + digits, + true, + ), + ); + }, + trunc(project, round, at) { + edit(project, round, (list) => { + if (!list[at]) throw Error("절하할 줄을 고르세요."); + if (!list[at].CalcBase) list[at].Diget = num(project.options.WongaLastDiget); + }); + }, + total(project, round, digits) { + if (round.locked) throw Error("확정한 회차는 고칠 수 없습니다."); + if (!Number.isInteger(digits) || digits < 0 || digits > 9) + throw Error("자리수는 0~9 사이로 입력하세요."); + if (digits) round.wongaTotalDigits = digits; + else delete round.wongaTotalDigits; + }, + init(project, round) { + if (round.locked) throw Error("확정한 회차는 고칠 수 없습니다."); + round.wongaUndo = round.wonga ? structuredClone(round.wonga) : null; + delete round.wonga; + delete round.wongaTotalDigits; + }, + undo(project, round) { + if (round.locked) throw Error("확정한 회차는 고칠 수 없습니다."); + if (!("wongaUndo" in round)) throw Error("되살릴 조작이 없습니다."); + if (round.wongaUndo) round.wonga = round.wongaUndo; + else delete round.wonga; + delete round.wongaUndo; + }, + field(project, round, at, name, value) { + edit(project, round, (list) => { + if (!list[at] || !["Gubun", "Name", "Youl", "VSusic", "Cost"].includes(name)) + throw Error("고칠 칸이 없습니다."); + list[at][name] = name === "Cost" ? num(String(value).replaceAll(",", "")) : value; + }); + }, + }; + + // 화면 + function render(state, round, output) { + const { esc, number } = EstApp, + project = state.project, + list = round.wonga || template(project, round), + locked = round.locked, + lockFormula = project.options.WongaSNameShow, + pick = state.progressWongaRow; + const b = (action, label) => + ``; + const tools = [ + b("pw-insert", "한줄 삽입"), + b("pw-append", "한줄 추가"), + b("pw-delete", "한줄 삭제"), + b("pw-clear", "내용 삭제"), + b("pw-position", "선택항목 절하하기"), + b("pw-trunc", "선택데이타 절하하기"), + b("pw-total", "공사비역산 자리수 맞추기"), + b("pw-init", "원가계산서 초기화"), + b("pw-undo", "되살리기"), + ``, + round.wonga ? "회차 서식 사용 중" : "", + round.wongaTotalDigits ? `역산 ${round.wongaTotalDigits}자리` : "", + ].join(""); + const input = (i, name, value, disabled) => + ``; + const body = (output.costs || []) + .map((row, i) => { + const tpl = list[i] || {}; + return `
| 기호 | 원가 비목 | 요율 | 산출근거 | 자리 | 도급금액 | 전회 | 금회 | 사정 | 누계 |
|---|