fix(est): keep large contract snapshots saveable

This commit is contained in:
2026-11-05 14:05:41 +09:00
parent 9f9151f56d
commit b15f7cbf09
4 changed files with 72 additions and 3 deletions
+10 -1
View File
@@ -64,7 +64,16 @@ else if (command === "repeat")
);
else if (command === "import")
result = require(path.join(base, "import-estx.cjs")).importEstx(fs.readFileSync(process.argv[3]));
else if (command === "blob-tail") {
else if (command === "baseline-size") {
context.input = require(path.join(base, "import-estx.cjs")).importEstx(
fs.readFileSync(process.argv[3]),
);
const baseline = vm.runInContext("EstBusiness.baseline(input)", context);
result = {
bytes: Buffer.byteLength(JSON.stringify(baseline), "utf8"),
archivePreserved: baseline.originalArchive === context.input.originalArchive,
};
} else if (command === "blob-tail") {
const { blob } = require(path.join(base, "import-estx.cjs")),
bytes = Buffer.alloc(1536);
bytes.writeUInt32LE(2, 516);
+37
View File
@@ -208,3 +208,40 @@ def test_original_numeric_fields_reject_invalid_saved_values():
})()""",
)
assert "GN_" in result
def test_baseline_keeps_current_inputs_once_and_preserves_working_binaries():
result = run(
"math",
"""(()=>{
const p=EstNative.empty();
p.tables.CostMainDat=[{Index:1,Code:'C',LineData:'current',LineData_:'previous'}];
p.tables.CadMainDat=[{Code:'D',Data:{binary:'QUJD'}}];
p.tables.StuffcDat=[{Code:'M',InputTC:100}];p.originalArchive='original bytes';
const q=EstBusiness.baseline(p),again=EstBusiness.baseline(q);
return {p,q,again};
})()""",
)
for item in [result["q"], result["again"]]:
assert item["originalArchive"] == "original bytes"
assert item["tables"]["CadMainDat"][0]["Data"]["binary"] == "QUJD"
assert "CadMainDat" not in item["baseline"]["tables"]
assert "StuffcDat" not in item["baseline"]["tables"]
assert item["baseline"]["tables"]["CostMainDat"][0]["LineData"] == "current"
assert "LineData_" not in item["baseline"]["tables"]["CostMainDat"][0]
assert result["p"]["tables"]["CostMainDat"][0]["LineData_"] == "previous"
def test_large_original_baseline_stays_within_the_save_request_limit():
import os
from pathlib import Path
import pytest
archive = Path(
os.environ.get("EST_REA_MAIN", "C:/Dasansoft/Est Plus 2/Data/ProjectData/main.estx")
)
if not archive.is_file():
pytest.skip("Original main.estx is not installed")
result = run("baseline-size", str(archive))
assert result["archivePreserved"]
assert result["bytes"] < 256 * 1024 * 1024
+2
View File
@@ -10,6 +10,8 @@
Ctrl+S는 입력 중인 셀도 확정한 뒤 저장합니다. 연속 저장 요청은 순서대로 처리하며, 저장 대기 중의 추가 입력이나 새로 연 문서를 이전 저장 응답으로 덮어쓰지 않습니다. 실행 취소는 현재 작업 파일의 연결을 유지합니다.
당초 확정 사본에는 재계산 입력을 한 번만 보관하며, 작업본의 도면·원본 압축 자료는 보존합니다. 설치된 `main.estx`의 당초 확정 후 실제 저장 API를 통과했고, 산근 77,395행과 원본 압축 해시 보존·계산 오류 0을 확인했습니다(요청 약 215MB, 저장 약 221MB).
초기 자료는 기술정보 DB의 실제 REA 저장 샘플입니다. `REA 샘플 대조`에서 원본 저장값과 275개 계산 결과를 비교합니다. 테스트용 임의 요율을 원본 기본값으로 넣지 않습니다. 새 원가 서식의 요율은 사용자가 입력합니다.
## 검증과 남은 범위
+23 -2
View File
@@ -5,8 +5,29 @@ const EstBusiness = (() => {
const rowKey = (row, index) => String(row.PkID ?? row.Code ?? index);
const special = (row) => [57, 58, 62, 67].includes(num(row.LinkIndex));
function baseline(project) {
const next = copy(project);
next.baseline = { tables: copy(project.tables), name: project.name };
const working = { ...project };
delete working.baseline;
const next = copy(working);
// Original recalculation replaces source catalogs from the working project.
// Keep its contract inputs once; drawings and pre-existing '_' copies stay in the working file.
const tables = {};
for (const table of [
"EstMainDat",
"HeadMainDat",
"HeadTitleDat",
"CostMainDat",
"CostTitleDat",
"MachTitleDat",
"Wonga",
]) {
tables[table] = (project.tables[table] || []).map((row) => {
const values = Object.fromEntries(
Object.entries(row).filter(([key]) => !key.endsWith("_")),
);
return copy(values);
});
}
next.baseline = { tables, name: project.name };
for (const rows of Object.values(next.baseline.tables))
for (const row of rows) row.NewItem = false;
for (const rows of Object.values(next.tables))