# -*- coding: utf-8 -*- """마스터 키 — 테이블ID(영문 대문자 2) + 6자리 일련번호 · 대장 `_키대장.json` (`_틀.md` 2장). 한 번 준 키는 안 바뀜 · 새 줄은 대장의 다음 번호. 원문이 준 번호·옛 열쇠는 줄의 「원문번호」. """ from __future__ import annotations import json import re from pathlib import Path MASTER = Path(__file__).resolve().parent.parent BOOK = MASTER / "_키대장.json" KEY = re.compile(r"[A-Z]{2}\d{6}") # (그룹, 원문) → 테이블ID · 인력·기계는 원문 구분 없이 한 테이블 TABLES = { ("인력", None): "LB", ("재료", "시중물가"): "MT", ("재료", "나라장터자재"): "MN", ("재료", "오피넷유가"): "MO", ("재료", "품셈재료"): "MP", ("기계", None): "EQ", ("소요량", "산림품셈"): "QF", ("소요량", "건설품셈"): "QC", ("계수", "산림품셈"): "CF", ("계수", "건설품셈"): "CC", ("환율", "한국은행환율"): "FX", ("요율", "조달청제비율"): "RT", ("로직", "산림품셈"): "GF", ("로직", "건설품셈"): "GC", ("로직", "자체"): "GX", } GROUP_OF = {tid: group for (group, _), tid in TABLES.items()} IDS = tuple(GROUP_OF) def table_id(group: str, book: str | None) -> str: return TABLES.get((group, None)) or TABLES[(group, book)] def id_of(ref: str) -> str: """키·「ID:원문번호」 의 테이블ID — 모르면 "".""" return ref[:2] if ref[:2] in GROUP_OF else "" def load_book(path: Path = BOOK) -> dict: if path.is_file(): return json.loads(path.read_text(encoding="utf-8")) return {"다음": {}, "키": {}} def save_book(book: dict, path: Path = BOOK) -> None: """키 한 줄씩 — 머리 「다음」 뒤에 키 차례대로.""" lines = ["{", ' "다음": ' + json.dumps(book["다음"], ensure_ascii=False) + ",", ' "키": {'] items = sorted(book["키"].items()) for i, (key, v) in enumerate(items): comma = "," if i < len(items) - 1 else "" lines.append(f" {json.dumps(key)}: {json.dumps(v, ensure_ascii=False)}{comma}") lines += [" }", "}"] path.write_text("\n".join(lines) + "\n", encoding="utf-8", newline="\n") def issue(book: dict, tid: str, number: str, file: str) -> str: """(테이블ID, 원문번호) 의 키 — 대장에 있으면 그 키 · 없으면(원문번호 빈 새 줄 포함) 다음 번호를 줌.""" index = book.setdefault("_찾기", {}) if not index: for key, v in book["키"].items(): index[(key[:2], v["원문번호"])] = key key = index.get((tid, number)) if number else None if key: book["키"][key]["파일"] = file return key n = book["다음"].get(tid, 1) key = f"{tid}{n:06d}" book["다음"][tid] = n + 1 book["키"][key] = {"원문번호": number, "파일": file} index[(tid, number)] = key return key def finish(book: dict) -> dict: book.pop("_찾기", None) return book def stamp( book: dict, tid: str, rows: list[dict], file: str, extra: dict | None = None ) -> list[dict]: """빌더가 만든 줄(「열쇠」 = 원문번호) → 「키」 · 「원문번호」 · extra 칸을 앞에 둔 줄.""" out = [] for row in rows: row = dict(row) number = str(row.pop("열쇠", row.get("원문번호"))) row.pop("원문번호", None) key = row.pop("키", None) or issue(book, tid, number, file) out.append({"키": key, "원문번호": number, **(extra or {}), **row}) return out