feat(est): save quantity calculation results
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
const zlib = require("node:zlib");
|
||||
const quantity = require("./native-quantity.cjs");
|
||||
const { calculateQuantity } = require("./quantity-calculate.cjs");
|
||||
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
||||
|
||||
function escapeText(text) {
|
||||
@@ -66,11 +67,12 @@ function editDocument(text, oldSheet, sheet) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function updateQuantities(project, base, cp949) {
|
||||
function updateQuantities(project, base, cp949, memory) {
|
||||
const sheets = project.quantitySheets || [],
|
||||
originals = base.quantitySheets || [];
|
||||
if (sheets.length !== originals.length) throw Error("수량산출서 추가·삭제는 지원하지 않습니다.");
|
||||
const rows = project.tables.MulMainDat.map((r) => ({ ...r }));
|
||||
const savedSheets = sheets.slice();
|
||||
for (let i = 0; i < sheets.length; i++) {
|
||||
if (same(sheets[i], originals[i])) continue;
|
||||
const row = rows.find((r) => r.Code === originals[i].Code);
|
||||
@@ -84,9 +86,56 @@ function updateQuantities(project, base, cp949) {
|
||||
: packed;
|
||||
const text = new TextDecoder("euc-kr", { fatal: true }).decode(bytes);
|
||||
if (!cp949(text).equals(bytes)) throw Error("수량산출서 원본 인코딩 보존 불가");
|
||||
const output = cp949(editDocument(text, originals[i], sheets[i]));
|
||||
let document = editDocument(text, originals[i], sheets[i]);
|
||||
const baseline = calculateQuantity(originals[i]),
|
||||
calculated = calculateQuantity(sheets[i]);
|
||||
if (calculated.errors.length || baseline.errors.length)
|
||||
throw Error(`수량산출서 계산 오류: ${calculated.errors[0] || baseline.errors[0]}`);
|
||||
const markerCount = originals[i].rows.reduce((total, row) => total + row.markers.length, 0);
|
||||
if (
|
||||
baseline.checks.length !== markerCount ||
|
||||
calculated.checks.length !== markerCount ||
|
||||
baseline.checks.some((v) => !Number.isFinite(v.stored) || v.stored !== v.calculated) ||
|
||||
baseline.items.some((v, n) => v.GN !== originals[i].items[n].GN)
|
||||
)
|
||||
throw Error("수량산출서 원본 결과와 재계산 값이 다릅니다. JSON으로 저장해 확인하세요.");
|
||||
let current = structuredClone(sheets[i]);
|
||||
for (let n = 0; n < current.rows.length; n++) {
|
||||
const desired = calculated.rows[n].LineData;
|
||||
const before = [...current.rows[n].LineData.matchAll(/\x12([-\d.,]+)\x12/g)];
|
||||
const after = [...desired.matchAll(/\x12([-\d.,]+)\x12/g)];
|
||||
if (before.length !== after.length) throw Error("수량산출 결과 표지 수 불일치");
|
||||
for (let j = 0; j < after.length; j++) {
|
||||
const matches = [...current.rows[n].LineData.matchAll(/\x12([-\d.,]+)\x12/g)];
|
||||
if (matches[j][0] === after[j][0]) continue;
|
||||
const next = structuredClone(current),
|
||||
at = matches[j].index;
|
||||
next.rows[n].LineData =
|
||||
next.rows[n].LineData.slice(0, at) +
|
||||
after[j][0] +
|
||||
next.rows[n].LineData.slice(at + matches[j][0].length);
|
||||
document = editDocument(document, current, next);
|
||||
current = next;
|
||||
}
|
||||
if (current.rows[n].LineData !== desired) throw Error("수량산출 결과 재계산 검산 실패");
|
||||
}
|
||||
if (!same(row.MulList, oldRow.MulList)) throw Error("수량산출서 목록 데이터 충돌");
|
||||
if (!same(calculated.items, current.items)) {
|
||||
row.MulList = {
|
||||
binary: memory(Buffer.from(row.MulList.binary, "base64"), calculated.items).toString(
|
||||
"base64",
|
||||
),
|
||||
};
|
||||
current.items = calculated.items;
|
||||
}
|
||||
savedSheets[i] = current;
|
||||
const output = cp949(document);
|
||||
row.Editor = { binary: (compressed ? zlib.deflateSync(output) : output).toString("base64") };
|
||||
}
|
||||
return { ...project, tables: { ...project.tables, MulMainDat: rows } };
|
||||
return {
|
||||
...project,
|
||||
quantitySheets: savedSheets,
|
||||
tables: { ...project.tables, MulMainDat: rows },
|
||||
};
|
||||
}
|
||||
module.exports = { editDocument, updateQuantities };
|
||||
|
||||
Reference in New Issue
Block a user