diff --git a/resources/tester/helper_est_native.cjs b/resources/tester/helper_est_native.cjs
index 5165e54c7..1cf5887aa 100644
--- a/resources/tester/helper_est_native.cjs
+++ b/resources/tester/helper_est_native.cjs
@@ -20,6 +20,7 @@ for (const file of [
"native-schedule.js",
"native-issues.js",
"native-attachments.js",
+ "native-standard.js",
"native-model.js",
"native-c3r.js",
"native-exchange.js",
diff --git a/resources/tester/test_est_documents.py b/resources/tester/test_est_documents.py
index c011b954d..88f54bd4d 100644
--- a/resources/tester/test_est_documents.py
+++ b/resources/tester/test_est_documents.py
@@ -5,13 +5,17 @@ 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 p=EstNative.empty();p.documents={'annual-items':'stage note','progress-costs':'progress note','standard-usage':'standard 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["valid"] == {
+ "annual-items": "stage note",
+ "progress-costs": "progress note",
+ "standard-usage": "standard note",
+ }
assert result["rejected"]
diff --git a/resources/tester/test_est_standard.py b/resources/tester/test_est_standard.py
new file mode 100644
index 000000000..d0529bfe1
--- /dev/null
+++ b/resources/tester/test_est_standard.py
@@ -0,0 +1,24 @@
+from test_est_rea_parity import run
+
+
+def test_standard_usage_reports_applied_and_source_prices_without_mutation():
+ result = run(
+ "math",
+ """(()=>{
+ const p=EstNative.empty();p.tables.SilJukDat=[{Code:'A',Name:'source',ValueIndex:4,InputTC:120},
+ {Code:'B',ValueIndex:4,InputTC:50},{Code:'B',ValueIndex:4,InputTC:60}];
+ p.tables.EstMainDat=[{Code:'A',Name:'work',LinkIndex:21,GN:2,TU:100,TC:200},
+ {Code:'B',Name:'duplicate',LinkIndex:21,GN:1,TU:45,TC:45},
+ {Code:'C',Name:'missing',LinkIndex:21,GN:1,TU:20,TC:20},
+ {Code:'A',Name:'material',LinkIndex:5,GN:1,TU:10}];
+ const before=JSON.stringify(p), rows=EstStandard.usage(p), print=EstForms.data('standard-usage',p);
+ return {rows,print,same:before===JSON.stringify(p)};
+ })()""",
+ )
+ assert result["same"]
+ assert [row["status"] for row in result["rows"]] == ["연결됨", "코드 중복", "연결 없음"]
+ assert result["rows"][0]["sourcePrice"] == 120
+ assert result["rows"][0]["appliedPrice"] == 100
+ assert result["rows"][0]["difference"] == -20
+ assert result["rows"][1]["sourcePrice"] is None
+ assert result["print"]["rows"] == result["rows"]
diff --git a/tools/est-test/PLAN.md b/tools/est-test/PLAN.md
index 186a88a9e..71c6a50b8 100644
--- a/tools/est-test/PLAN.md
+++ b/tools/est-test/PLAN.md
@@ -1,4 +1,7 @@
## Codex · EST 독립 테스트 앱 (2026-11-04)
+- [x] 표준시장단가 사용 내역·기초 단가 비교 화면·출력 구현 → 연결·중복·누락·행 이동 시험.
+ - 자체 검증: 연결 단가·중복·누락·문서 시험 12개 통과, Edge에서 화면·인쇄·해당 내역 이동 확인.
+
- [x] 추가 인쇄 서식의 본문 저장·미리보기·Excel 연결 보완 → 서식 문서 검증·재열기 시험.
- 자체 검증: 문서·Excel 시험 24개 통과, Edge에서 본문 저장·재열기·인쇄·Excel 요약 확인.
diff --git a/tools/est-test/README.md b/tools/est-test/README.md
index 9a0cd43e3..8ad2ab1a4 100644
--- a/tools/est-test/README.md
+++ b/tools/est-test/README.md
@@ -6,6 +6,8 @@
작업모드의 `자료 오류 검색`은 코드 중복, 연결 자료 누락, 연결된 품명·규격 차이와 계산 오류를 표시합니다. 항목의 `행 열기`로 해당 자료 위치로 이동할 수 있습니다. 품명·규격 차이는 사용자가 확인할 항목으로 표시합니다.
+작업모드의 `표준시장단가 사용 내역`은 표준시장단가에 연결된 내역별 적용 단가와 현재 기초 단가, 차이와 연결 상태를 보여 줍니다. 원래 내역으로 이동하거나 해당 표를 인쇄·Excel로 출력할 수 있습니다.
+
행을 선택한 뒤 편집 메뉴의 `선택 행 자릿수 설정`에서 처리방식과 소수 자릿수를 일괄 적용할 수 있습니다. 기존 계산 설정은 실행 취소로 되돌릴 수 있습니다.
내역서 편집 메뉴의 `내역 수량 초기화`는 선택한 상세 행 또는 모든 상세 행의 수량을 0으로 바꿉니다. 비율·합계 자동행은 건드리지 않으며 실행 취소할 수 있습니다.
diff --git a/tools/est-test/index.html b/tools/est-test/index.html
index 9de76a575..24d9adcdb 100644
--- a/tools/est-test/index.html
+++ b/tools/est-test/index.html
@@ -21,6 +21,7 @@
+
@@ -114,6 +115,7 @@