Files
Aislo/tools/est-test/native-multi-search.js
T
eomsangdonandClaude Opus 5.5 5b2ebeb676 feat(est-test): 저장된 작업 통합 검색과 가져오기
- 원본 통합 검색처럼 자료 7종을 검색어로 찾고 하위 연결째 현재 공사로 가져옴

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 19:43:15 +09:00

80 lines
4.1 KiB
JavaScript

// 원본 통합 검색(TFRMMULTISERCH) 화면 — 저장된 다른 작업에서 단가·호표를 찾아, 고른 자료를 하위 연결 자료와 함께
// 현재 공사로 가져온다(EstTransfer). 같은 코드는 현재 공사 자료를 그대로 둔다. 가져온 뒤 단가 고르기로 행에 넣는다.
const EstMultiSearch = (() => {
const kinds = [
[103, "일위대가"],
[104, "단가산출"],
[105, "기계경비"],
[101, "견적단가"],
[21, "실적단가"],
[5, "자재단가"],
[6, "노임단가"],
];
function form(state) {
const { esc } = EstApp,
saved = state.multiSearch || { query: "", kinds: kinds.map(([k]) => k), hits: [], total: 0 };
state.multiSearch = saved;
const rows = saved.hits
.map(
(h, i) =>
`<tr><td><input type="checkbox" name="ms-hit" value="${i}"></td><td>${esc(h.project)}</td><td>${esc(h.label)}</td><td>${esc(h.Code)}</td><td style="text-align:left">${esc(h.Name)}</td><td>${esc(h.Size)}</td><td>${esc(h.Unite)}</td><td style="text-align:right">${EstApp.number(h.price)}</td></tr>`,
)
.join("");
EstApp.showDialog(
"통합 검색",
`<p>검색위치: 이 앱에 저장된 다른 작업</p><div class="form-fields">${kinds.map(([k, label]) => `<label><input type="checkbox" name="ms-kind" value="${k}" ${saved.kinds.includes(k) ? "checked" : ""}>${label}</label>`).join("")}<label>검색어<input name="ms-query" value="${esc(saved.query)}"></label></div><button data-action="multi-search-run">검색</button> <button data-action="multi-search-take">고른 자료를 이 공사로 가져오기</button><div style="max-height:360px;overflow:auto;border:1px solid #ccc;margin-top:6px"><table class="sheet" style="font-size:12px"><thead><tr><th></th><th>작업</th><th>구분</th><th>코드</th><th>품명</th><th>규격</th><th>단위</th><th>단가</th></tr></thead><tbody>${rows}</tbody></table></div><p>찾은 자료 ${saved.total}건${saved.total > saved.hits.length ? ` 중 앞 ${saved.hits.length}건` : ""}</p>`,
);
}
async function run(name, state) {
if (name === "multi-search") form(state);
else if (name === "multi-search-run") {
const saved = state.multiSearch;
saved.query = document.querySelector('#dialog-content [name="ms-query"]').value;
saved.kinds = [...document.querySelectorAll('#dialog-content [name="ms-kind"]:checked')].map(
(n) => Number(n.value),
);
const params = new URLSearchParams({ q: saved.query, kinds: saved.kinds.join(",") });
if (state.project.id) params.set("exclude", state.project.id);
Object.assign(saved, await EstApp.api(`/api/search?${params}`));
form(state);
} else if (name === "multi-search-take") {
const picked = [...document.querySelectorAll('#dialog-content [name="ms-hit"]:checked')].map(
(n) => state.multiSearch.hits[Number(n.value)],
);
if (!picked.length) throw Error("가져올 자료를 고르세요.");
const projects = new Map();
for (const hit of picked)
if (!projects.has(hit.id))
projects.set(hit.id, await EstApp.api(`/api/projects/${hit.id}`));
const deps = picked.map((hit) =>
EstTransfer.collect(projects.get(hit.id), [{ LinkIndex: hit.kind, Code: hit.Code }]),
);
let added = 0,
kept = 0;
EstApp.change((project) => {
for (const dep of deps) {
const result = EstTransfer.merge(project, dep);
added += result.added.length;
kept += result.kept.length;
}
});
EstApp.byId("dialog").close();
state.notice = `자료 ${added}건을 가져왔습니다${kept ? `, 같은 코드 ${kept}건은 이 공사 자료를 그대로 씀` : ""}. 단가 고르기로 행에 넣으세요.`;
EstApp.render();
}
}
const names = new Set(["multi-search", "multi-search-run", "multi-search-take"]);
function handle(name, state) {
if (!names.has(name)) return false;
run(name, state).catch((error) => {
state.notice = error.message;
EstApp.render();
});
return true;
}
return { handle };
})();