diff --git a/resources/tester/test_est_multi_search.py b/resources/tester/test_est_multi_search.py index 69928c982..149df1a1a 100644 --- a/resources/tester/test_est_multi_search.py +++ b/resources/tester/test_est_multi_search.py @@ -34,3 +34,22 @@ def test_search_finds_words_in_selected_kinds(tmp_path): assert result["none"]["total"] == 0 assert result["excluded"]["total"] == 0 assert result["err"] == ["검색어를", "검색할 "] + + +def test_search_price_range_and_main_data_only(tmp_path): + sample = json.loads((ROOT / "tools/est-test/sample.json").read_text(encoding="utf-8")) + (tmp_path / ("a" * 24 + ".json")).write_text(json.dumps(sample), encoding="utf-8") + (tmp_path / ("c" * 24 + ".json")).write_text(json.dumps(sample), encoding="utf-8") + script = """ + const s = require('./tools/est-test/search-store.cjs'), dir = process.argv[1]; + const range = s.search(dir, '1~999999999', ['5']); + const exact = s.search(dir, String(range.hits[0].price), ['5']); + const only = s.search(dir, '1~999999999', ['5'], '', ['c'.repeat(24)]); + process.stdout.write(JSON.stringify({ range: range.hits.map((h) => h.price), exact: exact.total, only: only.hits.map((h) => h.id), total: range.total })); + """ + out = json.loads( + subprocess.check_output(["node", "-e", script, str(tmp_path)], cwd=ROOT).decode("utf-8") + ) + assert out["range"] and all(1 <= p <= 999999999 for p in out["range"]) + assert out["exact"] >= 2 + assert set(out["only"]) == {"c" * 24} and len(out["only"]) == out["total"] // 2 diff --git a/tools/est-test/PLAN.md b/tools/est-test/PLAN.md index 7cd49ce93..331e13903 100644 --- a/tools/est-test/PLAN.md +++ b/tools/est-test/PLAN.md @@ -489,6 +489,8 @@ ative-standard.js에 표준시장단가 원천(SilJukDat)과 내역 행(EstMainD - 남음: 구성비·요율 전환(CalcBase), 약어 표시(SName), 제비율 기준 문서 보기(원본 한글 파일). - [x] 수량산출서 검색·전체보기(원본 TFRMMULLANG btnSerch·btnAllDisplay — 빈칸·|·괄호 무시 포함 검색) — 고르기 줄을 `native-quantity-sheets.js` 로 옮겨 700줄 제한 유지. - 검증완료: `test_est_quantity_sheets.py` 검색 시험 포함 수량 시험 22개 통과. ORCA 브라우저에서 「집수」 검색 → 항목에 집수정이 있는 「배수」만·선택 이동, 전체보기 → 3개 복귀, 샘플 복구. + - [x] 설계참고철(Main Data)과 단가 범위 검색(원본 TfrmMainTableList 「MAIN DATA(설계참고철) 추가 및 삭제」 · TfrmFolderSerch 「Main Data에서 검색」·범위 검색 0xefefb0) — 통합 검색 「설계참고철 관리」에서 저장된 작업 중 최대 10개 지정(양식 보관함 종류 options), 검색위치 「설계참고철」이면 그 작업만, 검색어 「a~b」·숫자 하나는 단가 범위·같음. 원본의 검색중지는 서버 검색이 바로 끝나 두지 않음. + - 검증완료: `test_est_multi_search.py` 2개(범위·같음·지정 작업만) 통과. ORCA 브라우저에서 2개 지정 → 「1000~2000」 24건 모두 지정 작업·범위 안, 목록 지워 복구. - [x] 줄 연결 도구(원본 TfrmHead popupCostNC·GC·JC·All 0xf1b54c · popMainSumIndex · mnuDataLink 0xf00e6c — 디스어셈블 근거) — 비목별 단가 불러오기(일위대가 줄: 하위 견적·일위·단산·기계에서 고른 비목 단가만 남기고 나머지 0, 기준비목 지정, 노임·자재·표준 거부), SUM 색인지정(해제·A~Z → 구간 SKind, 레벨·소계·도급액·조달수수료·호표머리 줄 거부), 하위데이타 연결/끊기(연결 줄은 끊고 값 유지, 끊긴 줄은 일위→단산→기계→표준→견적→자재→노임 차례로 코드 또는 품명·규격·단위 맞춤으로 연결, 자재는 재료단가·노임은 노무단가 = 원본 TC). 원본은 초점 한 줄, 웹은 고른 줄 모두. - 검증완료: `test_est_row_links.py`(경비만 5·전체 40/15/5, 거부, 자재 연결 M1·5000·끊기, 못 찾음 문구, 색인 3·거부 3종) 통과. ORCA 브라우저에서 일위대가 합판거푸집 노무비만 → 0, 재료비만 → 재료단가 34,666·금액 13,173, 내역 일위 연결 줄 끊기 → 다시 연결 103·도급액 불변, SUM 색인 B, 샘플 복구. - [x] 묶음 인쇄 간지 설정값 일괄적용·기본양식에저장·전체선택/선택해제(원본 TFRMESTPRINTPRIVATE btnGangiAllSet·btnSaveToMain, TFRMESTPRINT2 btnNoselect) — 간지 인쇄·간지 겹테두리를 모든 서식에 같게, 고른 서식·간지 설정을 「묶음기본양식」(양식 보관함 종류 print)으로 저장해 묶음 설정 없는 공사에서 열 때 씀. diff --git a/tools/est-test/native-multi-search.js b/tools/est-test/native-multi-search.js index 0825a5727..2ba87dc96 100644 --- a/tools/est-test/native-multi-search.js +++ b/tools/est-test/native-multi-search.js @@ -23,11 +23,16 @@ const EstMultiSearch = (() => { .join(""); EstApp.showDialog( "통합 검색", - `
검색위치: 이 앱에 저장된 다른 작업
| 작업 | 구분 | 코드 | 품명 | 규격 | 단위 | 단가 |
|---|
찾은 자료 ${saved.total}건${saved.total > saved.hits.length ? ` 중 앞 ${saved.hits.length}건` : ""}
`, + `검색위치: · 검색어에 「10000~20000」처럼 쓰면 단가 범위
| 작업 | 구분 | 코드 | 품명 | 규격 | 단위 | 단가 |
|---|
찾은 자료 ${saved.total}건${saved.total > saved.hits.length ? ` 중 앞 ${saved.hits.length}건` : ""}
`, ); } async function run(name, state) { + if (name === "main-list") return mainForm(state); + if (name === "main-list-save") { + await mainSave(); + return form(state); + } if (name === "multi-search") form(state); else if (name === "multi-search-run") { const saved = state.multiSearch; @@ -35,7 +40,14 @@ const EstMultiSearch = (() => { saved.kinds = [...document.querySelectorAll('#dialog-content [name="ms-kind"]:checked')].map( (n) => Number(n.value), ); + saved.where = document.querySelector('#dialog-content [name="ms-where"]:checked')?.value; const params = new URLSearchParams({ q: saved.query, kinds: saved.kinds.join(",") }); + if (saved.where === "main") { + const ids = await mainList(); + if (!ids.length) + throw Error("설계참고철에 등록한 작업이 없습니다. 설계참고철 관리에서 추가하세요."); + params.set("only", ids.join(",")); + } if (state.project.id) params.set("exclude", state.project.id); Object.assign(saved, await EstApp.api(`/api/search?${params}`)); form(state); @@ -65,7 +77,41 @@ const EstMultiSearch = (() => { EstApp.render(); } } - const names = new Set(["multi-search", "multi-search-run", "multi-search-take"]); + // 설계참고철(TfrmMainTableList 「MAIN DATA 추가 및 삭제」): 저장된 작업 중 최대 10개 — 양식 보관함(종류 options, 이름 「설계참고철」) + const MAIN = "설계참고철"; + async function mainList() { + return ( + (await EstApp.api("/api/forms")).find((f) => f.kind === "options" && f.name === MAIN)?.data + ?.ids || [] + ); + } + async function mainForm(state) { + const ids = await mainList(), + projects = await EstApp.api("/api/projects"), + { esc } = EstApp; + EstApp.showDialog( + "MAIN DATA(설계참고철) 추가 및 삭제", + `통합 검색 「설계참고철」에서 찾을 작업을 고르세요(최대 10개).