feat(est): save quantity item labels in ESTX

This commit is contained in:
2026-11-07 15:37:20 +09:00
parent 1d1f27bdff
commit 8d4d23e783
4 changed files with 34 additions and 2 deletions
@@ -90,6 +90,32 @@ def test_quantity_document_edits_keep_styles_and_bookmarks_and_block_marker_edit
assert result == {"same": True, "tags": True, "rejected": True}
def test_estx_quantity_item_labels_round_trip_when_sample_exists():
sample = Path("C:/Dasansoft/Est Plus 2/Data/ProjectData/main.estx")
if not sample.exists():
pytest.skip("installed EST sample unavailable")
script = """const fs=require('fs'),m=require('./tools/est-test/import-estx.cjs'),e=require('./tools/est-test/export-estx.cjs');
const p=m.importEstx(fs.readFileSync(process.argv[1])),before=structuredClone(p.quantitySheets),sheet=p.quantitySheets[0];
sheet.items[0].Name='changed name';sheet.items[0].Size='changed size';
const q=m.importEstx(e.exportEstx(p)),item=q.quantitySheets[0].items[0];
const other=JSON.stringify(q.quantitySheets[0].items.slice(1))===JSON.stringify(before[0].items.slice(1));
const rest=JSON.stringify(q.quantitySheets.slice(1))===JSON.stringify(before.slice(1));
p.quantitySheets[0].items[0].TargetCode='new target';let rejected=false;try{e.exportEstx(p)}catch{rejected=true}
console.log(JSON.stringify({name:item.Name,size:item.Size,other,rest,rejected}));"""
result = json.loads(
subprocess.check_output(["node", "-e", script, str(sample)], cwd=ROOT, timeout=45).decode(
"utf-8"
)
)
assert result == {
"name": "changed name",
"size": "changed size",
"other": True,
"rest": True,
"rejected": True,
}
def test_quantity_document_edit_across_character_styles_preserves_tags():
script = r"""const q=require('./tools/est-test/native-quantity.cjs'),w=require('./tools/est-test/export-quantity.cjs');
const doc='<cs nr=1/><cs nr=2/><div><c nr=1/>abc<c nr=2/>def<c nr=1/>ghi</div>';
+2
View File
@@ -1,4 +1,6 @@
## Codex · EST 독립 테스트 앱 (2026-11-04)
- [x] 기존 수량산출 항목의 품명·규격을 ESTX에 저장 → 재열기·다른 항목 보존·연결 변경 차단 확인.
- 자체 검증: 설치 main.estx 기존 항목의 품명·규격 저장·재열기, 다른 항목·문서 보존과 연결 변경 차단 확인. 저장·수량 관련 시험 22개 통과.
- [x] 인쇄 서식의 상·하·좌·우 여백 개별 설정과 ESTX 저장 → 기존 단일 여백 호환·실제 서식 재읽기 확인.
- 자체 검증: 거창 ESTX 여백 13·14·15·16mm 미리보기·JSON 저장과 기존 단일 여백 호환을 Edge에서 확인. 설치 샘플 ESTX 저장·재읽기 포함 관련 시험 24개 통과.
- [x] 산출근거 계산 오류에서 해당 행으로 이동 → 실무 ESTX 오류와 중복 코드 안전 처리 확인.
+2
View File
@@ -56,6 +56,8 @@ Ctrl+S는 입력 중인 셀도 확정한 뒤 저장합니다. 연속 저장 요
수량 화면에서 새 산출서를 만들고 이름과 산출 항목의 품명·규격을 편집할 수 있습니다. `산출 행 추가`로 결과 표지가 연결된 행과 항목을 함께 만든 뒤 수식을 입력하고, 연결 내역코드를 지정해 계산 수량을 내역에 반영합니다. 행 아래 삽입, 위·아래 이동과 산출 행·산출서 삭제도 가능하며, 이 구조 변경은 JSON 저장과 다시 열기를 지원합니다. 기존 연결은 내역코드를 비워 해제할 수 있습니다.
원본 ESTX의 기존 수량산출 항목은 품명·규격을 수정해 ESTX에 저장할 수 있습니다. 연결 변경과 새 항목 추가·삭제는 계속 JSON으로 보관합니다.
재계산 메뉴의 수량 반영도 현재 선택한 산출서 또는 직접 작성 수식표를 사용합니다. 반영 전에 모든 연결 대상과 수식을 검사하며, 기존 원본 연결 데이터는 그대로 보관합니다.
재계산 메뉴의 `모든 수량산출 합산 반영`은 모든 산출서와 직접 작성 수식표의 연결 수량을 내역 행별로 합산합니다. 어느 산출서든 계산 오류가 있거나 연결 대상이 모호하면 전체 반영을 중단합니다.
+4 -2
View File
@@ -90,8 +90,10 @@ function editStyledRuns(div, before, after, parse) {
// Change text inside an existing styled run, never WPTools tags or bookmarks.
function editDocument(text, oldSheet, sheet) {
const withoutLabels = (items) => items.map(({ Name, Size, ...rest }) => rest);
if (
!same({ ...oldSheet, rows: [] }, { ...sheet, rows: [] }) ||
!same({ ...oldSheet, rows: [], items: [] }, { ...sheet, rows: [], items: [] }) ||
!same(withoutLabels(oldSheet.items), withoutLabels(sheet.items)) ||
oldSheet.rows.length !== sheet.rows.length
)
throw Error("수량산출서 목록·연결·행 구조 변경은 ESTX 저장을 지원하지 않습니다.");
@@ -193,7 +195,7 @@ function updateQuantities(project, base, cp949, memory) {
if (current.rows[n].LineData !== desired) throw Error("수량산출 결과 재계산 검산 실패");
}
if (!same(row.MulList, oldRow.MulList)) throw Error("수량산출서 목록 데이터 충돌");
if (!same(calculated.items, current.items)) {
if (!same(calculated.items, originals[i].items)) {
row.MulList = {
binary: memory(Buffer.from(row.MulList.binary, "base64"), calculated.items).toString(
"base64",