From ba95a6d60659d58a6f4650b593eabd40f8606514 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 7 Nov 2026 11:27:41 +0900 Subject: [PATCH] fix(est): preserve notes on added report forms --- resources/tester/test_est_documents.py | 14 ++++++++++++++ tools/est-test/PLAN.md | 3 +++ tools/est-test/native-model.js | 15 ++++++++++++++- tools/est-test/native-report.js | 4 ++-- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/resources/tester/test_est_documents.py b/resources/tester/test_est_documents.py index 9f2ac80a8..c011b954d 100644 --- a/resources/tester/test_est_documents.py +++ b/resources/tester/test_est_documents.py @@ -1,6 +1,20 @@ from test_est_rea_parity import run +def test_custom_print_form_documents_are_saved_and_unknown_keys_rejected(): + result = run( + "math", + """(()=>{ + const p=EstNative.empty();p.documents={'annual-items':'stage note','progress-costs':'progress note'}; + const valid=EstModel.validate(p).documents;let rejected=false; + const q=EstNative.empty();q.documents={'invalid-key':'bad'};try{EstModel.validate(q)}catch{rejected=true} + return {valid,rejected}; + })()""", + ) + assert result["valid"] == {"annual-items": "stage note", "progress-costs": "progress note"} + assert result["rejected"] + + def test_schedule_refreshes_progress_from_latest_locked_round_without_losing_dates(): result = run( "math", diff --git a/tools/est-test/PLAN.md b/tools/est-test/PLAN.md index c1ef75e9e..186a88a9e 100644 --- a/tools/est-test/PLAN.md +++ b/tools/est-test/PLAN.md @@ -1,4 +1,7 @@ ## Codex · EST 독립 테스트 앱 (2026-11-04) +- [x] 추가 인쇄 서식의 본문 저장·미리보기·Excel 연결 보완 → 서식 문서 검증·재열기 시험. + - 자체 검증: 문서·Excel 시험 24개 통과, Edge에서 본문 저장·재열기·인쇄·Excel 요약 확인. + - [x] 기성 회차 이름 변경·추가 시 중복 방지 → 공백·기존 이름 충돌 시험. - 자체 검증: 기성·업무 시험 22개 통과, Edge에서 공백 중복 이름 거부·새 이름 생성 확인. diff --git a/tools/est-test/native-model.js b/tools/est-test/native-model.js index fc0d6989d..b2b03b749 100644 --- a/tools/est-test/native-model.js +++ b/tools/est-test/native-model.js @@ -344,8 +344,21 @@ const EstModel = (() => { if (project.documents != null) { if (typeof project.documents !== "object" || Array.isArray(project.documents)) throw Error("문서 본문 형식 오류"); + const extraForms = new Set([ + "progress-summary", + "progress-costs", + "escalation-summary", + "escalation-costs", + "annual-summary", + "annual-items", + "change-costs", + ]); for (const [key, value] of Object.entries(project.documents)) - if (!/^(current|\d+)$/.test(key) || typeof value !== "string" || value.length > 100000) + if ( + (!/^(current|\d+)$/.test(key) && !extraForms.has(key)) || + typeof value !== "string" || + value.length > 100000 + ) throw Error("문서 본문 형식 오류"); } for (const key of ["quantities", "progress", "annual", "drawings", "attachments"]) { diff --git a/tools/est-test/native-report.js b/tools/est-test/native-report.js index 2a6633057..946d76030 100644 --- a/tools/est-test/native-report.js +++ b/tools/est-test/native-report.js @@ -106,7 +106,7 @@ const EstReport = (() => { .document-text{white-space:pre-wrap;line-height:1.7;min-height:40mm}.page{break-after:page}.page:last-child{break-after:auto}.footer{text-align:right;margin-top:3mm}

${esc(state.project.name)}

${esc(title)}

${detail ? `

${esc(detail)}

` : ""}${totals ? `
순공사비 ${number(totals.direct?.TC)}원 · 도급액 ${number(totals.total)}원
` : ""} - ${paginate(root, settings)}${errors.length ? `

계산 오류 ${errors.length}건: ${esc(errors.join(" / "))}

` : ""}`; + ${paginate(root, settings)}${output && settings.notes ? `
${esc(settings.notes)}
` : ""}${errors.length ? `

계산 오류 ${errors.length}건: ${esc(errors.join(" / "))}

` : ""}`; EstApp.byId("print-frame").srcdoc = source; } function paginate(root, settings) { @@ -279,7 +279,7 @@ const EstReport = (() => { name: state.project.name, columns, rows, - detail: output.detail || "", + detail: [output.detail, setting().notes].filter(Boolean).join("\n"), errors: output.errors || [], }), });