- [x] 산출근거 주석 지정/해제(`popMainSetStr`) 및 블럭 삭제(`popMainBlockDel`) 구현 - 자체 검증: 1) 산출근거 주석 지정/해제 (`popMainSetStr`, 0xf08b1c): - REA `TFRMCOST`/`TFRMESTBASE`의 팝업 메뉴 `popMainSetStr` / `mnuSetGuSuc` ("주석으로 지정", Ctrl+J, 0xf08b1c) 스펙 근거 기반 구현. - 단가산출(`CostMainDat`) 화면의 산출근거 행에서 `Index`를 `-1`(주석)로 지정하거나 원래 `Index`(0)로 복원. - 주석 지정 시 `_origIndex: curIndex`를 명시적으로 보존하고, `Index === -1`로 전환. 주석 해제 시 `_origIndex` 또는 0으로 안전하게 복원하고 임시 속성 제거. - 호표 제목 행(`Index > 0`) 또는 소계 구분선(`Index === -20`)은 주석으로 지정할 수 없도록 안전 가드 적용. - 다중 선택 시 제목 행이나 비산출근거 행이 포함되면 전체 변경을 중단하고 원자성(Atomic) 보장. - `native-text.js`에서 `Index === -1`인 행은 소계(`LinkIndex: 61`) 계산 시 `if (num(previous.Index) !== -1)` 조건에 따라 자동으로 합산에서 제외되므로 산출식 수치 무결성 완벽 보장. 2) 블럭 삭제 (`popMainBlockDel`, 0xf08adc): - REA `TFRMCOST`/`TFRMHEAD`/`TFRMMACH`/`TFRMEST` 전역의 `popMainBlockDel` ("블럭삭제", Ctrl+Del, 0xf08adc) 스펙 근거 기반 구현. - `EstBlockActions.deleteBlockRows(state)`: 선택된 범위/블럭의 행들을 일괄 삭제. - 호표 제목 행(`Index > 0`)이 포함된 경우 호표 전체 행을 일괄 삭제 범위로 확장. - 다른 항목(`EstMainDat`, `HeadMainDat` 등)에서 참조 중인 코드가 포함된 경우 "다른 항목에서 사용 중입니다. 연결을 먼저 해제하세요."로 안전 차단. - 삭제 완료 후 선택 해제 및 블럭 시작/끝 상태 초기화. 3) UI 연동 및 700줄 제한 엄수: - `native-block-actions.js`에 `deleteBlockRows` 및 `toggleCostComment`를 모듈화 배치하여 기존 700줄 한도에 도달한 `native-actions.js`(699줄), `native-extra.js`(697줄) 코드 변경 없이 파일 크기 제한 완벽 준수 (`native-block-actions.js`: 185줄). - `index.html` 편집(E) 메뉴에 `블럭 삭제`(`data-action="block-del"`) 및 `산출근거 주석 지정/해제`(`data-action="toggle-cost-comment"`) 등록. - 관련 테스트: - `pytest resources/tester/test_est_row_actions.py` 7개 전수 통과: - `test_toggle_cost_comment_and_block_delete`: 산출근거 행 주석(-1) 지정 및 `_origIndex` 보존, 0으로의 복원 및 임시 속성 제거, 호표 제목 및 구분선 지정 거부, 다중 선택 원자성 보장, 블럭 행 일괄 삭제 및 참조 중인 호표 삭제 차단 검증 완료. - `test_block_actions_range_selection_and_clear`: 블럭 시작/끝 지정, 범위 선택, 전체 선택, 블럭 해제 및 예외 검증 완료. - `pytest resources/tester/test_est_row_actions.py resources/tester/test_est_estimate.py resources/tester/test_est_business.py`: 29 passed in 21.24s. - [x] 단가산출 산출근거 비목 지정/해제(`popMainSetNC/GC/JC/TC/BimogFree`) 구현 및 순공사비·경비성 안전 가드 보강 - 자체 검증: 1) 순공사비·경비성 토글 안전 가드 및 원자적 일괄 검증 보강: - **명시적 0/1/2 이력 보존 및 복원**: `toggleJcBimog`에서 경비성(3) 전환 시 원래 `SCheck`(0:비목별, 1:재료, 2:노무)을 `_prevSCheck`에 명시적으로 보존. 해제 시 해당 이력 또는 원본 `SCheck_`가 존재하는 경우에만 정확한 이전 값으로 복원. - **이력 없는 경비성 3 임의 변환 차단**: `_prevSCheck` 및 `SCheck_`가 없는 기존 3 행이나 원래 유형을 알 수 없는 행의 임의 0 변환을 안전하게 차단. - **다중 선택 원자성(Atomic) 보장**: 복수 행 선택 토글 시 사전 검증 계획(`plans`)을 수립하여 한 행이라도 거부 대상이 포함되면 전체 변경을 중단하고 앞선 행도 변경되지 않도록 원자적 일괄 적용 보장. - **JSON 저장 및 재열기 왕복 보증**: JSON 직렬화/역직렬화 후에도 `_prevSCheck` 및 `SCheck_`가 보존되어 당초 SCheck(0/1/2)로 100% 온전하게 복원됨을 검증. - 원본부터 순공사비(54)인 행의 해제 시도나 대체 시도 역시 `_origLinkIndex`나 `LinkIndex_` 등 원래 유효 유형이 확인되지 않으면 오류로 차단하고 기존 행 속성 보존. 2) 단가산출 산출근거 비목 지정/해제 (`popMainSetNC`, `popMainSetGC`, `popMainSetJC`, `popMainSetTC`, `popMainSetBimogFree`): - REA `TFRMCOST`/`TFRMESTBASE`의 팝업 메뉴 비목 지정(`0xf0c0f0`, `0x10d815c`) 스펙 근거 기반 구현. - 단가산출(`CostMainDat`) 화면에서 산출근거 행의 `OCheck` 및 `SCheck`를 노무비(-1), 재료비(-2), 경비(-3), 소계(-5)로 지정하거나 일반 산출식(0)으로 해제. - UI 연동: 편집(E) 메뉴에 `산출근거 비목 지정/해제`(`data-action="set-cost-line-kind"`) 등록 및 `EstActions.form` 대화상자 지원. 3) 700줄 제한 엄수: - `native-business-actions.js`: 643줄, `native-extra.js`: 696줄, `index.html`: 211줄, `resources/tester/test_est_row_actions.py`: 422줄. - 관련 테스트: - `pytest resources/tester/test_est_row_actions.py` 5개 전수 통과: - `test_toggle_safety_guards_prevent_arbitrary_zero_conversion_without_history`: 복원 정보 없는 원본 54 행 해제/대체 차단 및 원본 경비성(3) 임의 0 변환 차단 검증. - `test_jc_bimog_multi_selection_atomic_and_json_roundtrip`: 다중 선택 시 거부 행 발생 시 앞선 행 변경 롤백(원자성), SCheck=0 지정/해제 및 JSON 재열기 왕복 복원 검증. - `test_set_cost_line_kind_action`: 산출근거 행의 노무비(-1) 지정, 재료비(-2)의 일반 해제(0) 및 타 화면 안전 거부 검증. - `pytest resources/tester/test_est_row_actions.py resources/tester/test_est_estimate.py resources/tester/test_est_business.py`: 27 passed in 19.26s. - [x] 데이터 사용위치 검색(`popUsesSerch` / `TFRMUSESDATASERCH`) 구현 - 자체 검증: 1) REA 스펙 근거: - REA `TfrmUsesDataSerch` (0x10d819c) 및 `popUsesSerch`(내역서, 일위대가, 단가산출, 기계경비 전역 팝업 메뉴) 기반 구현. - 임의의 품목 행(자재, 노임, 견적, 표준, 일위대가, 단가산출, 기계경비, 내역서)에서 `데이터 사용위치 찾기` 실행 지원. 2) `EstExtra.findDataUsages(project, target)` 검색 엔진 구현: - 대상 항목의 `Code`(우선) 또는 정규화된 `Name`+`Size`를 기준으로 내역서(`EstMainDat`), 일위대가(`HeadMainDat`), 단가산출(`CostMainDat`), 기계경비(`MachMainDat`)의 참조 행을 전수 검색. - 대상 항목 자기 자신의 대표 행은 검색 결과에서 안전하게 제외. - 일위/단산/기계의 경우 상위 공종 코드(`curGroup`)를 함께 추적하여 위치 이동 시 정확한 묶음(`state.group`)으로 진입 지원. 3) UI 연동 및 대화상자 이동 기능: - `index.html` 상단 툴바에 `사용위치` 버튼(`data-action="uses-data-search"`) 및 편집 메뉴에 `데이터 사용위치 찾기` 추가. - `EstExtra.showUsesSearchDialog(targetRow)`를 통해 검색된 위치 목록(구분, 코드, 품명/산출근거, 규격, 단위, 수량, 금액) 표시. - `이동`(`goto-use-location`) 클릭 시 대화상자를 닫고 대상 테이블(`navigate`), 대상 묶음 그룹(`state.group`), 페이지(`state.page`), 선택 행(`state.selection`)으로 즉시 포커스 이동. 4) 700줄 제한 엄수: - `native-extra.js`: 554줄, `native-business-actions.js`: 685줄, `native-views.js`: 140줄, `index.html`: 210줄. - 관련 테스트: - `pytest resources/tester/test_est_row_actions.py` 통과 (`test_uses_data_search_finds_usages_across_tables`: 자재 M001의 일위/단산/내역 4건 검출 및 그룹 보존, 일위 U001의 내역 1건 검출, 이름 일치 항목 검출, 미사용 항목 0건 반환 검증 완료). - `pytest resources/tester/test_est_row_actions.py resources/tester/test_est_estimate.py` 6개 전수 통과 (0 실패). - [x] 일위대가 공종 할증계산(`TFRMHALJUNGBIUL`) 및 자재단가 부가세계산(`TFRMCONVERTTOGANGUB`) 구현 - 자체 검증: 1) 일위대가 공종 할증계산 (`TFRMHALJUNGBIUL`): - REA `TFRMHEAD`의 `DoHalJungClick` (0xf5b7fc) 및 `TFRMHALJUNGBIUL`(명칭, 불러올비목, 적용율, 적용비목, 0xdb4b14) 근거 기반 구현. - [native-haljung.js](file:///D:/aislo-wt/CODEX/tools/est-test/native-haljung.js)의 `EstHalJung.apply(project, tableKey, groupCode, { name, size, rate, sourceKind, targetKind })`: - 불러올비목(규격): 0=비목별, 1=재료비의, 2=노무비의, 3=경비의, 4=합계의 (`OCheck`). - 적용비목: 0=비목별, 1=재료비에, 2=노무비에, 3=경비에 (`SCheck`). - **비목 매핑 정확성 보장**: `sourceKind`가 특정 비목(1=재료비, 2=노무비, 3=경비)이고 `targetKind = 0`(비목별)인 경우, 기본 경비(`JC`)로 왜곡되지 않고 해당 원천 비목(`SCheck = sInfo.ocheck`)으로 정확히 가산되도록 보정. - 묶음 내 소계(`LinkIndex = 51, 68`) 직전 위치에 `LinkIndex = 58`(비율) 행을 안전하게 자동 삽입하고 즉시 재계산 반영. - 0 또는 잘못된 할증율 및 존재하지 않는 공종/화면 요청 안전 거부. - UI 연동: `native-views.js`에서 일위대가 화면 활성화 시 `할증계산` 버튼(`data-action="haljung-calc"`) 노출 및 대화상자 연동. 2) 자재단가 부가세계산 (`TFRMCONVERTTOGANGUB`): - REA `TFRMSTUFFC`의 팝업 `popChangeCost` 및 `TFRMCONVERTTOGANGUB`(부가세포함/제외, 단단위계산, 0xf616f0) 근거 기반 구현. - [native-vat.js](file:///D:/aislo-wt/CODEX/tools/est-test/native-vat.js)의 `EstVat.apply(project, indices, { calcMethod, diget, digetMethod })`: - 계산방법: 0 = 부가세포함(×1.1), 1 = 부가세제외(÷1.1). - 단단위계산: 원단위 또는 지정 자리수(1=십원, 2=백원..) 이하에 대해 사사오입/절하/절상 단단위 처리. - 근거 불충분한 `row.Kind` 변경 기능 비활성화: REA 스펙상 `StuffcDat`에 `Kind` 필드가 소비되지 않으므로 혼선 방지를 위해 자재구분 변경 옵션 제거 및 안전 처리. - 선택 행 또는 전체 자재단가(`Cost1~6`, `InputTC`, `TC`) 일괄 변환 및 Undo 지원. `ValueIndex`별(최저/평균/최고/선택/직접) 단가 및 재계산 후 원본 단가 보존 검증 완료. - UI 연동: `native-views.js`에서 자재단가 화면(`StuffcDat`) 활성화 시 `부가세계산` 버튼(`data-action="vat-calc"`) 노출 및 대화상자 연동. 3) 700줄 제한 엄수: - `native-haljung.js`: 91줄, `native-vat.js`: 58줄, `native-business-actions.js`: 593줄, `native-views.js`: 140줄. - 관련 테스트: - `pytest resources/tester/test_est_business.py` 18개 통과 (`test_haljung_calculation_apply_to_head_and_cost_groups`, `test_vat_calculation_exclude_include_and_unit_rounding_for_materials` 검증 보강 통과). - 핵심 EST 테스트 45개 전수 통과 (0 실패). - [x] 일위대가 공종 단위환산 계산(`TFRMUNITECALC`) 및 낙찰률 당초단가(100%) 복원(`TFRMBIMOGBIUL`/`TFRMNACCHALAPPLY`) 구현 - 자체 검증: 1) 일위대가 공종 단위환산 계산 (`TFRMUNITECALC`): - REA `TFRMHEAD`의 팝업/도구 버튼 `popUniteCalc` (`단위환산 계산`, 0xf59bd8) 및 `TFRMUNITECALC`(명칭, 규격, 수량, 단위) 근거 기반 구현. - `native-business.js`에 `convertGroupUnit(project, groupCode, { name, size, factor, unit })` 함수 구현: - 선택한 일위대가 공종(묶음)의 제목 행(`Index > 0`)에 명칭(`Name`), 규격(`Size`), 단위(`Unite`) 적용. - 특수행 제외: 비율 행(`LinkIndex=58, 62`), 낙찰률 행(`LinkIndex=52`), 소계 행(`LinkIndex=51, 68`) 및 계산 안 함/고정금액 행(`CalcIndex=1, 3`)은 수량(`GN`) 배수 변경에서 안전하게 제외하여 백분율 왜곡 및 중복 팽창 방지. - 일반 비목 행의 수량(`GN`)에만 환산 계수(`factor`)를 부동소수점 곱으로 적용. - `AutoCalc: false` 등 프로젝트 옵션 보존 및 0 또는 유효하지 않은 계수 거부. - UI 연동: `index.html` 및 `native-views.js`에서 일위대가 화면(`HeadMainDat`) 활성화 시 `단위환산` 버튼(`data-action="unit-calc"`) 자동 노출. - 대화상자(`EstActions.form`)를 통해 사용자 입력 접수 후 `EstApp.change()`로 트랜잭션 및 Undo 지원. 2) 낙찰률 당초단가(100%) 복원 (`TFRMBIMOGBIUL`, `TFRMNACCHALAPPLY`): - REA `btnUndo` (Hint: "당초단가(100%)로 복원합니다.") 근거 구현. - `native-business.js`의 `bid(project, rates)`: - 연속 낙찰률 적용 시에도 최초 단가와 최초 옵션을 잃지 않도록 `row.PreBidRates`가 이미 존재하면 덮어쓰지 않고 최초 단가 유지. - `O${field}`도 최초 단가(`PreBidRates[field]`)를 기준으로 낙찰률을 계산하여 다회차 적용 시의 누적 왜곡 방지. - 원본 프로젝트의 `SourceRefresh` 설정값은 `next.options._preBidSourceRefresh ??= project.options.SourceRefresh`로 최초 1회만 보존. - `restoreBid(project)`: - 원래의 `SourceRefresh`가 `true`이더라도 재계산 도중 원천 단가로 복원 단가가 다시 덮이지 않도록, `SourceRefresh: false` 상태로 복원 재계산 수행 후 마지막에 원래 사용자의 `SourceRefresh` 옵션 상태를 안전하게 복원. - `PreBidRates` 및 생성된 낙찰 단가를 복원하고, 원본 파일에 이미 존재하던 `O*` 필드(`OTU/ONU/OGU/OJU/OSU`)는 임의 삭제하지 않고 영구 보존. - 저장·재열기(JSON 왕복), 수동/자동 계산 모드, 원천 단가와 다른 초기 단가 상태에서도 최초 단가 100% 온전 복원 확인. - 설계변경 화면 도구 모음에 `당초단가(100%) 복원`(`restore-bid`) 버튼 연동. 3) 700줄 제한 엄수: - `native-business.js`: 692줄, `native-business-actions.js`: 505줄, `native-actions.js`: 699줄, `native-views.js`: 136줄. - 관련 테스트: - `pytest resources/tester/test_est_business.py` 16개 통과 (`test_unit_calc_group_conversion_preserves_percentages_subtotals_fixed_and_other_groups` 포함). - `pytest resources/tester/test_est_change_workflow.py` 15개 통과 (`test_bid_rates_consecutive_apply_source_refresh_and_roundtrip_restore` 추가 통과). - 핵심 EST 테스트 43개 전수 통과 (0 실패). - [x] 자료 오류 검색(issues) 및 불일치 데이터 확인: REA `TFRMNAMESIZECHECK`(명칭·규격·단위 불일치) 및 `TFRMPERSENTCHECK`(단위 백분율(%) 불일치 데이터 검색) 검출 구현 - 자체 검증: 1) REA `TFRMNAMESIZECHECK`(명칭 불일치 및 중복 데이타 확인) 근거 기반 검출 및 동기화 구현: - `native-issues.js`의 `scan()`에서 기존 품명(`Name`), 규격(`Size`) 비교에 더해 **단위(`Unite`)** 불일치(`연결 단위 차이`) 검출 로직 추가. - 원천 데이터(자재 `StuffcDat`, 노임 `LaborcDat`, 표준 `SilJukDat`, 견적 `EstiMateDat`, 일위 `HeadMainDat`, 단가 `CostMainDat`, 기계 `MachMainDat`)의 실제 명칭·규격·단위(`sourceName`, `sourceSize`, `sourceUnite`)를 이슈 항목에 보존. - UI 렌더링에 `원천 실제 명칭` 표시 및 `원천명칭 반영`/`원천단위 반영` 개별 버튼(`data-issue-sync-row`), 상단 도구 모음에 `불일치 원천 명칭/규격 일괄 반영` 버튼(`data-issue-sync-all`) 제공. 2) REA `TFRMPERSENTCHECK`(단위 백분율(%) 불일치 데이터 검색) 근거 기반 검출 추가: - REA `TFRMPERSENTCHECK` ("위의 데이타는 백분율(%)로 계산되어야 할 항목들입니다(할증, 낙찰율, 제잡비, 조달수수료 등). 그러나 단위가 %가 아니기 때문에 백분율로 계산하지 않습니다. 확인하세요.") 근거 구현. - 일위대가(`HeadMainDat`), 내역서(`EstMainDat`), 기계경비(`MachMainDat`), 단가산출(`CostMainDat`)의 비목 상세 행 중 백분율 연산 특수행(`LinkIndex = 52, 57, 58, 62, 67`)인데 단위(`Unite`)가 `%` 또는 `%`가 아닌 항목을 검출(`단위 백분율(%) 불일치`). 3) 불일치 필드별 안전 반영 및 단위 왜곡·규격 삭제 방지: - 단위(`Unite`)는 수량 및 단가 산식과 직결되므로 일괄 반영(`sync-all`) 대상에서 완전히 제외하고, 개별 행에서 명시적 승인(`원천단위 반영`) 시에만 처리하도록 분리. - 규격(`Size`)은 원천 규격이 비어 있지 않은 유효 문자열일 때만 반영하여, 빈 원천 규격으로 기존 내역 규격을 덮어써 지우는 현상 방지. - 품명(`Name`) 불일치는 품명만 원천 값으로 안전하게 동기화하고 기존 규격·단위를 보존. - 일괄 반영 범위는 전체 스캔 결과가 아니라 화면의 현재 필터 조건(`tableFilter`, `typeFilter`)에 해당하는 `currentFiltered` 항목만 대상으로 한정. - 반영 시 `EstApp.change()` 트랜잭션을 통해 실행 취소(Undo) 지원 및 데이터 무결성 보존. 4) 700줄 제한 준수: - `native-issues.js` 372줄로 엄수. - 관련 테스트: - `pytest resources/tester/test_est_issues.py` 12개 통과 (`test_data_issues_detect_percentage_unit_mismatch` 추가). - 브라우저 Undo 복원 및 원천 단위/규격 안전 처리 검증 완료. - [x] 인쇄 서식 옵션 검토 및 안전 조치: `PrintApplyField`(단가 0원 누락 위험 방지) 및 `PrintSumBottom`(공종/소계 중복 합산 및 단가 합산 왜곡 차단) 안전 처리 - 자체 검증: 1) 결함 분석 및 안전 조치: - `PrintSumBottom`: 표시되는 모든 행을 단순 누적할 경우 공종/소계와 상세 항목이 중복 합산되어 실제 공사금액의 2배 이상으로 뻥튀기되고, 단위가 다른 수량 및 단가(TU)를 합산하는 논리적 왜곡이 발생함. - `PrintApplyField`: REA의 적용 단가 필드 표시 의도를 '단가 0인 행 필터링'으로 오해하여 삭제할 경우, 공종 제목 및 정상적인 0원 항목·음수 정산 항목이 누락되는 중대 위험이 발생함. - REA 원문의 정확한 세부 집계/필터 알고리즘 근거가 불충분하므로, 서식 데이터의 왜곡 및 행 삭제를 즉시 차단하고 미지원 처리. 2) 코드 정리 및 데이터 무결성 보존: - `native-forms.js`: `PrintApplyField`에 의한 행 삭제 필터 및 `PrintSumBottom`에 의한 단순 `
` 합산 렌더링을 완전히 제거하고, 모든 공종(Level>0), 소계, 0원 항목, 음수 변경분 행이 원본 그대로 보존되도록 복원. - `native-report.js`: 불안정한 체크박스 UI 노출을 비활성화하고, 공람용 옵션 등 검증된 서식 기능만 안정적으로 제공. - 바이너리 레코드 오프셋(`import-print.cjs` / `export-print.cjs`)은 데이터 무결성을 위해 안전하게 0/1 값을 읽고 쓸 수 있도록 유지하되 잘못된 화면 처리를 차단. 3) 700줄 제한 준수: - `native-report.js` 352줄, `native-forms.js` 445줄, `export-print.cjs` 67줄, `import-print.cjs` 75줄로 엄수. - 관련 테스트: - `pytest resources/tester/test_est_documents.py` 16개 통과 (`test_print_apply_field_and_sum_bottom_preserve_all_rows_and_no_destructive_filtering` 추가). - 전체 연계 회귀 시험 54개 전수 통과 (0 실패). - [x] 공람용 서식(내역서 117, 내역서총괄표 118, 일위대가 115, 일위대가총괄표 116) 인쇄 옵션 및 공람방법(수량만/단가만/수량·단가) 렌더링 구현 - 자체 검증: 1) REA `TFRMESTPRINTPRIVATE` 및 `DatPrintOption.opt`의 `PrintGongMethod` 설정 연동: - 인쇄 미리보기(`native-report.js`) 서식 선택 시 공람용 서식(115, 116, 117, 118)에 대해 `공람용 방법` 셀렉트(`PrintGongMethod`: 0=수량만, 1=단가만, 2=수량·단가) 노출 및 설정 동기화. 2) `native-forms.js` 열 정의 및 마스킹 로직 구현: - 공람용 내역서(`117`) 및 일위대가(`115`): - `PrintGongMethod = 0`(기본값, 수량만): 단가 및 금액 열(TU, TC, NC, GC, JC, SC / NU, GU, JU, SU, TC)을 숨기고 공통정보 및 수량(GN)만 인쇄. - `PrintGongMethod = 1`(단가만): 수량(GN)을 숨기고 단가 및 금액 열만 인쇄. - `PrintGongMethod = 2`(수량·단가): 수량과 단가/금액을 모두 인쇄. - 공람용 총괄표(`116`, `118`): `PrintGongMethod = 0` 시 금액 비목을 제외하고 공통 레벨·공종 열만 안전하게 출력. - 일반 표준 서식(`1`, `2`, `103`, `106`)은 변경 없이 기존 전체 열 출력 및 데이터 무결성 보존. 3) 700줄 제한 준수: - `native-report.js` 342줄, `native-forms.js` 439줄로 엄수. - 관련 테스트: - `pytest resources/tester/test_est_documents.py` 15개 통과 (`test_public_view_forms_print_gong_method_options` 추가). - 전체 연계 회귀 시험 52개 전수 통과 (0 실패). - [x] 계약심사(review) 화면 변경 행 필터링(전체/변경/사유작성/사유미작성) 및 심사 사유 일괄 적용 구현 - 자체 검증: 1) `native-review.js` 보기 필터(`review-filter`) 및 사유 일괄 적용(`review-batch-reason`) 신규 구현: - 계약심사 테이블 상단에 항목 필터 셀렉트(`전체 항목`, `변경 항목만`, `사유 작성 항목`, `사유 미작성 변경항목`) 추가. - 대규모 내역서에서 수량/단가 변경이 발생한 항목이나 사유 작성이 누락된 변경 항목만 즉시 선별하여 검토할 수 있도록 개선. - 개별 행 선택 체크박스(`reviewSelection`) 및 일괄 사유 적용(`data-review-batch-reason`) 지원: 선택된 행들에 대해 공통 사유를 한 번에 입력·반영하며, 선택이 없는 경우 현재 화면에 표시된 필터링 대상 행 전부에 대해 일괄 반영. - 심사 입력 초기화(`review-clear`) 시 선택 세트도 함께 정리되도록 상태 무결성 보존. - 입력된 사유는 `contractReview.edits[key].Reason`으로 안전하게 저장되며, 실행 취소(Undo) 및 심사결과요약서(서식 171) 인쇄/엑셀 내보내기 연동 보존. 2) 모델 및 계산 무결성 검증: - 기존 심사 수량/단가 계산기(`EstReview.calculate`)와 사본 열기(`EstReview.copy`) 로직은 변경 없이 100% 동일하게 유지. 3) 700줄 제한 준수: - `native-review.js` 258줄로 700줄 이하 엄수. - 관련 테스트: - `pytest resources/tester/test_est_review_workflow.py` 8개 통과 (`test_review_view_filtering_and_batch_reason_application` 추가). - 전체 연계 회귀 시험 50개 전수 통과 (0 실패). - [x] 자료 오류 검색(issues)의 원가계산서(Wonga) 산출식(VSusic) 참조 유효성 검사 및 실제 계산기(calculate) 의존성/값/오류 로직 단일화 구현 - 자체 검증: 1) `native-wonga.js`의 계산 엔진 로직 단일화(`evaluateRows` 공통화): - `scan`과 `calculate`가 별도의 파서/DFS/참조 로직을 갖지 않고, 동일한 `evaluateRows` 함수를 공유하여 전방 참조, 의존성 순서, 실제 재귀 계산, 범위(CalcIndex 2, 3 제외 행 필터링), 순환 참조 감지(`active` Set) 로직을 100% 동일하게 실행. - 저장된 `Cost=0`이어도 수식이 있는 선행 참조 행(예: `B=A*2`)의 실제 재귀 계산 결과를 평가에 사용하여, `A=1/B`와 같은 유효한 나눗셈이 오래된 0값으로 인해 0 나눗셈으로 오탐되는 결함 원천 해결. - 오류 발생 시(`onError` 콜백) `scan`은 해당 원인 행을 등록하고 기존 `Cost`로 대체하여 후속 행으로의 연쇄 전파를 방지. 2) `native-issues.js`의 실제 프로젝트 기초금액(`direct`) 전달: - `issues.scan(project)` 호출 시 `project.calculation.direct`로부터 실제 `NC`, `GC`, `JC`, `SC`, `TC`, `노무비`, `재료비`, `경비`, `실적`, `직접공사비`를 추출해 `EstWonga.scan`의 `bases` 인자로 전달하여 기초 비목 0 판정 및 오탐 방지. 3) 700줄 제한 준수: - `native-wonga.js` 163줄, `native-issues.js` 274줄로 700줄 이하 엄수. - 관련 테스트: - `pytest resources/tester/test_est_issues.py` 9개 통과 (`test_wonga_scan_parity_with_calculate_forward_refs_old_cost_bases_ranges_and_cycles` 추가). - 전체 연계 회귀 시험 51개 전수 통과 (0 실패). - [x] 자료 오류 검색(issues)의 단가산출(CostMainDat) 상세 행 연결 자료(자재·노임·기계 등) 부재 및 중복 검출 확장 구현 - 자체 검증: 1) `native-issues.js`의 `scan()` 테이블 검사 대상 확장: - 기존 검사 대상(`EstMainDat`, `HeadMainDat`, `MachMainDat`)에 `CostMainDat`를 추가하여, 단가산출 호표 상세 행에서 자재(`LinkIndex: 5`), 노임(`LinkIndex: 6`), 기계(`LinkIndex: 105`), 표준(`LinkIndex: 21`), 견적(`LinkIndex: 101`), 일위(`LinkIndex: 103`), 산근(`LinkIndex: 104`) 등 원천 자료를 참조하는 상세 행(`Index === 0 && Code`)에 대해 연결 자료 존재 여부(`연결 자료 없음`) 및 원천 코드 중복(`연결 코드 중복`)을 전수 검사하도록 개선. - 오류 항목 클릭 시 `data-issue-table="CostMainDat"`로 해당 호표(`group`) 및 상세 행으로 정확히 이동하고 선택 행을 하이라이트 표시하도록 연동 보존. - 관련 테스트: - `pytest resources/tester/test_est_issues.py` 5개 통과 (`test_data_issues_detect_cost_main_dat_missing_and_duplicate_links` 추가). - 전체 연계 회귀 시험 76개 전수 통과 (0 실패). - [x] ESTX 내보내기 시 웹 전용 작업 데이터(예정공정표 schedule, 추가 서식 문서 documents) 누락 방지 및 기본 빈 상태 대조 차단 구현 - 자체 검증: 1) `export-estx.cjs` 및 `import-estx.cjs` 검토 및 수정: - `import-estx.cjs`에서 원본 ESTX 로드 시 기본 빈 공정표(`schedule: []`)를 명시적으로 초기화. - `export-estx.cjs`에서 원본 가져오기 기본 상태(`schedule: []`)와 대조하여, 유효 필드 유무와 무관하게 `project.schedule?.length > 0` (빈 문자열·0값만 가진 행, 임의 필드 행 포함) 존재 시 공정 데이터 누락 방지를 위해 JSON 저장 안내와 함께 차단(`웹 예정공정표는 ESTX에 저장할 수 없습니다. JSON 저장을 사용하세요.`). - `project.documents`의 공백 문자열(" ") 역시 사용자가 입력한 내용으로 취급하여 `text.length > 0` 검사로 누락 없이 JSON 저장 안내와 함께 차단(`웹 추가 서식 문서는 ESTX에 저장할 수 없습니다. JSON 저장을 사용하세요.`). - 원본 ESTX에서 불러온 기본 빈 상태(빈 schedule `[]`, 빈 documents `{}` 또는 미입력)에서는 정상적으로 ESTX 바이너리 패치가 통과되어 기존 기능 유지. - 관련 테스트: - `pytest resources/tester/test_est_attachments.py` 6개 통과 (일반 행, 빈 문자열/0값 행, 임의 필드 행, documents 공백 문자열 저장 차단 단위 검증). - `pytest resources/tester/test_est_native_export.py` 15개 통과 (`test_estx_export_schedule_and_documents_safety_guards` 실제 파일 기반 정상 패치 및 빈 행/0값/공백 문서 차단 실측 검증). - 전체 연계 회귀 시험 92개 통과 (0 실패). - [x] 예정공정표(schedule) 공정 항목 상/하 순서 이동(`schedule-move`) 및 전체 비우기(`schedule-clear`) 조작 구현 - 자체 검증: 1) `native-schedule.js`에 공정 행 상/하 이동(`moveRow`) 및 전체 비우기(`clearSchedule`) 구현: - 연속된 공정 항목 배열(`project.schedule`)에 대해 인접 행과 위치를 맞교환하는 `moveRow(project, index, direction)` 지원. - 상단 경계(`index === 0, direction === -1`) 및 하단 경계(`index === length - 1, direction === 1`) 도달 시 비활성화(`disabled`) 및 배열 범위 침범 방지. - 공정표 상단 툴바에 `공정 전체 비우기`(`data-action="schedule-clear"`) 버튼을 추가하고 확인 대화상자(`confirm`) 후 안전하게 초기화 지원(목록이 비어있으면 `disabled`). - 모든 조작은 `EstApp.change(..., false)`를 통해 수행되어 실행 취소(Undo)로 변경 전 공정 순서 및 데이터 완전 복원 가능. 2) 모델 검증 및 계산 무결성: - 이동 후에도 `EstSchedule.calculate(project)`를 통해 `left`, `width`, `weight`, 가중평균 `progress`, 전체 시작일/종료일이 정상 재계산됨을 확인. - Excel 내보내기/불러오기(`EstExchange`) 및 JSON 작업본 저장 시 순서 유지 확인. - 관련 테스트: - `pytest resources/tester/test_est_documents.py` 14개 통과 (`test_schedule_move_row_and_clear_operations` 추가). - 전체 연계 회귀 시험 85개 전수 통과 (0 실패). - [x] 동원인원·자재·장비 집계(resources) 화면 비목별(노임·자재·기계·표준·견적) 필터링 및 공종별 전개 조회 구현 - 자체 검증: 1) `native-extra.js`의 `view === "resources"` 렌더링 확장: - 전체 집계뿐만 아니라 비목 구분(노임 `kind: 6`, 자재 `kind: 5`, 기계 `kind: 105`, 표준 `kind: 21`, 견적 `kind: 101`, 전체 `all`) 필터 셀렉트(`id="resource-kind-filter"`) 추가. - 내역 공종별 세부 소요 전개 체크박스(`id="resource-by-work"`)를 추가하여, 체크 시 `EstResources.calculate(project, true)`를 호출해 공종코드(`WorkCode`) 및 공종명(`WorkName`) 열을 포함한 세부 전개 테이블 표시. - 필터링 결과 건수 표시(`(총 N건)`) 및 오류 메시지 보존. 2) `native-business-actions.js` 이벤트 연동: - `resource-kind-filter` change 시 `state.resourceKind`를 갱신하고 `EstApp.render()` 호출. - `resource-by-work` change 시 `state.resourceByWork`를 갱신하고 `EstApp.render()` 호출. 3) 원천 서식(`print-catalog.json`) 및 `EstForms.data` 일치 확인: - `112`(동원인원 공종별), `113`(소요자재 공종별), `114`(동원장비 공종별), `163`(동원실적 공종별), `164`(동원견적 공종별) 서식과 `13`(동원인원), `110`(소요자재), `111`(동원장비), `161`(동원실적), `162`(동원견적) 총괄 서식 간의 데이터 일관성 및 금액/수량 무결성 보존. - 관련 테스트: - `pytest resources/tester/test_est_documents.py` 13개 통과 (`test_resource_view_filtering_and_by_work_expansion` 추가 검증). - 전체 회귀 시험 69개 전수 통과 (0 실패). - [x] 기계경비(MachMainDat ↔ MachTitleDat) 당초 계약 단가 비교·설계변경 조회 및 데이터 보호(적용 미지원) 구현 - 자체 검증: 1) `native-machine.js` 검토 및 수정: - REA `f18804` 기계경비 계산 엔진(`EstMachine.calculate`)과 `MachTitleDat`를 대조한 결과, 기계경비 호표 단가는 `MachMainDat`의 상세 산출 공식에 의해 결정되며, `MachTitleDat`의 `TC_`/`NC_`/`GC_`/`JC_`는 설계변경 비교를 위한 당초 계약값임. - 당초 계약값은 현재 기준단가의 근거가 아니므로, 현재 단가를 과거 계약값으로 덮어쓰는 파괴적인 개별/일괄 적용 UI를 비활성화(`canApply: false`, 적용 버튼 미노출). - 코드 호출 시에도 안전하게 예외를 발생(`기계경비 호표는 MachMainDat 산출 결과이며 당초 계약값으로의 덮어쓰기 적용은 지원하지 않습니다.`)시켜 사용자 데이터 오염 및 자동 재계산 충돌을 원천 차단. - 신규 항목(`TC_ === null`)에 대해 0으로 왜곡하지 않고 `originalPrice: null`, `difference: null`, `status: "신규(당초없음)"`으로 안전하게 분기 표시. - 화면 안내 문구에 기계 호표 단가는 `MachMainDat` 산출 공식에 의해 결정되며 당초값 덮어쓰기는 지원하지 않음을 명시. 2) UI 및 서식 연동: - `index.html`, `native-app.js`, `native-extra.js`, `native-report.js`, `native-model.js`, `native-forms.js` 연동을 통해 사용 내역(`machine-usage`) 및 설계변경(`machine-change`)의 안전한 조회·인쇄 서식 지원. - 관련 테스트: - `pytest resources/tester/test_est_basic_prices.py` 5개 통과 (기계경비 당초/현재 비교, 신규 항목 TC_ null 안전 처리, 파괴적 apply 차단 및 데이터 불변 보존, Edge 브라우저 화면 조회 실측 검증). - 전체 연계 회귀 시험 56개 전수 통과 (0 실패). - [x] 호표(일위대가·단가산출·기계경비) 상세 행 이동(`move-estimate-up`, `move-estimate-down`) 및 단가산출 다중 -20 구간·참조 수치 무결성 보존 구현 - 자체 검증: 1) `native-business.js`에 `moveGroupDetailRows(rows, groupCode, selection, direction, table)` 구현 및 산출근거 다중 구간/참조 수치 무결성 검증 보완: - 일위대가(`HeadMainDat`), 단가산출(`CostMainDat`), 기계경비(`MachMainDat`)의 호표 상세 행에 대해 연속 선택 행의 상/하 이동 지원. - 호표 제목 행(`Index > 0`) 이동 차단 및 제목 행 건너뛰기 방지. - 선택 행이 해당 호표 범위를 벗어나거나 인접 호표의 영역을 침범하지 않도록 상/하 경계 보호(경계 도달 시 이동 없이 원래 인덱스 보존). - 합계/소계/구간비율 행(`LinkIndex` 54, 55, 58, 59, 61, 62) 및 합계 수식표지(`\x1a`) 포함 행의 이동 및 건너뛸 수 없도록 안전 차단. - **다중 소계 구간 시작 표지(`Index === -20`)의 개별 보존 및 다중 선택 경계 보호**: 이동에 참여한 국소 교환 위치 사이에서만 `-20` 표지를 정확히 교환하여, 호표 내 다른 소계 구간의 `-20` 표지(예: `D0000000005`의 다중 소계 구간)가 0으로 초기화되거나 왜곡되지 않고 완전히 유지되도록 수정. 선택 범위 내에 복수 `-20`이 포함되거나 범위 중간에 `-20`이 끼어 있어 단일 경계 스왑으로 보장할 수 없는 경우는 보수적으로 이동 차단. - **고유 식별자(`rowKey`) 매칭 및 앞줄 참조(`\x0c`) 수식/수치 불변 사전 검증(`validateCostOrderIntegrity`)**: PkID 유무와 관계없이 `rowKey(row, index)`를 통해 전수 매칭하여, PkID 누락 행에서도 정확한 전/후 대조 보장. 호표 최종 금액(`rows[0].TC`)뿐 아니라 각 소계(`LinkIndex === 61`)·비율(`LinkIndex === 58`) 행의 최종 금액, 그리고 앞줄 참조(`\x0c`)를 사용하는 모든 행의 `LineData` 수식 문자열이 완전히 동일하게 보존되는지 검증. 앞줄 참조(`\x0c`) 행이 포함된 복수 행 동시 이동은 안전한 구분을 위해 단일 행 이동으로 제한하고 차단. - **동일 결과값 선행 행 교환 시 뒤따르는 직전 결과 참조 대상 왜곡 방지 및 일반 행/변수 재정의 보수적 차단**: 뒤따르는 행이 특정 선행 결과를 직전 참조(`\x0c`)하는 구간에서, 동일 비목과 동일 결과값을 가진 선행 후보 행들이 2개 이상 존재할 때 이들 간의 순서 교환은 참조 대상이 왜곡되므로 보수적으로 이동 차단(`직전 결과를 참조하는 행이 뒤따라 참조 대상 구분이 불명확하므로 이동할 수 없습니다.`). `LinkIndex 58`뿐 아니라 일반 행(`LinkIndex !== 61`)의 `\x0c` 앞줄 참조 역시 선행 후보 행이 2개 이상일 때의 순서 교환을 보수적으로 차단. 동일 변수명 중복 할당(변수 재정의) 구간에 포함된 행들의 교환 시 전역 변수 사전 순서 의존성 왜곡을 방지하기 위해 이동 차단(`동일 변수(...)를 재정의하는 구간에서는 참조 대상 보존을 위해 이동할 수 없습니다.`). 2) `native-business-actions.js` 및 `native-views.js` 연동: - 툴바의 행 이동 버튼(`move-estimate-up`, `move-estimate-down`)이 내역서(`EstMainDat`)뿐 아니라 호표 화면(`HeadMainDat`, `CostMainDat`, `MachMainDat`)에서도 활성화되도록 노출. - 호표 화면 조작 시 `moveGroupDetailRows`를 호출하고 `EstApp.change()`를 통해 작업본 반영 및 실행 취소(Undo/Redo) 지원. - 관련 테스트: 1) `pytest resources/tester/test_est_change_workflow.py` 13개 전수 통과: - 일위대가 상세 행 이동 및 Edge 실측 시험. - 단가산출(`CostMainDat`)의 실제 사례(`D0000000004` 인부소계 구간)에서 상세 행 이동 후 소계(`14,373.6`) 및 호표 총액(`16,421`) 완벽 보존 검증. - 다중 `-20` 구간을 가진 실제 사례(`D0000000005`)에서 상세 행 이동 후에도 `-20` 표지 2개 및 1차 소계(`1,383.4`), 2차 소계(`1,407.8`)가 모두 보존됨을 검증. - A/B 동일값 선행 행 교환 시 직전 결과 참조 대상 왜곡 재현 및 보수적 차단 검증. - `LinkIndex 58` 이외 일반 행의 `\x0c` 앞줄 참조 모호성 차단 검증. - 동일 변수(`W`) 재정의 구간 행 교환 보수적 차단 검증. - 소계 행(`LinkIndex 61`), 비율 행(`LinkIndex 58`), 변수 산식 행(`D0000000000`의 Q식), 소계 수치가 왜곡되는 구간 침범 이동, 범위 중간에 `-20`이 포함된 이동, 앞줄 참조 복수 행 이동의 안전 차단 검증. - Edge 브라우저에서 단가산출 상세 행 이동, 소계 보존 및 실행 취소(Undo) 원복 실측 검증. 2) 원본 ESTX 무결성 보호 시험 14개 통과 (`pytest resources/tester/test_est_native_export.py`). 3) 핵심 비즈니스 및 가격 회귀 시험 28개 통과 (`test_est_basic_prices.py`, `test_est_standard.py`, `test_est_estimate.py`, `test_est_business.py`). 4) 주 수량 회귀 시험 12개 통과 (`test_est_quantity_workflow.py`). - [x] 자재단가(StuffcDat) 및 노임단가(LaborcDat) 사용 내역 화면과 기초단가 개별/일괄 적용 구현 - 자체 검증: ative-basic-prices.js를 신규 구현하여 자재단가(LinkIndex === 5) 및 노임단가(LinkIndex === 6)를 원천(StuffcDat, LaborcDat)과 비교하는 사용 내역(material-usage, labor-usage) 및 설계변경(material-change, labor-change) 화면 제공. 1) 자재는 GU, 노임은 NU 비목으로 원천 기초단가 반영 및 SCheck > 0 재분류 비목 보존. 2) 수동계산(AutoCalc = false) 시 원천 단가·비목은 변경하되 해당 행의 기존 금액(GC, NC, TC)을 강제 계산하지 않고 보존하며, AutoCalc=true 전환/재계산 시 수량(GN)을 반영해 전체 전파되도록 규칙 일치. 3) 화면 네비게이션, 인쇄 서식, 모델 검증 등록 및 EstApp.change() 연동 Undo/Redo 지원. - 관련 테스트: pytest resources/tester/test_est_basic_prices.py 4개 통과(단위 시험 및 Edge 브라우저 자재/노임 단가 적용, Undo 원복 검증). - [x] 견적단가 사용 내역 화면(estimate-usage) 및 기초단가(EstiMateDat) 개별/일괄 적용 구현 - 자체 검증: ative-estimate.js를 신규 작성하여 견적단가 원천(EstiMateDat, LinkIndex === 101)과 내역 행 간 단가 비교(usage), 차이 검출, 개별 적용(pplyRowPrice), 일괄 적용(pplyAllPrices) 구현. 1) 원천 비목 보존: 원천 비목 분할(InputGC, InputNC, InputJC) 유지 및 SCheck > 0 재분류 비목 보존. 2) 수동계산(AutoCalc = false) 시 원천 단가·비목은 변경하되 해당 행의 기존 금액을 보존하고, AutoCalc=true 전환/재계산 시 수량(GN)을 반영해 갱신되도록 수동계산 규칙 일치. 3) 화면 네비게이션, 인쇄 서식(estimate-usage, estimate-change), 모델 검증 등록 및 EstApp.change() 연동 Undo/Redo 지원. - 관련 테스트: pytest resources/tester/test_est_estimate.py 4개 통과(단위 시험 및 Edge 브라우저 개별/일괄 적용, Undo 원복 검증). - [x] 표준시장단가 사용 내역 화면에서 개별 및 일괄 기초단가 내역 적용·실행 취소 구현 - 자체 검증: ative-standard.js에 표준시장단가 원천(SilJukDat)과 내역 행(EstMainDat, LinkIndex === 21) 간 단가 차이가 있는 항목을 선별(canApply)하고, 개별 행 단위 적용(pplyRowPrice, data-standard-apply-row) 및 전체 차이 항목 일괄 적용(pplyAllPrices, data-standard-apply-all) 기능을 구현. 1) 적용 시 원천 자료의 고유성 검증: 원천 코드가 없거나 중복된 경우 임의 적용을 차단하고 예외 메시지 출력. 2) 원천 비목 보존 및 계산 규칙 일치: - 원천(SilJukDat)이 재료/노무/경비/실적 비목 분할(InputGC, InputNC, InputJC, InputSC)을 제공할 경우 이를 그대로 단가 비목(GU, NU, JU, SU)으로 반영. - 사용자가 설정한 비목 재분류(SCheck > 0: 재료/노무/경비 몰아주기)가 있을 경우 이를 임의로 해제하지 않고 해당 대상 비목으로 기초 단가 총액을 보존. - 수동계산(AutoCalc = false) 상태에서는 기존 내역 편집 및 est_estimate_classification_refreshes_only_selected_source_and_preserves_manual_mode 규칙과 일치하도록, 원천 단가 및 비목 분할은 반영하되 해당 행의 기존 금액(GC, NC, JC, SC, TC)을 강제 계산하지 않고 보존. 이후 AutoCalc=true로 전환하거나 재계산을 실행할 때 수량(GN)을 반영한 정식 금액으로 전파. 3) 화면 상단 툴바에 적용 대상 건수(기초단가 일괄 적용 (N건))를 표시하고 대상이 없으면 비활성화(disabled). 4) 작업본 반영은 EstApp.change()를 통해 이루어지므로 실행 취소(Undo)로 변경 전 단가 및 금액을 단계별로 완전 복원 가능. - 관련 테스트: pytest resources/tester/test_est_standard.py 5개 통과(수동계산 AutoCalc=false 보존 및 재계산 전환, 단위 시험 및 Edge 브라우저 개별/일괄 적용, Undo 원복, 비목 분할 보존, SCheck 보존 등), 연계 회귀 39개 통과. - [x] 수량산출 항목 단위(Unite) 편집 및 Title 테이블 메모 필드 보존을 통한 ESTX 저장·재열기 - 자체 검증: `native-quantity.cjs` 수량산출 화면에 단위(`Unite`) 편집 열 추가 및 `export-quantity.cjs`의 `withoutLabels`에 `Unite` 라벨 변경 차단 방지 반영. `native-engine.js`의 `saveTitles()`에서 `CostTitleDat`·`HeadTitleDat`·`MachTitleDat`의 식별자(`PkID`, `Index`, `RecNo`, `Flag`)뿐만 아니라 BLOB/메모 필드(`DifineMemo`, `SpaceMemo`, `EscData`)를 원본 Title 행 기준으로 보존(기존 Title에 없을 시 Main 값이 오염 생성되지 않도록 필터링). - 브라우저 검증: 임시 서버(127.0.0.1:5186)와 Edge에서 설치 `main.estx`를 열어 수량 항목 단위를 `m2`로 변경 후 ESTX 내보내기/다운로드, 브라우저 재열기 및 다른 수량 항목 보존·실행 취소 확인. (대용량 프로젝트 약 164MB에 따른 브라우저 임시 저장 용량 부족 경고 확인). - 관련 테스트: `pytest resources/tester/test_est_quantity_workflow.py` 12개 통과, 기존 `test_est_native_export.py` 14개는 수정 전 기반 통과 상태이며 이번 Title 보존 전용 시험(`test_recalculation_and_native_export_keep_original_title_identities_when_sample_exists`) 1개 통과(58.08s, 인덱스 `.idx` 동일성 및 단위 `m2` 보존). - 남은 제한: 원본 EST와의 실행 동등성은 미확인. - [x] 수량산출서 항목 추가·삭제 및 내역 연결·JSON 저장/재열기 지원 - 자체 검증: `native-quantity.cjs`의 수량산출 화면에 `수량 항목 추가`(`data-quantity-add-item`) 및 각 수량 항목 행에 `삭제`(`data-quantity-delete-item`) 버튼을 구현. 1) 항목 추가 시 기존 항목 코드(`r000000`, `r000001` ...)와 중복되지 않는 새 고유 코드 자동 생성(`r######`), 품명/규격/단위/수량 초기화 및 `EstApp.change()` 등록. 2) 항목 삭제 시 안전성 보장: 산출 행의 산출근거(`LineData`) 결과 표지(`\x12...\x12`) 및 `row.markers`에서 참조 중인 항목은 산출 행 결과 표지 수와 마커 수 불일치로 인한 계산 오류를 방지하기 위해 임의 삭제를 차단하고 사전 안내 메시지 출력. 미참조 항목에 대해서만 확인(`confirm`)을 거쳐 안전하게 삭제. 3) 품명·규격·단위 및 연결 내역 대상 지정(`TargetKey` / `TargetCode`) 후 JSON 작업본 저장 및 재열기 지원. 4) ESTX 바이너리로 표현 불가능한 임의 행 구조 변경(신규 산출서/항목 증감)에 대해서는 기존 ESTX 저장 시의 불변 무결성 보호를 유지하고 JSON 보관 안내. - 관련 테스트: `pytest resources/tester/test_est_quantity_workflow.py` 12개 통과 (신규 항목 추가, 참조 중인 항목 삭제 차단 안내 및 미참조 항목 안전 삭제 단위 시험 반영). - [x] 자료 오류 검색의 수량산출 항목 내역 대상 연결 검사, 해당 산출서 이동 및 검색 화면 내역 연결 지정 - 자체 검증: `native-issues.js`의 `scan()` 함수를 실제 수량 적용(`totals()`) 규칙과 정확히 일치하도록 개편: 1) `TargetKey` 우선 매칭(`id:${row.PkID}`): 두 행의 코드가 동일해도 `TargetKey`로 고유하게 연결된 경우 정상 판정하여 오탐 방지. 잘못된 키는 `수량 대상 내역 없음`으로 탐지. 2) `TargetKey`가 없을 시 `TargetCode ?? LinkCode` 대체값으로 매칭하며, `Level > 0`인 공종/비고 행 제외 규칙 일치. 3) 수량산출서(`quantitySheets`) 및 수식표 직접 작성(`quantities`) 항목 모두 검사하며 미연결/대상 부재 항목을 `unlinked`로 추출. 4) 오류 검색 화면에서 수량산출 오류 항목에 대해 `산출서 열기` 버튼을 제공하여, 클릭 시 `quantity` 뷰 및 해당 `quantitySheet` 코드로 즉시 전환·선택되도록 구현. 5) 자료 오류 검색 화면에서 미연결 또는 대상 부재인 수량 항목에 대해 바로 내역 행을 선택할 수 있는 드롭다운(`data-issue-target-select`)을 제공하여, 오류 검색 화면을 벗어나지 않고도 `TargetKey`(`id:${row.PkID}`) 및 `TargetCode`를 즉시 지정하고 `EstApp.change()`를 통해 JSON 작업본에 즉시 반영 및 실행 취소 가능하도록 구현. 6) `native-links.cjs`의 `existingTargets()`에서 고유한 `PkID`가 존재할 때만 `TargetKey`(`id:${row.PkID}`)로 안전하게 연결하고, `PkID`가 없는 동일 코드 행 간의 모호한 연결은 기존대로 미연결 유지 및 경고 처리 보존. - 관련 테스트: `pytest resources/tester/test_est_native_export.py::test_existing_quantity_links_respect_native_mode_and_avoid_ambiguous_targets resources/tester/test_est_issues.py` 5개 통과, `test_est_quantity_workflow.py` 12개 통과. Edge 브라우저 '산출서 열기' 클릭 시 수량산출서 전환 이동 및 오류 화면 내역 연결 드롭다운 선택 시 작업본(`TargetKey`) 즉시 연결 실측 확인. - [x] 테일스케일 전용 독립 서버 감시 프로세스(`watch-server.cjs`) 및 대용량 IndexedDB 캐시 복원 - 자체 검증: `server.cjs`의 외부 바인딩을 `EST_TEST_HOST=100.65.141.15:5175`로 한정(127.0.0.1 접속 시 ECONNREFUSED 차단 확인). Node 내장 `--watch` 기반 감시 프로세스(`watch-server.cjs`)를 구현해 `data/` 및 로그를 제외한 `.js`·`.cjs` 소스 변경 시에만 자동 재기동되도록 구성(파일 touch 시 자동 재기동 및 헬스 200 확인). `server.cjs`를 require하는 테스트 실행 시 watcher hang 없음 확인(`test_est_quantity_workflow.py` 12개 2.69s 통과). - 대용량 임시 저장 보완: `native-app.js`에서 sessionStorage(약 5~10MB) 용량 초과 시 IndexedDB(`est-independent-cache`)로 자동 대체 저장·복원하도록 개선하여, 대용량(main.estx 약 157MB JSON) 작업 시 새로고침 유실 문제를 해결함. IndexedDB 트랜잭션 `waitForTx(tx)` 대기 및 순차 직렬화 큐(`cacheQueue`)를 적용해 연속 입력 시 덮어쓰기 레이스 컨디션을 방지하고, 탭별 고유 인스턴스 ID(`sessionStorage`의 `est-tab-instance-id`) 및 Chromium 탭 복제 시 `window.name` 리셋 감지를 적용해 복제 탭(Duplicate tab) 분리 격리 및 부모 작업본 초기 상속을 구현함. 실제 headless Edge 기반 Playwright 회귀(`resources/tester/test_est_browser_cache.py`)로 소형 데이터 격리, 대용량 `main.estx`(22MB 바이너리, 157MB JSON) 업로드 후 이름 수정→IndexedDB 저장→새로고침 복원(76개 전체 내역행 유지), 캐시 실패 안내 메시지 검증 및 탭 복제(Duplicate Tab) 상속·독립 격리 시험 통과(3 passed in 13.04s). - 백그라운드 상태 감시 및 자동 알림: `tools/est-test/monitor.cjs`를 통해 15초 주기로 `orca.exe` CLI(`shell: false`, timeout 4~5s)를 호출하여 CODEX 워크트리의 안티그래비티 작업 상태와 EST 5175 서버 헬스를 조회하고, 상태 변경 시에만 `monitor.log`에 기록(최대 512KB 순환). 안티그래비티 완료/대기 전이 시 Codex Orchestration Run(`run_cdb1558b9280`)으로 단발성 자동 알림(`status`/`messageId=msg_2c7bca748f91`)이 실제 전달됨을 확인(중복 폭주 방지 플래그 적용, 민감 환경변수 미기록, 재시작/자동지시 없음). ## Codex · EST 독립 테스트 앱 (2026-11-04) - [x] 일위대가 상세 비목 지정 변경을 해당 행에만 반영 → 자동·수동 계산, 원천 불일치·다른 호표 보존 시험. - 자체 검증: 관련 시험 33개 통과. Tailscale HTTP Edge에서 자동·수동 계산, 다른 호표 보존, 원천 단가 불일치 시 복원 차단 및 화면 오류 0 확인. - [x] 원천 재조회가 꺼진 내역의 비목 지정 변경을 해당 행에만 반영 → 자동·수동 계산, 미연결·다른 행 보존 시험. - 자체 검증: 현재 단가를 유지한 비목 지정·일치하는 원천으로 복원, 다른 행·재조회 옵션 보존. 원천 누락·중복·단가 불일치는 복원 차단. Edge에서 자동·수동 계산 확인, 관련 시험 32개 통과. - [x] 산출근거 문구 일괄 바꾸기 → 현재 호표·전체 범위, 표지 보존·재계산·실행 취소 확인. - 자체 검증: Tailscale HTTP Edge에서 현재 호표·전체 치환, 일치 없음 안내, 결과·단가 표지 보존과 실행 취소 확인. 산출근거 시험 24개 통과, 수식 변경 후 재계산 확인. - [x] Excel 파일 읽는 동안 파일·셀 선택이 바뀌면 이전 요청 반영 차단 → 지연 응답 시험. - 자체 검증: 지연된 Tailscale HTTP 응답 동안 셀과 파일을 각각 변경하면 이전 요청 반영이 차단되고 다시 실행은 성공. 수량 시험 12개 통과. - 자체 검증: 수량·Excel·설계변경·기성·물가변동·연차·문서·오류 기능 회귀 69개 통과(openpyxl 경고 8건). 원본 동등성 대조는 실행하지 않음. - [x] 계산 불일치 수량산출서의 계산값을 바꾸지 않는 문구 수정 저장 → 원본 수량·표지 보존과 수량 변경 차단 확인. - 자체 검증: main.estx N0000000083 문구를 수정해 저장·재열기한 뒤 원래 수량 286과 다른 행 보존. 산식 계산값·결과 표지 변경 차단, 기존 산식 저장 시험 통과. - [x] 삭제된 Excel 연결 대상의 행 식별자 재사용 방지 → 새 행·붙여넣기·Excel 가져오기 오연결 차단. - 자체 검증: 삭제된 2번을 예약해 Edge 추가·붙여넣기가 3·4번을 사용. Excel 가져오기 오연결 차단·연결 제거 후 적용 확인. 관련 시험 35개 통과, openpyxl 경고 8건. - [x] Excel 수량 연결을 전체 자료 Excel에 포함 → 재가져오기와 잘못된 내역 연결의 전체 적용 차단 확인. - 자체 검증: Tailscale HTTP Edge에서 실제 Excel 내보내기·재가져오기와 잘못된 내역 연결 전체 차단 확인. 수량·Excel 시험 25개 통과, openpyxl 경고 8건. - [x] Excel 셀과 내역 행 연결을 JSON에 보관하고 다시 선택한 파일로 일괄 갱신 → 중복·누락·오류 시 전체 변경 차단. - 자체 검증: Tailscale HTTP Edge에서 2행 연결·JSON 재열기·일괄 갱신·실행 취소·연결 해제 확인. 한 셀 오류 시 두 행 모두 유지, ESTX 저장에서 연결 누락 차단. 수량·첨부·독립 서버 시험 25개 통과. - [x] Excel 숫자 셀을 선택한 내역 행의 수량으로 반영 → 파일·시트·셀 오류 차단, 계산·저장·취소 확인. - 자체 검증: Tailscale HTTP Edge에서 실제 xlsx B2=6.25 반영·금액 625·취소·JSON 저장, 문자·미계산 수식·누락·범위 오류 차단 확인. 수량·Excel 시험 23개 통과, openpyxl 경고 7건. 자동 파일 감시는 없음. - [x] Tailscale HTTP에서 수량산출서와 산출 행 생성 → 생성·JSON 저장·복원 확인. - 자체 검증: Tailscale HTTP Edge에서 산출서·행 생성, JSON 저장·재열기 확인. 수량·독립 서버 시험 19개 통과. - [x] 기존 계산 불일치 수량산출서도 품명·규격만 바꿀 때 원본 수량 유지 → 실자료 재열기 확인. - 자체 검증: 설치 main.estx N0000000083의 저장 286·재계산 100.1 불일치 항목에서 품명만 변경한 뒤 원본 수량 286·문서·다른 문서 보존 확인. 저장·서식 시험 2개 통과. - [x] 기존 수량산출 항목의 품명·규격을 ESTX에 저장 → 재열기·다른 항목 보존·연결 변경 차단 확인. - 자체 검증: 설치 main.estx 기존 항목의 품명·규격 저장·재열기, 다른 항목·문서 보존과 연결 변경 차단 확인. 저장·수량 관련 시험 22개 통과. - 추가 검증: 품명·규격과 산식을 함께 수정한 ESTX의 수량 104→116, 다른 문서·인덱스 보존 확인. - [x] 인쇄 서식의 상·하·좌·우 여백 개별 설정과 ESTX 저장 → 기존 단일 여백 호환·실제 서식 재읽기 확인. - 자체 검증: 거창 ESTX 여백 13·14·15·16mm 미리보기·JSON 저장과 기존 단일 여백 호환을 Edge에서 확인. 설치 샘플 ESTX 저장·재읽기 포함 관련 시험 24개 통과. - [x] 산출근거 계산 오류에서 해당 행으로 이동 → 실무 ESTX 오류와 중복 코드 안전 처리 확인. - 자체 검증: 거창 실무 ESTX의 D0000000194:18 계산 오류에서 원본 해당 행으로 Edge 이동 확인. 중복 코드·범위 오류 차단 포함 시험 12개 통과. - [x] 다른 이름으로 저장할 때 작업 이름 입력 → 원본·복사본 구분과 저장 취소 확인. - 자체 검증: Tailscale HTTP Edge에서 빈 이름 차단, 별도 이름·ID의 사본 저장과 기존 파일 보존 확인. - [x] Tailscale HTTP 접속의 새 항목·첨부·공정 생성 오류 수정 → 실제 원격 주소에서 생성과 저장 확인. - 자체 검증: Tailscale HTTP Edge의 비보안 컨텍스트에서 UUID·공정·첨부 생성·JSON 저장 확인. 관련 시험 31개 통과. - [x] EST 백업 EBKX 파일 열기 → 실무 백업 읽기·JSON 저장·재열기 확인. - 자체 검증: 거창 실무 EBKX의 내역 106행을 Edge에서 열고 JSON 저장·재열기; 독립 서버 시험 9개 통과. 원본 EST에서의 백업 호환성은 미확인. - [x] Tailscale 주소에서 독립 테스트 서버 접속 → 접속과 계산 요청 확인. - 자체 검증: Tailscale IP에서 Edge 화면과 계산 POST 200, 다른 출처 403 확인. 다른 PC에서의 접속은 미확인. - [x] 표준시장단가 설계변경 내역·증감 화면·출력 구현 → 신규·삭제·연결 변경 시험. - 자체 검증: 표준 내역의 신규·삭제·연결 변경과 문서 기능 시험 21개 통과. Edge에서 증감·삭제 행·인쇄·내역 이동 확인. - [x] 표준시장단가 사용 내역·기초 단가 비교 화면·출력 구현 → 연결·중복·누락·행 이동 시험. - 자체 검증: 연결 단가·중복·누락·문서 시험 12개 통과, Edge에서 화면·인쇄·해당 내역 이동 확인. - [x] 추가 인쇄 서식의 본문 저장·미리보기·Excel 연결 보완 → 서식 문서 검증·재열기 시험. - 자체 검증: 문서·Excel 시험 24개 통과, Edge에서 본문 저장·재열기·인쇄·Excel 요약 확인. - [x] 기성 회차 이름 변경·추가 시 중복 방지 → 공백·기존 이름 충돌 시험. - 자체 검증: 기성·업무 시험 22개 통과, Edge에서 공백 중복 이름 거부·새 이름 생성 확인. - [x] 첨부파일 추가 전 256MB 저장 한도 확인 → 대형 파일 차단·기존 작업 보존 시험. - 자체 검증: UTF-8·base64 실제 저장 크기 일치·한도 계산 포함 4개 통과. Edge에서 초과 파일 읽기 전 차단·안내 확인. - [x] 전체 수량 반영 시 중복·예약 산출서 코드 차단 → 중복 합산 방지 시험. - 자체 검증: 중복·빈·예약 코드 차단과 기존 수량 보존 포함 시험 19개 통과. - [x] 선택 또는 전체 상세 내역 수량 초기화 → 비율·합계 보존·실행 취소 시험. - 자체 검증: 설계변경·이력 시험 9개 통과, Edge에서 선택·전체 초기화, 비율 보존과 취소 확인. - [x] 전체 기성 회차 초기화 구현 → 내역·다른 업무 보존·취소 시험. - 자체 검증: 기성·이력 시험 9개 통과, Edge에서 초기화·다른 업무 보존·확정 회차 취소 복원 확인. - [x] 로컬 첨부파일 추가·내려받기·삭제·JSON 보관 구현 → 파일 바이트·저장·취소 시험. - 자체 검증: 입력 검증·ESTX 누락 차단 시험 2개 통과, Edge에서 파일 추가·JSON 저장·재열기·바이트 내려받기·삭제 취소 확인. 업무 회귀 시험 82개 통과(openpyxl 경고 7건). - [x] 선택 행 자릿수·사사오입·절사·올림식 일괄 설정 → 선택 범위·재계산·취소 시험. - 자체 검증: 업무·수량 시험 21개 통과, Edge에서 두 행 절사 2자리 설정·다른 행 유지·재계산·실행 취소 확인. - [x] 일위·산근·기계 묶음 복사 시 기존 코드 충돌 방지 → 묶음·행 보존 시험. - 자체 검증: Edge에서 세 자료의 중복 코드 회피와 복사된 묶음 자식 행의 부모 연결 확인. - [x] 모든 수량산출서·직접 수식표의 내역 수량 일괄 합산 반영 → 동일 대상 합산·오류 시 전체 차단 시험. - 자체 검증: 동일 내역 합산·오류 시 전체 차단 포함 수량·문서 시험 18개 통과, Edge에서 일괄 반영·취소 확인. - 2026-11-07: 사용자 지시로 EST 작업 계획과 검증 기록을 공유 PLAN.md에서 이 파일로 이관. 업무 회귀 시험 79개 통과, openpyxl 경고 7건. Git push는 보류. - [x] 자료 오류 검색 화면과 해당 행 이동 구현 → 중복·누락 연결·품명·규격 차이 시험. - 자체 검증: 중복·누락·품명·규격 차이 시험 포함 19개 통과. Edge에서 오류 목록과 내역 행 이동 확인. - [x] 계약심사 화면에서 주요심사내용 작성·저장·출력 연결 → 입력·재열기·인쇄 시험. - 자체 검증: 심사·문서 시험 17개 통과. Edge에서 작성·저장·재열기·인쇄 확인. - [x] 계약심사 비목 누락 고정금액·중복 식별 처리 보완 → 잘못된 합계·다중 반영 차단 시험. - 자체 검증: 고정금액 비목 합계 오류·중복 식별 입력 차단을 포함해 시험 29개 통과, Edge 화면 확인. - [x] 직접 작성 수량 수식표 항목 이동 구현 → 수식 참조·저장·실행 취소 시험. - 자체 검증: 수량·문서 시험 17개 통과. Edge에서 이동 뒤 참조 오류·서버 저장·재열기·실행 취소 확인. - [x] 최근 확정 기성의 누계 수량을 예정공정표 진도로 반영 → 연결·범위·기존 일정 보존 시험. - 자체 검증: 최근 확정 회차·미연결·수량 0·범위 오류·일정 보존 포함 시험 18개 통과, Edge 진도 반영과 실행 취소 확인. - [x] 인쇄 서식의 계산 결과를 Excel 표로 내보내기 구현 → 실제 Excel 열기·수치 확인. - 자체 검증: Edge에서 연차 내역 Excel 다운로드·한글 제목·금액 확인. 요약·오류·수치·입력 검증 포함 문서·Excel 시험 22개 통과(openpyxl 경고 7건). - [x] 연차별 개별 내역·배분 금액 출력 구현 → 차수별 계산·수식 오류 시험. - 자체 검증: 차수별 배분·오류 표시 포함 문서·연차 시험 13개 통과, Edge 연차 내역 미리보기 확인. 업무 회귀 시험 74개 통과(openpyxl 경고 6건). - [x] 물가변동의 중복 코드 내역을 당초와 개별 연결 → 계약·적용제외 계산 시험. - 자체 검증: 중복 내역의 개별 계약 단가·적용제외 포함 시험 24개 통과, Edge에서 계약 단가 80·50 표시 확인. - [x] 기성 입력·일괄 적용의 중복 행 식별 차단 → 계산·확정·일괄 적용 시험. - 자체 검증: 중복 행 계산 및 확정 차단·다른 행 계산 포함 14개 통과, Edge 개별·일괄 입력 차단 확인. - [x] 기성 누계수량의 물가변동 연결 보완 → 중복 식별 차단·신규 행 입력 보존 시험. - 자체 검증: 중복 식별 차단과 신규 행 입력 보존 포함 시험 13개 통과, Edge 기성 누계 불러오기 확인. - [x] 행 복사·붙여넣기에서 다른 종류의 자료가 섞여 손상되지 않도록 제어 → 동일 자료 복사·오류 시험. - 자체 검증: Edge에서 다른 자료 종류의 붙여넣기를 차단하고 동일 자료 복사는 유지하는 것을 확인. - [x] 내역 선택 행 위·아래 이동 구현 → 행 식별·소계 보호·취소 시험. - 자체 검증: 연속 행 이동·소계·식별자 차단 시험 21개 통과, Edge에서 이동·기성 입력 유지·실행 취소 확인. - [x] 설계변경 중복 코드 내역의 당초 행 매칭 보완 → 증감·삭제 시험. - 자체 검증: 같은 코드의 다중 내역과 삭제 행의 당초 금액 분리를 포함한 시험 20개 통과. - [x] 설계변경 원가 비목별 당초·변경·증감 화면과 출력 구현 → 삭제·신규·중복 구분 시험. - 자체 검증: 중복·신규·삭제 및 행별 당초 값 포함 시험 15개 통과, Edge 화면과 인쇄 미리보기 확인. - [x] 물가변동 원가 비목별 계약·조정·제외 금액 인쇄 구현 → 계산 결과 시험. - 자체 검증: 기성·물가변동·문서 시험 21개 통과, Edge 미리보기에서 기성·물가변동 원가와 연차 출력 확인. - [x] 기성 원가계산서 인쇄 구현 → 회차별 전회·금회·사정·누계 시험. - 자체 검증: 확정 및 다음 회차 금액 포함 시험 15개 통과. - [x] 물가변동 전용 Excel 입력과 조사 도급액 입출력 구현 → 행 식별, 오류 차단, 계산 반영 시험. - 자체 검증: Excel 관련 시험 12개 통과, Edge에서 실제 파일 수정과 가져오기 확인. - [x] 연차 배분 계산 결과와 수식을 출력하는 서식 구현 → 차수별 계산과 오류 표시 시험. - 자체 검증: 차수별 금액과 잘못된 수식 오류 표시 포함 시험 11개 통과. - [x] 기성 회차와 물가변동 결과 인쇄 서식 구현 → 확정 회차 보존과 계산 결과 시험. - 자체 검증: 결과 출력 및 확정 회차 보존 시험 포함 18개 통과, Edge 미리보기에서 두 서식 확인. - 2026-11-07 사용자 지시: 동등성 대조와 Git push 보류, CAD 제외 기능 구현 우선. - 기능 회귀(2026-11-07): 수량·Excel·심사·설계변경·기성·물가변동·연차·공정·이력 관련 60개 통과(28.41초), openpyxl 날짜 API 경고 5건. 원본 동등성 대조는 실행하지 않음. - [x] 수량산출서 신규 생성·이름 변경·산출 행/항목 추가·삭제 및 내역 반영 → 화면 조작과 JSON 저장/복원 시험. - 자체 검증(2026-11-07): 수량 화면에서 새 산출서 생성, 항목 추가·품명 변경, `2*3` 계산과 내역 6 반영, 서버 JSON 저장·재열기. Edge 브라우저 오류 0, 이벤트 기능 시험 2개 통과. 설치 원본과의 동등성 대조는 사용자 지시에 따라 수행하지 않음. 신규 산출서/행 구조 변경의 원본 ESTX 쓰기는 미지원. - [x] 수량산출 행의 순서 변경과 선택 위치 삽입 → 계산 참조 순서·결과 표지 연결 확인. - 자체 검증(2026-11-07): 이벤트 시험에서 항목 결과 3·9·13 보존, 선언 이전 참조 오류 확인. Edge에서 행 아래 삽입·위로 이동 및 JSON 저장 후 재열기, 항목 결과 3·9 유지·브라우저 오류 0. - [x] 기존 수량 연결의 변경 및 해제 → 비운 연결이 원래 연결로 되살아나지 않는지 확인. - 자체 검증(2026-11-07): 기존 LinkCode가 있더라도 TargetCode를 빈 값으로 설정하면 해당 내역 수량을 변경하지 않음. 수량 기능 시험 3개 통과. - [x] 수식표와 산출서의 내역 반영을 같은 연결 검사로 처리하고 재계산 메뉴에서 선택한 자료를 반영 → 대상 누락·중복·수식 오류 시 전체 변경 차단. - 자체 검증(2026-11-07): 수식표 참조 합계 8, 선택 산출서 9, 기존 MulCode 보존, 없는 대상의 전체 변경 차단. Edge 재계산 메뉴에서 선택 산출서 9·직접 작성 수식표 8 반영, 브라우저 오류 0. 수량·이력 관련 5개 통과. 다른 프로젝트를 열 때 이전 산출서 선택이 남지 않도록 초기화. - [x] 예정공정표에 내역 일괄 추가와 금액 가중치 갱신 → 기존 일정·진도 보존 및 중복 방지 시험. - 자체 검증(2026-11-07): 같은 코드 2행과 코드 없는 1행을 행 식별자로 구분하고 재추가를 방지, 내역 순서 변경 뒤에도 금액을 연결. 일정·진도·이름 유지 및 연결 모호성 차단을 기능 시험. Edge에서 3행 추가·재추가 방지·금액 200/300/400 갱신 및 JSON 저장, 오류 0. 설치 내역의 코드 없는 39행도 공정 추가 가능함을 확인. 원본과의 동등성 대조 미실시. - [x] 수식표 항목 삭제 후 새 항목 추가 시 중복되지 않는 산출코드 생성 → 삭제·재추가와 참조 계산 시험. - 자체 검증(2026-11-07): 남은 Q2가 삭제된 Q1을 참조할 때 새 항목을 Q3으로 생성해 참조가 새 항목에 잘못 연결되지 않음을 Edge에서 확인. 수량·공정 기능 시험 9개 통과. - [x] 설계변경 비교에서 코드가 없는 내역도 품명과 수량·금액을 표시 → 당초·변경 차액과 화면 표시 시험. - 자체 검증(2026-11-07): 코드 없는 `earthwork` 내역의 당초 100·변경 200·증감 100이 화면에 표시되는지 Edge와 기능 시험으로 확인. 관련 기능 시험 13개 통과·브라우저 오류 0. - [x] 수량산출서 인쇄에 직접 작성 수식표와 산출서의 실제 수식·계산값·연결을 표시 → 계산 오류와 출력 데이터 시험. - 자체 검증(2026-11-07): 수식표 2·참조 결과 6, 오류 수식의 계산 오류, 산출서 4+5 결과 9·연결 내역을 출력 데이터로 확인. Edge 인쇄 미리보기에서 두 종류의 산식과 결과 표시·브라우저 오류 0, 수량·설계변경·공정 기능 시험 14개 통과. - [x] 수량산출과 직접 수식표에서 코드 없는 내역과 중복 코드의 개별 내역 행 연결 → 선택·계산·저장·재열기 시험. - 자체 검증(2026-11-07): 같은 코드의 두 내역 중 둘째 행과 코드 없는 내역에 각각 6·9를 반영하고 JSON 저장·재열기 및 인쇄에서 대상 확인. 직접 수식표의 코드 없는 행 선택·결과 5 반영·연결 해제, 내역 순서 변경 뒤 식별자 유지, 잘못된 식별자 차단. Edge 오류 0, 기능 시험 15개 통과. - [x] 연차 차수 위·아래 이동과 중복·기존 참조를 피하는 신규 차수 이름 생성 → 참조 순서 오류·저장 복원 시험. - 자체 검증(2026-11-07): 기존 2차가 삭제된 1차를 참조하면 새 이름을 3차로 생성. Edge에서 2차를 1차 앞으로 이동했을 때 참조 오류 표시, 변경 순서 저장, 다시 원래 순서로 옮겨 오류 해소 확인. 연차·수량 기능 시험 10개 통과, 브라우저 오류 0. - [x] 계약심사 화면: 사용자가 심사 수량·비목별 단가를 입력하고 기존 내역/심사액·차액을 비교, 심사 사본 열기와 JSON 저장 → 입력·원가 재계산·취소·저장/복원 시험. 자동 심사율·법적 기준은 정하지 않음. - 자체 검증(2026-11-07): 일반 단가 행과 고정금액 행을 수정해 원가 포함 기존 1,210→심사 198 계산, 기존 내역 보존·실행 취소·JSON 저장/재열기·독립 ID의 심사 사본 확인. 잘못된 입력·없는 행의 사본 생성 차단. Edge 오류 0, 관련 기능 시험 47개 통과(25.68초). 원본 계약심사 동작 대조는 수행하지 않음. - [x] 계약심사 결과요약서에 기존액·심사액·차액과 내역별 비교 출력 → 출력 데이터·미리보기 확인. - 자체 검증(2026-11-07): 기존 200·심사 80·차액 -120 및 코드 없는 내역을 요약서 출력 데이터와 Edge 인쇄 미리보기에서 확인. 심사·문서 관련 8개 통과, 브라우저 오류 0. - [x] 직접 작성 수식표·예정공정표 Excel 내보내기와 가져오기 → 참조 수식·내역 행 연결·일정·진도 유지 및 잘못된 입력 차단. - 자체 검증(2026-11-07): Edge에서 Excel 내려받기→openpyxl로 수식·진도 변경→가져오기 및 내역 식별자 보존. 중복 코드·소수자리·진도 오류 차단, Excel·수량·공정 관련 17개 통과. openpyxl 환경의 날짜 API 사용 중단 경고 2건, 실패 0. - [x] 산출근거의 내부 표지 문자가 Excel 파일을 손상하지 않도록 인코딩·복원 → 원본 표지와 표지처럼 생긴 일반 문자 왕복 확인. - 자체 검증(2026-11-07): 제어 문자가 포함된 Excel 파일이 XML 파싱에 실패하던 상황을 재현한 뒤, 표지와 일반 문자열 `_x0012_`를 구분해 저장·openpyxl 편집·브라우저 재가져오기 왕복 확인. Edge 오류 0. - [x] 수량산출서 문서·산출 행·항목의 Excel 내보내기와 편집 후 가져오기 → 표지·내역 연결 보존 및 계산 확인. - 자체 검증(2026-11-07): 세 Excel 시트 내보내기, 산출 행 2×3→2×4와 품명 수정 후 가져오기, 표지·내역 행 연결·Excel 미표시 속성 보존 및 내역 수량 8 반영을 Edge에서 확인. 누락 시트·잘못된 표지·중복 순서 차단과 빈 원래 필드 유지, 수량·Excel 기능 시험 14개 통과. Edge 오류 0; openpyxl 날짜 API 사용 중단 경고 3건, 실패 0. - 추가 보완: 기존 `LinkCode`만 있는 항목은 Excel에서 연결을 변경하지 않았을 때 새 연결 필드를 덧붙이지 않고 원래 구조를 유지. - [x] 수량산출 행 편집 중 결과 표지가 삭제되거나 추가되면 이전 저장 수량이 잘못 적용되지 않도록 차단 → 화면·Excel 편집 후 계산 시험. - 자체 검증(2026-11-07): 결과 표지가 0개 또는 2개인데 연결 표지가 1개인 행의 계산 오류와 내역 반영 차단, 기존 수량 1 유지. Edge에서도 표지 삭제 후 반영 차단·오류 0, 수량·Excel 기능 시험 15개 통과. - [x] 계약심사 항목별 검토 사유 입력·저장 및 요약서 출력 → 금액 재계산과 사유 보존 시험. - 자체 검증(2026-11-07): 심사 단가 변경과 한글 사유 입력 후 JSON 저장·재열기, 심사액 160과 요약서 사유 표시를 Edge에서 확인. 관련 기능 시험 8개 통과, 브라우저 오류 0. - [x] 계약심사 입력·사유 Excel 내보내기와 수정 후 가져오기 → 내역 행 연결·재계산·입력 검증 시험. - 자체 검증(2026-11-07): Excel `Review` 시트에서 심사 단가 80→60과 사유를 변경해 가져온 뒤 심사액 120 및 화면 사유 표시 확인. 중복 식별자·잘못된 숫자·식별자 오류 차단, 심사·Excel 기능 시험 12개 통과. Edge 오류 0, openpyxl 날짜 API 경고 4건. - [x] Excel 계약심사 입력이 존재하지 않거나 중복된 내역을 가리키면 가져오기 자체를 차단 → 다른 표 교체도 함께 취소되는지 확인. - 자체 검증(2026-11-07): 없는 내역 및 해당 행에서 사용할 수 없는 비목 입력 차단. Edge에서 잘못된 심사 행과 내역 수량 변경을 함께 가져왔을 때 두 변경 모두 적용되지 않음 확인. 심사·Excel 시험 14개 통과, 브라우저 오류 0. - [x] 계약심사 개별 행의 입력·사유 초기화 → 다른 행 입력과 실행 취소 보존 시험. - 자체 검증(2026-11-07): 한 행만 초기화해 다른 행의 수치·사유 유지, 마지막 행까지 초기화 시 심사 작업 비우기. Edge 실행 취소로 초기화된 사유 복원, 심사 기능 시험 4개 통과, 브라우저 오류 0. - [x] 계약심사 고정금액 행의 사유·수량만 변경해도 기존 금액이 유지되도록 처리 → 비목 금액 변경과 구분 시험. - 자체 검증: 수정 전 문제 재현, 수정 후 금액 유지와 비목 변경 재계산 확인. 관련 시험 16개 통과. - [x] 연차 차수와 미확정 기성 회차·입력 Excel 편집 → 확정 회차의 계약·누계 보존 및 가져온 업무 계산 시험. - 자체 검증(2026-11-07): 확정 회차는 내보내기 대상에서 제외하고 기존 계약·누계를 그대로 유지. Edge에서 미확정 금회 수량 1→3, 연차 수식 50%→25%를 Excel로 변경해 가져온 뒤 기성 누계 500·연차 250 확인. 없는 행·확정 회차·중복 ID·잘못된 입력 차단, Excel·기성·연차 시험 22개 통과. Edge 오류 0, openpyxl 날짜 API 경고 5건. - [x] 내역·일위대가 행의 경비성단가(ActionSetJCBimog) 및 순공사비 경계 행(popMainSetTotalSumLine) 화면 조작 메뉴와 토글 재계산 지원. - 자체 검증(2026-11-08): REA ActionSetJCBimog(0xf17c10/0x10dba14) 및 popMainSetTotalSumLine 근거를 기반으로 `toggle-jc-bimog`, `toggle-sun-gongsa` 조작 액션 구현. 1) 경비성단가 보존 및 복원: SCheck=1(재료) 또는 2(노무) 상태에서 경비성단가 지정(SCheck=3) 후 해제 시 원래의 SCheck 값(`_prevSCheck`)으로 온전히 복원(기존 비목별 0으로의 왜곡 차단), 노무비(SCheck=2, NU=2000)가 SCheck=3 전환 후 해제 시 SCheck=2, NU=2000으로 복원됨을 검증. 2) 순공사비 연결 행 보호: 원천 연결(자재/노임/일위/단가/기계 등 LinkIndex 5, 6, 21, 51, 52, 55, 57, 58, 61, 62, 67, 68, 101~105) 또는 코드·수량이 있는 상세 행의 순공사비 경계선 지정을 안전하게 차단(`"단가·수량 연결 행이나 기존 특수 공종 행은 순공사비 경계선으로 지정할 수 없습니다. 빈 제목/구분 행을 선택하세요."`). 3) 순공사비 속성 보존/복원: 기존 54 행이 있을 때 새 행을 순공사비로 지정하거나 해제 시 원래의 `LinkIndex`와 `Name`(`_origLinkIndex`, `_origName`)으로 정확히 복원됨을 검증. 4) 안전성 거부 4건(비허용 화면 호출, 선택 없음, 복수 순공사비 지정, 원천 연결 상세행 지정 거부) 전수 확인. 신규 전용 시험 `resources/tester/test_est_row_actions.py` 통과. - [ ] 남은 웹 업무 기능을 이어서 구현하고 각 기능의 입력·계산·저장 흐름 확인. - [x] ESTX 원본 옵션·공사명 및 기존 BLOB 확장 저장 구현 → 설치 샘플 재읽기와 인덱스·다른 자료 보존 확인. CAD 제외. - 자체 검증(2026-11-06): 설치 sample.estx에서 한글 공사명·자동계산·절사·자릿수 변경과 BLOB 12,000바이트 확장 저장 후 재읽기, 다른 속성·전체 인덱스·CAD 보존 확인. EST 전용 100개 통과(51.80초). 독립 파서 대조이며 원본 EST에서 파일을 열어보지는 못함. - [x] WPTools 수량산출서의 기존 서식 구간 안 텍스트 편집 저장 → 실제 수량산출서 샘플 재읽기와 다른 문서 보존 확인. - 자체 검증(2026-11-06): main.estx의 75개 수량산출서 중 한 문서 편집·재읽기, 나머지 문서·인덱스·CAD 유지, 서식 구간을 가로지르는 편집 거부 확인. EST 전용 102개 통과(70.77초). 원본 EST 직접 실행 비교는 미실시. - [x] 원본 결과와 기존 계산이 일치하는 수량산출서의 결과 표지·수량 목록 재계산 저장. - 자체 검증(2026-11-06): main.estx 수량산출서 폭 9→10 변경 시 표지 및 목록 수량 104→116으로 기록·재읽기, 다른 문서·인덱스·CAD 보존. EST 전용 102개 통과(70.78초). 계산 오류·기존 결과 불일치 문서는 저장을 거부하며 원본 EST 실행 검증은 미실시. - [ ] 서식 구간을 넘는 수량산출서 편집과 목록·연결 변경 지원; 계산 오류나 기존 결과 불일치 문서의 처리 확인. - 진행 및 미완료 범위(2026-11-08): 1. 서식 편집 지원: 수량산출서 편집기에서 위첨자(`^(2)` 등) 및 복합 서식 태그 경계를 가로지르는 텍스트 수정(`abc^(2)def` -> `abc^(3)xyz`) 시 분할된 서식 런을 유지하며 인라인 패치 적용 확인 (`test_quantity_document_edit_across_styles_and_superscript_preserves_structure` 통과). 2. 불일치 문서 처리: 원본 저장 수량과 산식 계산 결과가 다른 불일치 문서(예: `N0000000083` 원본 286 vs 산식 100.1)의 경우, 품명/규격/단위(Unite) 편집 시 기존 원본 수량(286)을 보존해 ESTX 패치를 허용하며, 산식을 수정해 결과가 변경되는 경우 "수량산출서 원본 결과와 재계산 값이 다릅니다. JSON으로 저장해 확인하세요"로 ESTX 덮어쓰기를 안전 차단함을 확인. 3. 미완료 범위(제한 사항): 수량산출서 목록·연결(항목 추가/삭제, 수량산출서 신규/삭제, 행 구조 증감 등) 변경 시 ESTX 저장(`MulMainDat`, `MulTitleDat`, `Editor`, `MulList`)은 고정 인덱스 및 BLOB 구조 보존을 위해 현재 안전 차단되어 있으며, JSON 저장소(`project.quantitySheets`)에서만 지원됨. ESTX 목록·연결 구조 변경 저장은 미완료 상태임. 4. 관련 회귀 시험 `test_est_quantity_workflow.py` 12개, `test_est_business.py` 18개, `test_est_native_export.py` 수량/위첨자 10개 전수 통과. - [x] 수량산출 항목의 단위(Unite) 화면 입력 열과 ESTX 저장 → 재열기·다른 항목 보존·목록 바이너리 검증. - 자체 검증(2026-11-07): native-quantity 렌더러에 단위 입력 열 추가 및 change 핸들러에서 Unite 변경 허용. 설치 main.estx 기존 항목의 품명·규격과 함께 단위(Unite: 'm2')를 수정해 브라우저 이벤트·저장·재열기, 다른 항목·연결·수량 보존 및 실행취소 확인. 단위 변경 시 산식 계산 불변 확인(퍼센트 등 임의 자동변환 없음). test_est_quantity_workflow 12개 및 test_est_native_export 회귀 14개 통과. 원본 EST 실행 검증은 미실시. - [x] 수량산출서의 연속 글자 서식에 걸친 텍스트 편집 저장 → 서식 태그 보존 및 재읽기 검증. - 자체 검증(2026-11-07): 서로 다른 세 글자 서식에 걸친 텍스트를 변경한 뒤 태그와 재읽기 결과를 대조. 변경 시작 위치의 서식으로 새 텍스트를 저장하며 위첨자·표지를 넘는 임의 편집은 계속 제한. 관련 시험 10개와 EST 전용 120개 통과(77.60초). 원본 EST 실행 비교는 미실시. - [x] 설치 수량산출서의 실제 글자 서식 경계 편집을 회귀시험으로 보존 → 해당 문서와 태그 재읽기. - 자체 검증(2026-11-07): main.estx N0000000113의 `27.22