diff --git a/resources/tester/test_est_issues.py b/resources/tester/test_est_issues.py index 0bd31b0a9..d56f2f5be 100644 --- a/resources/tester/test_est_issues.py +++ b/resources/tester/test_est_issues.py @@ -24,3 +24,20 @@ def test_data_issues_detect_duplicate_missing_and_mismatched_links_without_modif assert ("EstMainDat", 1, "연결 코드 중복") in items assert ("EstMainDat", 2, "연결 자료 없음") in items assert len(items) == 6 + + +def test_cost_error_location_requires_unique_group_and_valid_row(): + result = run( + "math", + """(()=>{ + const p=EstNative.empty(); + p.tables.CostMainDat=[{Index:1,Code:'A'}, {Index:0}, {Index:0}, + {Index:1,Code:'B'}, {Index:0}, {Index:1,Code:'B'}, {Index:0}]; + p.calculation={errors:['A:2 bad formula','A:8 invalid row','B:2 duplicate','other error']}; + return EstIssues.scan(p).filter(x=>x.message.includes('formula') || + x.message.includes('row') || x.message.includes('duplicate') || x.message==='other error'); + })()""", + ) + assert result[0]["table"] == "CostMainDat" + assert result[0]["index"] == 1 + assert all(row["table"] == "" for row in result[1:]) diff --git a/tools/est-test/PLAN.md b/tools/est-test/PLAN.md index 6f5071343..469f11c8a 100644 --- a/tools/est-test/PLAN.md +++ b/tools/est-test/PLAN.md @@ -1,4 +1,6 @@ ## Codex · EST 독립 테스트 앱 (2026-11-04) +- [x] 산출근거 계산 오류에서 해당 행으로 이동 → 실무 ESTX 오류와 중복 코드 안전 처리 확인. + - 자체 검증: 거창 실무 ESTX의 D0000000194:18 계산 오류에서 원본 해당 행으로 Edge 이동 확인. 중복 코드·범위 오류 차단 포함 시험 12개 통과. - [x] 다른 이름으로 저장할 때 작업 이름 입력 → 원본·복사본 구분과 저장 취소 확인. - 자체 검증: Tailscale HTTP Edge에서 빈 이름 차단, 별도 이름·ID의 사본 저장과 기존 파일 보존 확인. - [x] Tailscale HTTP 접속의 새 항목·첨부·공정 생성 오류 수정 → 실제 원격 주소에서 생성과 저장 확인. diff --git a/tools/est-test/native-issues.js b/tools/est-test/native-issues.js index bbc17b769..075464f83 100644 --- a/tools/est-test/native-issues.js +++ b/tools/est-test/native-issues.js @@ -50,8 +50,23 @@ const EstIssues = (() => { } }); } - for (const message of project.calculation?.errors || []) - issues.push({ table: "", index: -1, code: "", message: String(message) }); + const costs = project.tables.CostMainDat || [], + costGroups = EstNative.groups(costs); + for (const message of project.calculation?.errors || []) { + const text = String(message), + match = text.match(/^(.+):(\d+) /), + code = match?.[1], + group = code && costGroups.get(code), + offset = match ? Number(match[2]) - 1 : -1, + unique = group && sources.get(104)?.get(code)?.length === 1, + index = unique && offset >= 0 && offset < group.rows.length ? group.start + offset : -1; + issues.push({ + table: index >= 0 ? "CostMainDat" : "", + index, + code: index >= 0 ? code : "", + message: text, + }); + } return issues; } function render() {