feat(719-1): 프로젝트 사본 SK 풀어 굳힘 — 고친 줄 = 사본 단가.json 로직 줄 · 굳힌 키 GX9##### (SK 이름표 해시 · 같은 SK = 같은 키) · B09 서고 manifest 원본판

- 새 M02_Item_Sangeun: 참조사본 SK → M02_Sangeun_Calc.resolve 고친 줄 → 로직_단가산출.json 줄 · 사본 SK = 바탕 굳힌 키 · 덮개 0 · 원본 · 바탕판 · 짝잃음 근거
- M02_Item_Source: labor_doc_rows 가 굳힘 · price_bundle 이 굳힌 줄과 그 줄이 닿는 마스터 줄 · 고른 자재 담음
- M02_Item_Prices: 수집기 줄 하나 길(row) 떼어 둠 · 요소 없는 줄(참조 · 고정 더한줄) 건너뜀
- B09 Bill_Library: 서고 사본 manifest 원본판 = 일위대가.json 지문(source_version)
- 시험 test_719_1_sk_freeze 4(임시 storage)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-01 15:34:29 +09:00
co-authored by Claude Opus 5.5
parent ee908fae28
commit b54950d28b
5 changed files with 257 additions and 9 deletions
+13 -4
View File
@@ -5,7 +5,7 @@
`일위대가.json` = 층 `labor/<열id>.json` 문서(39-1c · 없으면 옛 UA 조합 줄 ·
규격 열 = summary_item `spec` 열 수량을 손으로 굳힘 · 704-4)
+ 담은 로직 줄(M01 시스템) + 알약(가져온 때 그대로) +
참조사본(단가승격 · 사전조합을 값으로 굳힘) ·
참조사본(단가승격 · 사전조합을 값으로 굳힘 · 단가산출 SK = 풀어 굳힌 로직 줄 719-1) ·
`단가.json` 계산에 닿는 마스터 줄 전부(담은 로직 + 일위대가 자재 MT)
`원본판` = 모은 내용의 해시 — 지금 층 · 마스터에서 다시 모은 판과 대어 「마스터가 바뀜」 을 앎.
프로젝트가 고치는 값(`입력값.json` · `고른자재.json`)은 원본이 아니라 여기서 안 모음.
@@ -93,11 +93,12 @@ def labor_rows(ua_key: str) -> dict[str, Any] | None:
def labor_doc_rows(doc: dict[str, Any]) -> dict[str, Any]:
"""일위대가 문서(39-1a) + 담은 로직 줄 + 알약(`M02_Labor_Doc.pills` · 가져온 때 그대로 —
복사본 계산이 마스터를 안 읽게) + 참조사본 `{ref_id: 문서}`(50-3 · 원본이 바뀌어도 그대로)."""
from M02_MasterTemplete import M02_Item_Sangeun as sk
from M02_MasterTemplete import M02_Labor_Doc as labor_doc
from M02_MasterTemplete import M02_Labor_Ref as refs
rows = {**logic_rows(doc), "알약": labor_doc.pills(doc)}
copies = refs.frozen(doc)
copies = sk.freeze(refs.frozen(doc)) # 단가산출(SK) = 풀어 굳힌 로직 줄(719-1)
return {**rows, "참조사본": copies} if copies else rows
@@ -162,11 +163,14 @@ def price_bundle(labor: dict[str, Any] | None, root: Path) -> dict[str, Any]:
"""사본 단가 묶음(`단가.json`) — 담은 로직 · 굳힌 참조 로직 · 자재 · 고른 자재 · 사전조합 자재 ·
개인 자재(`root` = 원본 층 · B09 설계내역서 서고 사본도 이 길 · 204-2)."""
from M02_MasterTemplete import M02_Item_Prices as prices
from M02_MasterTemplete import M02_Item_Sangeun as sk
from M02_MasterTemplete import M02_Labor_Fixed as fixed
from M02_MasterTemplete import M02_Labor_Ref as refs
copies = (labor or {}).get("참조사본") or {}
sk_rows = sk.rows(copies) # 굳힌 단가산출 줄(719-1) — 그 줄이 닿는 마스터 줄도 모음
logic_keys = [str(one.get("키")) for one in (labor or {}).get("로직", [])]
logic_keys += refs.frozen_logics((labor or {}).get("참조사본") or {}) # 굳힌 단가승격 로직
logic_keys += refs.frozen_logics(copies) # 굳힌 단가승격 로직
doc = (labor or {}).get("줄") or {}
materials = [str(m.get("코드")) for m in doc.get("자재") or []]
materials += [ # 고른 로직 자재(103-1) 품목 줄도 — 복사본 계산이 그 단가를 씀
@@ -174,8 +178,13 @@ def price_bundle(labor: dict[str, Any] | None, root: Path) -> dict[str, Any]:
]
materials += refs.frozen_materials((labor or {}).get("참조사본") or {}) # 175-2 사전조합 자재
materials += fixed.link_keys(doc) # 705-1 고정 줄이 잇는 노임 · 자재 · 기계
materials += sk.materials(copies)
wanted = logic_keys + [code for code in materials if code]
bundle = prices.to_json(prices.collect(logic_keys, materials)) if wanted else {}
bundle = (
prices.to_json(prices.collect(logic_keys, materials, sk_rows)) if wanted or sk_rows else {}
)
if sk_rows:
bundle[sk.FILE] = {"그룹": "로직", "원문": "자체", "줄": sk_rows}
if mine := own.bundle(
[c for c in materials if own.is_own(c)], root
): # 개인 자재(148-3 · 사전조합 것도 175-2) — 원본 목록이 바뀌어도 사본 그대로