Merge remote-tracking branch 'origin/dev' into sub_desktop_1

# Conflicts:
#	M01_MasterData/M01_MasterData_Store.py
#	resources/tester/test_m01_api.py
This commit is contained in:
2026-09-20 22:47:35 +09:00
24 changed files with 1376 additions and 1113 deletions
+12 -6
View File
@@ -70,6 +70,11 @@ def _hit(row: dict, q: str) -> bool:
)
def _book(data: dict) -> str | None:
"""머리 원문 이름 — 한 테이블 파일(기계)은 머리 「원문」 이 갈래 묶음이라 이름이 묶음 안에."""
return data.get("원문") if isinstance(data.get("원문"), str) else None
def groups() -> list[dict]:
out = {g: {"group": g, "files": 0, "rows": 0} for g in cm.mf.GROUPS}
for data in cm.load(folder=FOLDER).values():
@@ -89,7 +94,7 @@ def files_of(group: str) -> list[dict]:
out.append(
{
"file": path.name,
"book": data.get("원문"),
"book": _book(data),
"chapter": chapter_of(path.name, data),
"edition": data.get("판"),
"rows": len(data.get(items_key(data)) or []),
@@ -130,7 +135,8 @@ _STATES = ("공표", "산정", "미공표", "미확보", "추정") # 인력 「
def subs(file: str = "", group: str = "") -> dict:
"""하위 거름 목록 — 한 테이블 파일은 머리 묶음(인력 · 기계 모두 「구분」 → 「상세구분」) ·
"""하위 거름 목록 — 한 테이블 파일은 머리 묶음(인력 · 기계 모두 「구분」 → 「상세구분」 ·
기계는 「원문」(건설품셈 · 산림품셈)도 머리에 있으나 「구분」 이 우선) ·
장 그룹(소요량 · 계수 · 로직)은 장 파일에서 모음(구분 = 원문 + 부문 · 상세구분 = 장 · 차례대로)."""
if group:
if group not in cm.mf.GROUPS:
@@ -146,7 +152,7 @@ def subs(file: str = "", group: str = "") -> dict:
slot["details"].append(mk.detail_of(info["file"]))
return {"file": "", "version": "", "slot": "구분", "subs": list(found.values())}
data, version = read(file)
slot = next((s for s in ("구분", "세부분류") if isinstance(data.get(s), dict)), "")
slot = next((s for s in cm.MERGED.values() if isinstance(data.get(s), dict)), "")
lines = data.get(items_key(data)) or []
has_state = any("상태" in r for r in lines)
@@ -184,8 +190,8 @@ def rows(
) -> dict:
data, version = read(file)
hits = [r for r in data.get(items_key(data)) or [] if _hit(r, q)]
if sub: # 인력·기계 구분 (세부분류는 남은 옛 화면 호출 대비)
hits = [r for r in hits if sub in (r.get("구분"), r.get("세부분류"))]
if sub: # 인력·기계 구분(우선) · 기계 원문(책)도 받음
hits = [r for r in hits if sub in {r.get(s) for s in cm.MERGED.values()}]
if detail: # 인력 상세구분 · 기계 상세구분(기종)
hits = [r for r in hits if r.get("상세구분") == detail]
if state: # 인력 상태
@@ -531,7 +537,7 @@ def _follow(row: dict, items: list[dict], file: str) -> dict:
def _apply(data: dict, changes: list[dict], file: str, book: dict) -> None:
"""고침 · 더함(키는 대장의 다음 번호 · 원문번호 없으면 빈 글) · 지움 — 키는 바꾸지 않음."""
items = data.setdefault(items_key(data), [])
tid = mk.table_id(data.get("그룹"), data.get("원문"))
tid = mk.table_id(data.get("그룹"), _book(data))
for ch in changes:
op, key, row = ch.get("op"), ch.get("key"), _dec(ch.get("row"))
if op not in ("edit", "add", "delete"):