- 수식 길 저장(따로 문서)은 옛 셈이 안 돌아 사본 칸이 1 줄로 줄던 것 — 두 칸 사본 줄 묶음 안에 드는 색인이 읽은 줄로 함께 줄임 · 사본 칸 빈 줄은 수식 칸 값 먼저 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
108 lines
4.5 KiB
Python
108 lines
4.5 KiB
Python
"""사본 = 셈이 실제로 읽은 줄만(PLAN 826-3 · 요구 806 · 808 · 조사 804 5 절) — 서버 단독.
|
||
|
||
[저장] 관문(`M02_MasterTemplete_Store._server` — SK · 일위대가 · 사전조합 · 층 복사 · 열 복사)에서:
|
||
`saved` 동안 사본 셈 색인(`skc.Copy.get`)이 내준 줄 키를 그 색인의 사본 줄 묶음별로 적음
|
||
(`skc.READS`) → 문서 사본(`사본` · `수식` 값 몫)을 이 문서 셈이 읽은 줄만 남김 · 읽었는데
|
||
사본에 없는 줄(옵션 · 기계 · 지역을 바꿔 새로 읽은 줄) = 지금 M01(+ 층 내 기계) 값으로 더함.
|
||
이 문서 셈 = 사본 줄 묶음이 이 문서 사본 안에 드는 색인(남의 SK · SC 참조 셈 = 제 사본 → 안 셈).
|
||
파일 꼴 그대로 — 옛 코드는 사본에 없는 줄을 지금 M01 로 읽음(지금 옵션에서 안 읽는 줄 = 금액 같음).
|
||
읽은 줄 없음(셈 안 돎) · 프로젝트 층 = 그대로 · 이미 저장된 파일은 다음 [저장] 때 줄어듦.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import Any, Callable
|
||
|
||
from M02_MasterTemplete import M02_Doc_Copy as dc
|
||
from M02_MasterTemplete import M02_Item_Prices as prices
|
||
from M02_MasterTemplete import M02_MyMachine as mym
|
||
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
||
|
||
|
||
def _keys(rows: list[dict]) -> set[str]:
|
||
return {str(r.get("키")) for r in rows}
|
||
|
||
|
||
def _rows(copy: dict) -> list[dict]:
|
||
return [*copy["로직"], *(copy.get("단가") or [])]
|
||
|
||
|
||
def cut(copy: Any, keys: set[str], pool: dict | None = None) -> Any:
|
||
"""값 사본(`skc` 꼴) → `keys` 줄만 · 사본 없는 줄 = `pool`(다른 칸 사본) › 지금 M01(+ 내 기계) ·
|
||
판은 바뀐 몫만 다시."""
|
||
if not skc.has({skc.KEY: copy}) or not keys:
|
||
return copy
|
||
rows = _rows(copy)
|
||
have = _keys(rows)
|
||
whole = skc.whole_()
|
||
add = [
|
||
(pool or {}).get(k) or prices.to_json(whole.index[k[:2]][k])
|
||
for k in sorted(keys - have)
|
||
if k in (pool or {}) or k in whole.index.get(k[:2], {})
|
||
]
|
||
keep = [r for r in rows if str(r.get("키")) in keys] + add
|
||
logic = [r for r in keep if str(r.get("키"))[:2] not in skc.RES]
|
||
cost = [r for r in keep if str(r.get("키"))[:2] in skc.RES]
|
||
out = {**copy, "로직": logic, "단가": cost}
|
||
if logic != copy["로직"]:
|
||
out["판"] = skc._fp(logic)
|
||
if cost != (copy.get("단가") or []):
|
||
out["단가판"] = skc._fp(cost)
|
||
return out
|
||
|
||
|
||
def cut_doc(doc: Any, reads: dict) -> Any:
|
||
"""문서의 로직 사본(`사본`) · 수식 사본 값 몫(`수식`)을 두 칸 같은 줄로 줄임 —
|
||
줄 = 사본 줄 묶음이 두 칸 안에 드는 색인이 읽은 것 + 문서 안 내 기계 키(822-1) ·
|
||
읽은 줄 없음 = 그대로."""
|
||
if not isinstance(doc, dict):
|
||
return doc
|
||
old = doc[skc.KEY] if skc.has(doc) else None
|
||
form = doc[dc.KEY] if dc.has(doc) and isinstance(doc[dc.KEY].get("로직"), list) else None
|
||
mine = {str(r.get("키")): r for c in (form, old) if c for r in _rows(c)}
|
||
keys = {k for box, got in reads.items() if box <= mine.keys() for k in got}
|
||
if not keys:
|
||
return doc # 셈이 이 사본을 안 읽음 — 그대로
|
||
keys |= set(mym.keys_in({k: v for k, v in doc.items() if k not in (skc.KEY, dc.KEY)}))
|
||
out = dict(doc)
|
||
if form:
|
||
out[dc.KEY] = {**form, **cut(dc.values_of(form), keys)}
|
||
if old:
|
||
pool = {str(r.get("키")): r for r in _rows(out[dc.KEY])} if form else None
|
||
out[skc.KEY] = cut(old, keys, pool)
|
||
return out
|
||
|
||
|
||
def _project() -> bool:
|
||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||
|
||
return refs.here()[0] == "project"
|
||
|
||
|
||
def _record(kind: str, out: Any) -> None:
|
||
"""저장 길이 이 문서 셈을 안 돌린 몫만 한 번 셈(읽은 줄 적기) — 사전조합 · 수식 길로 고친 SK."""
|
||
if not isinstance(out, dict):
|
||
return
|
||
if kind == "precombo" and skc.has(out):
|
||
from M02_MasterTemplete import M02_Labor_Doc as labor
|
||
|
||
labor.calc(out, {})
|
||
elif kind == "sangeun" and dc.has(out) and out[dc.KEY].get("따로"):
|
||
from M02_MasterTemplete import M02_Doc_Sk as dsk
|
||
|
||
dsk.run(out, out[dc.KEY])
|
||
|
||
|
||
def saved(kind: str, make: Callable[[], Any]) -> Any:
|
||
"""[저장] 관문 — `make()`(정리 · 셈 · 사본 정함) 동안 읽은 줄을 적고 사본을 그 줄로 줄임."""
|
||
if _project():
|
||
return make()
|
||
reads: dict = {}
|
||
token = skc.READS.set(reads)
|
||
try:
|
||
out = make()
|
||
_record(kind, out)
|
||
finally:
|
||
skc.READS.reset(token)
|
||
return cut_doc(out, reads)
|