knowledge(마스터): 재료 열 한 벌 정리 — 시중물가 → 자재품목 · 값 다섯 열 · 유가·환율도 같은 열
- 재료_시중물가.json → 재료_자재품목.json(테이블ID MT · 키 그대로) · 모든 줄이 같은 열 한 벌(키 · 원문번호 · 구분 · 상세구분 · 이름 · 규격 · 단위 · 물가자료 · 유통물가 · 물가정보 · 거래가격 · 관급 · 출처 · 비고 · 면수) - 값 묶음(시중·조달)을 풀어 다섯 값을 열로 · 관급 = 조달 값(4,552 줄 · 기간은 비고 「조달 26.7」) · 원문 가격정보만 남은 72 줄은 값 열에 안 넣고 비고 「가격정보 ○○」 · 구분·상세구분은 원문에 분류가 없어 비움 - 재료_오피넷유가 · 환율_한국은행환율도 열 한 벌(기준일 → 규격 · 유가 구분 = 전국평균/시도별 · 상세구분 = 지역) · 상품코드·지역코드 삭제 - 엔진 단가(연결된 줄의 낮은 값 · 출처 = 「<키>.<열>」) · check_master 열 검사 · M01 고르기(procure 걷어냄) · 빌더 · _틀.md · 화면 계약 · 시험 같이 고침 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
This commit is contained in:
@@ -103,7 +103,7 @@ def files_of(group: str) -> list[dict]:
|
||||
_REF_KEY = re.compile(r"^[A-Z]{2}\d{6}$")
|
||||
_REF_FILE = {
|
||||
"LB": "인력.json",
|
||||
"MT": "재료_시중물가.json",
|
||||
"MT": "재료_자재품목.json",
|
||||
"MN": "재료_나라장터자재.json",
|
||||
"MP": "재료_품셈재료.json",
|
||||
"EQ": "기계.json",
|
||||
@@ -111,16 +111,9 @@ _REF_FILE = {
|
||||
|
||||
|
||||
def _ref_keys(row: dict) -> list[str]:
|
||||
"""줄이 가리키는 키 — 준용 · 연결 · 조달 출처(「나라장터:<키>」)."""
|
||||
put = (
|
||||
row.get("준용"),
|
||||
row.get("연결"),
|
||||
(row.get("값") or {}).get("조달", {}).get("출처")
|
||||
if isinstance(row.get("값"), dict)
|
||||
else None,
|
||||
)
|
||||
out = [v.removeprefix("나라장터:") for v in put if isinstance(v, str)]
|
||||
return [k for k in out if _REF_KEY.match(k)]
|
||||
"""줄이 가리키는 키 — 준용 · 연결."""
|
||||
put = (row.get("준용"), row.get("연결"))
|
||||
return [v for v in put if isinstance(v, str) and _REF_KEY.match(v)]
|
||||
|
||||
|
||||
def refs_of(rows_: list[dict]) -> dict[str, str]:
|
||||
@@ -301,29 +294,24 @@ def elements(group: str, q: str, limit: int) -> dict:
|
||||
return {"total": len(hits), "items": hits[: min(max(limit, 1), 200)]}
|
||||
|
||||
|
||||
_PICK = {
|
||||
"procure": "재료_나라장터자재.json",
|
||||
"price": "재료_시중물가.json",
|
||||
"job": "인력.json",
|
||||
}
|
||||
_PICK = {"price": "재료_자재품목.json", "job": "인력.json"}
|
||||
|
||||
|
||||
def _squash(text) -> str:
|
||||
return "".join(str(text or "").lower().split())
|
||||
|
||||
|
||||
def _lowest(value) -> object:
|
||||
"""시중물가 줄 — 시중 다섯 칸 · 조달 값 가운데 낮은 값 · 그 밖은 `값` 그대로."""
|
||||
if not isinstance(value, dict):
|
||||
return value
|
||||
nums = [v for v in value["시중"].values() if isinstance(v, (int, float))]
|
||||
supply = value["조달"].get("값")
|
||||
return min(nums + ([supply] if supply is not None else []), default=None)
|
||||
def _lowest(row: dict) -> object:
|
||||
"""자재품목 줄 — 값 열 다섯 가운데 낮은 값(시험 계산용) · 값 칸이 있는 줄은 그 값 그대로."""
|
||||
if "값" in row:
|
||||
return row["값"]
|
||||
nums = [row[s] for s in cm.mf.SLOTS if row.get(s) is not None]
|
||||
return min(nums, default=None)
|
||||
|
||||
|
||||
def pick(kind: str, q: str, limit: int) -> dict:
|
||||
"""고르기 창 — `procure` 나라장터자재(ref = 나라장터:<키>) · `price` 시중물가(관급 조달 줄 포함 · ref = 키)
|
||||
· `job` 값 있는 공표 노임 직종(미확보 빼고 모든 구분)(ref = 키) · 이름·규격 낱말이 모두 들어간 줄."""
|
||||
"""고르기 창 — `price` 자재품목(관급 줄 포함 · ref = 키) · `job` 값 있는 공표 노임 직종
|
||||
(미확보 빼고 모든 구분)(ref = 키) · 이름·규격 낱말이 모두 들어간 줄."""
|
||||
if kind not in _PICK:
|
||||
raise StoreError(404, f"없는 고르기 「{kind}」")
|
||||
words = [_squash(w) for w in q.split()]
|
||||
@@ -333,13 +321,12 @@ def pick(kind: str, q: str, limit: int) -> dict:
|
||||
continue
|
||||
text = _squash(f"{row.get('이름')} {row.get('규격')} {' '.join(row.get('옛이름') or [])}")
|
||||
if all(w in text for w in words):
|
||||
key = str(row.get("키"))
|
||||
hits.append(
|
||||
{
|
||||
"ref": f"나라장터:{key}" if kind == "procure" else key,
|
||||
"ref": str(row.get("키")),
|
||||
**{k: row.get(k) for k in ("원문번호", "구분", "이름", "규격", "단위")},
|
||||
"값": _lowest(row.get("값")),
|
||||
"관급": kind == "price" and row["값"]["조달"].get("값") is not None,
|
||||
"값": _lowest(row),
|
||||
"관급": row.get("관급") is not None,
|
||||
}
|
||||
)
|
||||
return {"total": len(hits), "items": hits[: min(max(limit, 1), 200)]}
|
||||
|
||||
Reference in New Issue
Block a user