feat(M01): B01 마스터 데이터 단추 하나로 · 시중물가 「조달 찾기」 모달 · 찾기 API

- B01 옛 「마스터 데이터」(Z01) 단추 제거 · 「마스터 요소」 이름을 「마스터 데이터」 로
- 재료 › 시중물가 줄마다 「조달 찾기」 — 나라장터자재 + 시중물가 조달 줄을 이름·규격으로 찾아 「나라장터:<열쇠>」 연결 · 노랑 표시 · 연결 끊기
- GET /api/m01/procurement 추가 · 값 묶음(조달{…}) 확정 전이라 연결은 조달›연결 칸에 임시로 담음

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WRFJmmhPi4exAzHgPZHMT
This commit is contained in:
2026-09-19 23:29:17 +09:00
co-authored by Claude Sonnet 5
parent dd120ce44b
commit f80046e4ae
9 changed files with 203 additions and 8 deletions
+16
View File
@@ -224,6 +224,22 @@ def elements(group: str, q: str, limit: int) -> dict:
return {"total": len(hits), "items": hits[: min(max(limit, 1), 200)]}
def procurement(q: str, limit: int) -> dict:
"""조달 찾기 창 — 나라장터자재 + 시중물가 안의 조달 줄에서 이름·규격 찾기 · `ref` = 「나라장터:<열쇠>」."""
words = q.lower().split()
hits = []
for book, only_procured in (("나라장터자재", False), ("시중물가", True)):
data, _ = read(f"재료_{book}.json")
for row in data.get("") or []:
if only_procured and "조달" not in row:
continue
text = f"{row.get('이름', '')} {row.get('규격', '')}".lower()
if all(w in text for w in words):
brief = {k: row.get(k) for k in ("이름", "규격", "단위", "")}
hits.append({"ref": f"{book}:{row.get('열쇠')}", **brief})
return {"total": len(hits), "items": hits[: min(max(limit, 1), 200)]}
# ── 시험 계산 ──────────────────────────────────────────────────────────
def _swap(files: dict, book: str, key: str, row: dict, file: str | None) -> None:
"""저장 전 시험 — 메모리 사본에서 그 로직을 고친 줄로 바꿈(없으면 `file` 에 더함)."""