From d2a88894751ba47d7943b7248567ca91e03ed3b2 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sat, 7 Nov 2026 11:19:28 +0900 Subject: [PATCH] fix(est): reject duplicate quantity sheet codes --- resources/tester/test_est_quantity_workflow.py | 17 +++++++++++++++++ tools/est-test/PLAN.md | 3 +++ tools/est-test/native-quantity.cjs | 8 +++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/resources/tester/test_est_quantity_workflow.py b/resources/tester/test_est_quantity_workflow.py index b2017857d..d3a1771db 100644 --- a/resources/tester/test_est_quantity_workflow.py +++ b/resources/tester/test_est_quantity_workflow.py @@ -21,6 +21,23 @@ def test_apply_all_quantities_sums_sheets_and_rejects_errors_atomically(): assert result == {"updated": [5, 4], "rejected": True, "unchanged": True} +def test_apply_all_quantities_rejects_duplicate_or_reserved_sheet_codes(): + result = run( + "math", + """(()=>{ + const p=EstNative.empty();p.tables.EstMainDat=[{PkID:1,Code:'A',GN:1}]; + p.quantities=[{Code:'Q1',formula:'2',TargetKey:'id:1'}]; + let rejected=0; + for(const codes of [['S','S'],['manual'],['']]) { + p.quantitySheets=codes.map(Code=>({Code,rows:[],items:[],options:{}})); + try{EstQuantity.allTotals(p)}catch{rejected++} + } + return {rejected,GN:p.tables.EstMainDat[0].GN}; + })()""", + ) + assert result == {"rejected": 3, "GN": 1} + + def test_quantity_apply_requires_one_detail_row_per_code(): result = run( "math", diff --git a/tools/est-test/PLAN.md b/tools/est-test/PLAN.md index 19f223aa6..955e2547a 100644 --- a/tools/est-test/PLAN.md +++ b/tools/est-test/PLAN.md @@ -1,4 +1,7 @@ ## Codex · EST 독립 테스트 앱 (2026-11-04) +- [x] 전체 수량 반영 시 중복·예약 산출서 코드 차단 → 중복 합산 방지 시험. + - 자체 검증: 중복·빈·예약 코드 차단과 기존 수량 보존 포함 시험 19개 통과. + - [x] 선택 또는 전체 상세 내역 수량 초기화 → 비율·합계 보존·실행 취소 시험. - 자체 검증: 설계변경·이력 시험 9개 통과, Edge에서 선택·전체 초기화, 비율 보존과 취소 확인. diff --git a/tools/est-test/native-quantity.cjs b/tools/est-test/native-quantity.cjs index f5040a0cc..4c4d7a1ff 100644 --- a/tools/est-test/native-quantity.cjs +++ b/tools/est-test/native-quantity.cjs @@ -175,7 +175,13 @@ const EstQuantity = (() => { } function allTotals(project) { const combined = new Map(); - for (const selected of ["manual", ...(project.quantitySheets || []).map((sheet) => sheet.Code)]) + const codes = (project.quantitySheets || []).map((sheet) => sheet.Code); + if ( + codes.some((code) => typeof code !== "string" || !code || code === "manual") || + new Set(codes).size !== codes.length + ) + throw Error("수량산출서 코드가 없거나 중복됩니다."); + for (const selected of ["manual", ...codes]) for (const [index, value] of totals(project, selected, true)) combined.set(index, (combined.get(index) || 0) + value); if (!combined.size) throw Error("연결할 내역코드를 먼저 입력하세요.");