"""B09 연결된 사본 → 원가 수요 자원 키(PLAN 144 · 143-1 원천) — 서버 단독 · 읽기만. 연결된 사본 = `M02_Item_Snapshot.linked_snapshots`(지정 ∩ 같은 항목 사본 · B08 · B09 공용). 사본마다 `일위대가.json` 담은 로직을 그 사본 단가 묶음(`단가.json`) · 입력값 · 고른자재로 돌리며 실제로 부른 자원 줄(인력 LB · 기계 EQ · 자재 MT · 유가 MO)만 모음 — 단가 묶음 통째 (고르기 후보 전부)는 안 씀 · 값은 쓰지 않음(단가는 원가 한 벌 `price_book.json` 이 맡음). 구조물 조합 사본 없으면 그 구조물은 없음 · 일위대가 없는 사본은 자원 없음. """ from __future__ import annotations from pathlib import Path from typing import Any from M02_MasterTemplete import M02_Item_Prices as item_prices from M02_MasterTemplete import M02_Labor_Doc as labor_doc from M02_MasterTemplete.M02_Item_Snapshot import ( PICKS_FILE, VALUES_FILE, linked_snapshots, structures_dir, ) from M02_MasterTemplete.M02_Item_Source import LABOR_FILE, PRICE_FILE, read_json #: 원가 단가 목록에 오르는 자원 표 RESOURCE_TABLES = ("LB", "EQ", "MT", "MO") mf = item_prices.mf def used_keys(folder: Path) -> list[str]: """사본 하나가 담은 로직을 돌릴 때 부른 자원 키 — 부른 차례 · 겹침 없음.""" labor = read_json(folder / LABOR_FILE) if not isinstance(labor, dict): return [] snapshot = item_prices.load_prices(read_json(folder / PRICE_FILE) or {}) values = read_json(folder / VALUES_FILE) or {} picks = read_json(folder / PICKS_FILE) or {} seen: list[str] = [] base_get = snapshot.get def get(ref: str) -> dict[str, Any]: row = base_get(ref) key = str(row.get("키") or "") if key[:2] in RESOURCE_TABLES and key not in seen: seen.append(key) return row snapshot.get = get # 이 사본 묶음 한 벌에만 — 마스터 캐시는 안 건드림 # 사본 셈 한 벌(142-1)과 같은 길 — 빈 입력 = 자동값 · 켜쌓기율 · 고름 · # 굳힌 참조사본 안 로직까지 doc = item_prices.with_values(labor.get("줄") or {}, values, picks) inner = [d for d in (labor.get("참조사본") or {}).values() if isinstance(d, dict)] for one in [*(doc.get("담은로직") or []), *(x for d in inner for x in d.get("담은로직") or [])]: # 못 돈 로직 — 부른 데까지만(까닭은 안 봄) if isinstance(one, dict) and one.get("로직"): labor_doc.run_line( snapshot, one["로직"], one.get("입력값"), one.get("켜쌓기율"), one.get("고름") ) return seen def linked_resource_keys(project_root: str | Path) -> list[str]: """연결된 사본 전부가 부른 자원 키 — 구조물 id 차례 · 겹침 없음.""" base = structures_dir(project_root) out: list[str] = [] for _owner, linked in sorted(linked_snapshots(project_root).items()): if "일위대가" not in linked.get("부분", []): continue for key in used_keys(base / linked["폴더"]): if key not in out: out.append(key) return out