feat(M02): 프로젝트 복사본 일위대가 문서 — 스냅샷 · 입력값 첫 값 · 자재 단가 · 수량 반영 계산 (39-1c)
- Item_Source: 층 labor/<열>.json 이 있으면 일위대가.json = {줄: 문서, 로직, 빠진로직, 알약} · 없으면 옛 UA 조합 줄 · 단가 묶음에 자재 MT
- Item_Snapshot: 입력값.json 첫 값 = 문서 입력값 {로직: {입력: {값, 확인: false}}}
- Item_Prices: collect 가 자재 MT 도 · calc 가 줄마다 수량 · 반영 + 자재 · 기준합 · 반영합(M02_Labor_Doc.settle 한 벌 · 면적 알약 칸 값)
- Item_Copy · Project_Items_Router: 일위대가 종류 읽기만(쓰면 400) · 재적용은 새 첫 값 위에 프로젝트 값 · calc 에 면적
- 시험 test_m02_item_labor.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
This commit is contained in:
@@ -2,9 +2,11 @@
|
||||
|
||||
모으는 것 = `{파일 이름: 내용}`:
|
||||
`집계.json` SS 줄 + 열 정의 · `도면.json` SD · `면적.json` SA · `재료.json` SM ·
|
||||
`자재조합.json` UM 줄 · `일위대가.json` UA 줄 + 담은 로직 줄(M01 시스템) ·
|
||||
`자재조합.json` UM 줄 ·
|
||||
`일위대가.json` = 층 `labor/<열id>.json` 문서(39-1c · 없으면 옛 UA 조합 줄)
|
||||
+ 담은 로직 줄(M01 시스템) + 알약(가져온 때 그대로) ·
|
||||
`입력연결.json` 층의 `inputs/<열id>.json`(없으면 빈 연결) ·
|
||||
`단가.json` 계산에 닿는 마스터 줄 전부
|
||||
`단가.json` 계산에 닿는 마스터 줄 전부(담은 로직 + 일위대가 자재 MT)
|
||||
`원본판` = 모은 내용의 해시 — 지금 층 · 마스터에서 다시 모은 판과 대어 「마스터가 바뀜」 을 앎.
|
||||
프로젝트가 고치는 값(`입력값.json` · `고른자재.json`)은 원본이 아니라 여기서 안 모음.
|
||||
원본 층 자리 = `M02_Template_Layers` 경로 · 일위대가 · 단가는 M01 시스템 것.
|
||||
@@ -23,6 +25,7 @@ TABLE_NAME = "구조물집계표"
|
||||
UM_FILE = "자재조합.json"
|
||||
#: 열 id → 스냅샷 파일(구조물 도면 · 면적산출 · 재료산출)
|
||||
PART_FILES = (("structure", "도면.json"), ("area", "면적.json"), ("material", "재료.json"))
|
||||
LABOR_KIND = "labor" # 열 id → 일위대가 문서(39-1c) — 스냅샷은 `LABOR_FILE` 에 감싸서
|
||||
LINK_FILE = "입력연결.json"
|
||||
PRICE_FILE = "단가.json"
|
||||
LABOR_FILE = "일위대가.json"
|
||||
@@ -80,15 +83,27 @@ def version_of(content: Any) -> str:
|
||||
|
||||
|
||||
def labor_rows(ua_key: str) -> dict[str, Any] | None:
|
||||
"""조합 줄(마스터 UA · 회사 UC · 개인 UP) + 담은 로직 줄(M01 시스템 · 없는 로직은 빼고 키만
|
||||
`빠진로직`)."""
|
||||
from M01_MasterData import M01_MasterData_Store as m01
|
||||
"""옛 조합 줄(마스터 UA · 회사 UC · 개인 UP) + 담은 로직 줄 — labor 문서가 없는 열
|
||||
(옮기기 전)."""
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Combo_Store as combos
|
||||
|
||||
ua = combos.find(ua_key)
|
||||
if ua is None:
|
||||
return None
|
||||
wanted = [str(entry.get("로직")) for entry in ua.get("담은로직") or [] if entry.get("로직")]
|
||||
return None if ua is None else logic_rows(ua)
|
||||
|
||||
|
||||
def labor_doc_rows(doc: dict[str, Any]) -> dict[str, Any]:
|
||||
"""일위대가 문서(39-1a) + 담은 로직 줄 + 알약(`M02_Labor_Doc.pills` · 가져온 때 그대로 —
|
||||
복사본 계산이 마스터를 안 읽게)."""
|
||||
from M02_MasterTemplete import M02_Labor_Doc as labor_doc
|
||||
|
||||
return {**logic_rows(doc), "알약": labor_doc.pills(doc)}
|
||||
|
||||
|
||||
def logic_rows(row: dict[str, Any]) -> dict[str, Any]:
|
||||
"""`{줄: row, 로직: 담은 로직 줄(M01 시스템), 빠진로직: 없는 로직 키}`."""
|
||||
from M01_MasterData import M01_MasterData_Store as m01
|
||||
|
||||
wanted = [str(entry.get("로직")) for entry in row.get("담은로직") or [] if entry.get("로직")]
|
||||
found: dict[str, dict[str, Any]] = {}
|
||||
raw: dict[str, Any] = {} # M01 적재본은 수가 Decimal — 줄은 원본 파일 JSON 그대로 담음
|
||||
for key in wanted:
|
||||
@@ -98,11 +113,11 @@ def labor_rows(ua_key: str) -> dict[str, Any] | None:
|
||||
continue
|
||||
if file not in raw:
|
||||
raw[file] = read_json(Path(m01.FOLDER) / file)
|
||||
row = row_of(raw[file], key)
|
||||
if row is not None:
|
||||
found[key] = row
|
||||
got = row_of(raw[file], key)
|
||||
if got is not None:
|
||||
found[key] = got
|
||||
return {
|
||||
"줄": ua,
|
||||
"줄": row,
|
||||
"로직": [found[key] for key in wanted if key in found],
|
||||
"빠진로직": [key for key in wanted if key not in found],
|
||||
}
|
||||
@@ -142,10 +157,16 @@ def build_source(item: dict[str, Any]) -> dict[str, Any]:
|
||||
um = row_of(read_json(root / UM_FILE), str(row["자재조합"]))
|
||||
if um is not None:
|
||||
files[UM_FILE] = um
|
||||
labor = labor_rows(str(row["일위대가"])) if row.get("일위대가") else None
|
||||
doc = read_json(root / LABOR_KIND / f"{column_id}.json") if column_id else None
|
||||
if isinstance(doc, dict):
|
||||
labor = labor_doc_rows(doc)
|
||||
else:
|
||||
labor = labor_rows(str(row["일위대가"])) if row.get("일위대가") else None
|
||||
if labor is not None:
|
||||
files[LABOR_FILE] = labor
|
||||
files[LINK_FILE] = input_links(root, column_id)
|
||||
logic_keys = [str(one.get("키")) for one in (labor or {}).get("로직", [])]
|
||||
files[PRICE_FILE] = prices.to_json(prices.collect(logic_keys)) if logic_keys else {}
|
||||
materials = [str(m.get("코드")) for m in ((labor or {}).get("줄") or {}).get("자재") or []]
|
||||
wanted = logic_keys + [code for code in materials if code]
|
||||
files[PRICE_FILE] = prices.to_json(prices.collect(logic_keys, materials)) if wanted else {}
|
||||
return files
|
||||
|
||||
Reference in New Issue
Block a user