diff --git a/resources/tester/test_est_escalation_workflow.py b/resources/tester/test_est_escalation_workflow.py index bb62d535e..36ed614c1 100644 --- a/resources/tester/test_est_escalation_workflow.py +++ b/resources/tester/test_est_escalation_workflow.py @@ -1,6 +1,25 @@ from test_est_rea_parity import run +def test_escalation_preserves_explicit_zero_total_and_falls_back_only_without_wonga(): + result = run( + "math", + """(()=>{ + const p=EstNative.empty();p.options.SourceRefresh=false;p.options.EscDesignTotal=1000; + p.tables.EstMainDat=[{PkID:1,Code:'R',GN:10,GU:100,AGU:100,EscActual:3},{LinkIndex:54}]; + p.tables.Wonga=[{Gubun:'D',BaseField:'TC'},{Gubun:'T',LinkIndex:55,VSusic:'0'}]; + const zero=EstBusiness.escalation(p);p.tables.Wonga=[]; + return {zero,absent:EstBusiness.escalation(p)}; + })()""", + ) + assert result["zero"]["errors"] == [] + assert result["zero"]["contractTotal"] == 0 + assert result["zero"]["adjustedTotal"] == 0 + assert result["zero"]["excludedTotal"] == 0 + assert result["absent"]["contractTotal"] == 1000 + assert result["absent"]["excludedTotal"] == 300 + + def test_escalation_uses_design_denominator_and_all_price_branches(): result = run( "math", diff --git a/resources/tester/test_est_progress_workflow.py b/resources/tester/test_est_progress_workflow.py index c5b398488..29d90e7c9 100644 --- a/resources/tester/test_est_progress_workflow.py +++ b/resources/tester/test_est_progress_workflow.py @@ -102,3 +102,22 @@ def test_progress_total_only_mode_and_invalid_saved_input_rejection(): assert result["output"]["errors"] == [] assert result["output"]["rows"][0]["GumTC"] == 250 assert result["output"]["total"] == 250 + + +def test_progress_preserves_zero_wonga_total_and_falls_back_only_when_absent(): + result = run( + "math", + """(()=>{ + const p=EstNative.empty();p.options.SourceRefresh=false; + p.tables.EstMainDat=[{PkID:1,Code:'R',GN:10,GU:100},{LinkIndex:54}]; + p.tables.Wonga=[{Gubun:'D',BaseField:'TC'},{Gubun:'T',LinkIndex:55,VSusic:'0'}]; + p.progress=[{id:'one',inputs:{'1':{Gum:2}}}]; + const zero=EstProgress.calculate(EstNative.calculate(p),'one'); + p.tables.Wonga=[];const absent=EstProgress.calculate(EstNative.calculate(p),'one'); + return {zero,absent}; + })()""", + ) + assert result["zero"]["errors"] == [] + assert result["zero"]["rows"][0]["GumTC"] == 200 + assert result["zero"]["total"] == 0 + assert result["absent"]["total"] == 200 diff --git a/tools/est-test/README.md b/tools/est-test/README.md index c3482e408..6a4388333 100644 --- a/tools/est-test/README.md +++ b/tools/est-test/README.md @@ -61,7 +61,7 @@ Ctrl+S는 입력 중인 셀도 확정한 뒤 저장합니다. 연속 저장 요 기성은 수량·금액·비율·비목별 입력, 사정 승인, 전회·금회·누계 원가를 계산합니다. 확정 회차는 당시 계약 자료를 보존하고 서버 저장 시 결과를 재검산합니다. 전회 수정은 이후 회차의 확정도 해제하며, 전회 미확정 상태에서 다음 회차를 확정할 수 없습니다. -물가변동은 같은 행 구조의 계약·입찰 자료(JSON/ESTX)를 불러와 조사·계약·변동 단가를 나눕니다. 원본 레코드 순서 방식에 따라 행 순서·코드·레벨이 다른 자료는 거부합니다. 등락 분기, 조사금액 기준 조정률, 자동 최대수량/수동 적용제외, 간접비 포함 적용대가와 기성 누계 불러오기를 제공합니다. 연차는 수식 참조 오류를 차단하며, 미리보기 뒤 선택한 차수만 독립 사본으로 엽니다. +물가변동은 같은 행 구조의 계약·입찰 자료(JSON/ESTX)를 불러와 조사·계약·변동 단가를 나눕니다. 원본 레코드 순서 방식에 따라 행 순서·코드·레벨이 다른 자료는 거부합니다. 등락 분기, 조사금액 기준 조정률, 자동 최대수량/수동 적용제외, 간접비 포함 적용대가와 기성 누계 불러오기를 제공합니다. 기성과 물가변동은 원가계산서의 명시적인 0원 도급액을 보존합니다. 연차는 수식 참조 오류를 차단하며, 미리보기 뒤 선택한 차수만 독립 사본으로 엽니다. **CAD를 제외한 모든 원본 동작의 동등성이 확보된 상태는 아닙니다.** 위 업무와 추가 입출력은 REA 분기·합성 시나리오·실제 Edge 화면 조작·서버 저장/재열기로 검증했습니다. XML은 DB의 XSD 검사, Excel은 별도 읽기 라이브러리 검사, ESTX는 설치 sample.estx의 수정·재읽기를 통과했습니다. 원본 EST 실행 비교, 원본과 같은 페이지 도형 배치, JDL 인증/확장 산식, 구조를 변경하는 완전한 ESTX 쓰기와 앞서 기록한 원본 산식 잔여 오류는 남아 있습니다. CAD/VEC0650 편집은 사용자 요청으로 제외합니다. diff --git a/tools/est-test/native-escalation.js b/tools/est-test/native-escalation.js index 967705058..9433d48b8 100644 --- a/tools/est-test/native-escalation.js +++ b/tools/est-test/native-escalation.js @@ -2,7 +2,8 @@ const EstEscalation = (() => { const { num, units, components, floating, sum } = EstMath; const special = (row) => [54, 55, 57, 58, 59, 62, 67].includes(num(row.LinkIndex)); - const total = (p) => num(p.calculation.total) || num(p.calculation.direct.TC); + const total = (p) => + p.tables.Wonga.length ? num(p.calculation.total) : num(p.calculation.direct.TC); function calculate(project) { const key = EstBusiness.rowKey, errors = [], diff --git a/tools/est-test/native-progress.js b/tools/est-test/native-progress.js index 3b2e6e076..6afced713 100644 --- a/tools/est-test/native-progress.js +++ b/tools/est-test/native-progress.js @@ -196,7 +196,10 @@ const EstProgress = (() => { ? floating((num(row[prefix + "TC"]) / num(row.TC)) * 100, 2, 1) : 0; } - return { rows: calculated.tables.Wonga, total: num(calculated.calculation.total) || current }; + return { + rows: calculated.tables.Wonga, + total: calculated.tables.Wonga.length ? num(calculated.calculation.total) : current, + }; } const gum = costsFor("Gum"), sa = costsFor("Sa"),