fix(822-1): 사본 빈틈 막기 — 셈이 읽은 M01 줄을 저장 때 값 사본에 박음 · 가져온 식 우리 = 사본 · 빈틈 표지
- 새 M02_Doc_Gap: 문서 셈이 읽은 요소 · 표 줄 가운데 값 사본에 없는 것(gaps) → 지금 M01 닫힌 묶음으로 더함(fill) - 수식 길(M02_Doc_Sk_Path.edited): 줄 쌓기 품셈 기계 · 바꿔 끼운 기계 · 자원 줄 · 단가산출 참조 · 내 기계 모두 저장 때 박음(옛 _mine 대신) - 저장 첫머리(M02_Doc_Sk.settle): 따로 = [저장] · [단가 갱신] 때 빈틈 메움 · 파생 = 옛 로직 사본에 더함 - 가져온 식 단가기준 우리(M02_Doc_Import): 셈 · 연결 기록 = 로직 사본 위(지금 M01 직접 읽던 빈틈) · 엑셀 기준 그대로 - 읽기 답 사본 표지 「사본없음」 n · 화면 배지 「사본 없는 줄 n」(지금 값으로 셈 · 저장하면 굳음) · 일괄 고쳐 쓰지 않음 - 시험 test_822_1_copy_gap 14 · storage SK 122 고치기 전후 금액 같음 · 빈틈 0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
"""M02 단가산출(SK) 수식 사본 빈틈(PLAN 822-1 · 요구 797-1) — 서버 단독.
|
||||
|
||||
빈틈 = 문서 셈이 읽은 M01 요소 · 표 줄 가운데 값 사본에 없는 것(줄 쌓기 기계 · 바꿔 끼운 기계 ·
|
||||
더한 자원 줄 · 단가산출 참조가 읽는 노임 · 유가 · 내 기계 …) — 사본 색인이 지금 M01 로 흘러
|
||||
M01 이 바뀌면 금액이 바로 따라 바뀜.
|
||||
`gaps` = 빈틈 키(셈 한 번 · 읽은 줄 적기) · `fill` = 빈틈을 지금 M01 닫힌 묶음으로 값 사본에 더함
|
||||
(있는 줄 그대로 — `skc.grow`) — [저장] · [단가 갱신] 때만(열기 · 미리 셈은 지금 값으로 셈 + 표지).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from M02_MasterTemplete import M02_Doc_Copy as dc
|
||||
from M02_MasterTemplete import M02_MyMachine as mym
|
||||
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
||||
|
||||
|
||||
class _Seen:
|
||||
"""셈 색인 겉 — `get` · `value` · `logic` 이 내준 줄 키를 적음(그 밖 = 속 색인 그대로)."""
|
||||
|
||||
def __init__(self, inner: Any) -> None:
|
||||
self._inner, self.keys = inner, set()
|
||||
|
||||
def get(self, ref: str) -> dict:
|
||||
return self._note(self._inner.get(ref))
|
||||
|
||||
def value(self, ref: str):
|
||||
self.get(ref)
|
||||
return self._inner.value(ref)
|
||||
|
||||
def logic(self, key: str) -> dict:
|
||||
return self._note(self._inner.logic(key))
|
||||
|
||||
def _note(self, row: Any) -> Any:
|
||||
if isinstance(row, dict) and row.get("키"):
|
||||
self.keys.add(str(row["키"]))
|
||||
return row
|
||||
|
||||
def __getattr__(self, name: str) -> Any:
|
||||
return getattr(self._inner, name)
|
||||
|
||||
|
||||
def _have(copy: dict) -> set[str]:
|
||||
return {str(r.get("키")) for r in [*(copy.get("로직") or []), *(copy.get("단가") or [])]}
|
||||
|
||||
|
||||
def gaps(copy: dict) -> list[str]:
|
||||
"""값 사본에 없는데 문서 셈이 읽은 M01 줄 키 + 문서의 내 기계 키(셈 틀림 = 읽은 데까지)."""
|
||||
if "로직" not in copy or not isinstance(copy.get("문서"), dict):
|
||||
return []
|
||||
seen = _Seen(dc.over(copy))
|
||||
try:
|
||||
dc.mc.calc(copy["문서"], dc.ml.Links(seen, dc.docs_of(copy)))
|
||||
except dc._ERR:
|
||||
pass
|
||||
have = _have(copy)
|
||||
return sorted({*seen.keys, *mym.keys_in(copy["문서"])} - have)
|
||||
|
||||
|
||||
def fill(copy: dict) -> dict:
|
||||
"""빈틈을 지금 M01(+ 지금 층 내 기계) 닫힌 묶음으로 값 사본에 더함 · 빈틈 없음 = 그대로."""
|
||||
keys = gaps(copy)
|
||||
if not keys:
|
||||
return copy
|
||||
return {**copy, **skc.grow(dc.values_of(copy), skc.snap([], keys))}
|
||||
@@ -51,6 +51,16 @@ def basis_of(sk: dict) -> str:
|
||||
return "우리" if (sk.get(imp.KEY) or {}).get("단가기준") == "우리" else "엑셀"
|
||||
|
||||
|
||||
def _index(sk: dict, master: Any = None) -> Any:
|
||||
"""셈 색인 — 우리 = 로직 사본 위(822-1 · 이음 값이 M01 따라 안 바뀜 · [단가 갱신] 으로만) ·
|
||||
엑셀 = 받은 색인 · 없으면 지금 M01."""
|
||||
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
||||
|
||||
if basis_of(sk) == "우리":
|
||||
return skc.over(sk, imp._whole())
|
||||
return master or imp._whole()
|
||||
|
||||
|
||||
# ── 엑셀 단가 그대로 엔진 줄(옛 셈 길 · SK 고침 얹은 것) ───────────────────
|
||||
def _ctx(sk: dict, whole: Any) -> tuple:
|
||||
"""엑셀 단가 기준 고친 줄 — 옛 셈 길(`OLD`)로 돌려 엔진에 넣은 (색인, 키, 입력, 답, 재료)."""
|
||||
@@ -514,7 +524,7 @@ def record(doc: dict, sk: dict) -> dict[str, Any]:
|
||||
import master_doc_record as mr # `M02_Doc_Copy` 가 scripts 를 길에 둔 뒤
|
||||
|
||||
basis = basis_of(sk)
|
||||
links = Links(imp._whole(), basis)
|
||||
links = Links(_index(sk), basis)
|
||||
mine = view(doc, basis)
|
||||
rec = mr.Rec(links)
|
||||
try:
|
||||
@@ -529,7 +539,7 @@ def record(doc: dict, sk: dict) -> dict[str, Any]:
|
||||
def run(doc: dict, sk: dict, master: Any = None) -> dict:
|
||||
"""가져온 식 문서 셈(SK 단가기준) — 계산기 = M01 과 같은 `master_doc_calc`."""
|
||||
basis = basis_of(sk)
|
||||
links = Links(master or imp._whole(), basis)
|
||||
links = Links(_index(sk, master), basis)
|
||||
mine = view(doc, basis)
|
||||
try:
|
||||
links.learn(mine)
|
||||
|
||||
@@ -22,6 +22,7 @@ from decimal import Decimal
|
||||
from typing import Any
|
||||
|
||||
from M02_MasterTemplete import M02_Doc_Copy as dc
|
||||
from M02_MasterTemplete import M02_Doc_Gap as gap
|
||||
from M02_MasterTemplete import M02_Doc_Import as dim
|
||||
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
||||
from M02_MasterTemplete import M02_Sangeun_Doc as sd
|
||||
@@ -196,8 +197,10 @@ def settle(out: dict, whole: Any, job: Any, raw: Any) -> dict:
|
||||
"수식 문서로 고친 단가산출 — 옛 칸(덮개 · 줄) 고침은 수식 탭에서 · 또는 [재생성]",
|
||||
409,
|
||||
)
|
||||
copy = dc.refresh(have)[0] if job == skc.PRICE and not dim.is_imported(out) else have
|
||||
return {**out, KEY: norm(copy)}
|
||||
if dim.is_imported(out):
|
||||
return {**out, KEY: norm(have)}
|
||||
copy = dc.refresh(have)[0] if job == skc.PRICE else have
|
||||
return {**out, KEY: norm(gap.fill(copy))} # 사본 빈틈 = 지금 값으로 박음(822-1)
|
||||
# 빈 SK(바탕 · 줄 없음) = 빈 문서(요구서_664 0 장) · 수식 길로 고친 빈 SK = 위 따로(804-4)
|
||||
if not skc.has(out) and not dim.is_imported(out):
|
||||
empty = seed(out)
|
||||
@@ -207,4 +210,7 @@ def settle(out: dict, whole: Any, job: Any, raw: Any) -> dict:
|
||||
calls = {} if job == skc.REGEN else (have or {}).get("부름") or {}
|
||||
first = {**(dc.values_of(out[skc.KEY]) if skc.has(out) else {}), "부름": calls}
|
||||
copy = copy_of({**out, KEY: first}, box[-1] if box else None)
|
||||
if copy and skc.has(out) and (keys := gap.gaps(copy)): # 파생 — 옛 로직 사본에 박음(822-1)
|
||||
out = {**out, skc.KEY: skc.grow(out[skc.KEY], skc.snap([], keys))}
|
||||
copy = {**copy, **dc.values_of(out[skc.KEY])}
|
||||
return {**out, KEY: norm({k: v for k, v in (copy or first).items() if k != "따로"})}
|
||||
|
||||
@@ -17,11 +17,11 @@ import json
|
||||
from typing import Any
|
||||
|
||||
from M02_MasterTemplete import M02_Doc_Copy as dc
|
||||
from M02_MasterTemplete import M02_Doc_Gap as gap
|
||||
from M02_MasterTemplete import M02_Doc_Import as dim
|
||||
from M02_MasterTemplete import M02_Doc_Screen as screen
|
||||
from M02_MasterTemplete import M02_Doc_Sk as dsk
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
from M02_MasterTemplete import M02_MyMachine as mym
|
||||
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
||||
from M02_MasterTemplete import M02_Sangeun_Doc as sd
|
||||
|
||||
@@ -77,7 +77,11 @@ def answer(copy: dict, sk: dict) -> dict[str, Any]:
|
||||
got = dsk.run(sk, copy)
|
||||
head = {k: copy.get(k) for k in ("시점", "단가시점")}
|
||||
mark = {**head, "따로": bool(copy.get("따로"))}
|
||||
mark |= {"단가기준": dim.basis_of(sk)} if dim.is_imported(sk) else dc.state(copy)
|
||||
mark |= (
|
||||
{"단가기준": dim.basis_of(sk)}
|
||||
if dim.is_imported(sk)
|
||||
else {**dc.state(copy), "사본없음": len(gap.gaps(copy))} # 저장하면 지금 값으로 굳음
|
||||
)
|
||||
body = {
|
||||
"문서": copy["문서"],
|
||||
"부름": copy.get("부름") or {},
|
||||
@@ -129,22 +133,12 @@ def edited(copy: dict, body: dict, key: str, sk: dict | None = None) -> dict:
|
||||
*(c for d in out.get("끊음", {}).values() for c in dc.calls(d)),
|
||||
]
|
||||
if not dim.is_imported(sk):
|
||||
out |= _mine(out)
|
||||
out["부름"] = dc.closure(dc.over(out), calls, copy.get("부름"))
|
||||
out = gap.fill(out) # 셈이 읽은 줄 가운데 사본 없는 것 = 지금 값으로 박음(822-1)
|
||||
out["따로"] = True
|
||||
return out
|
||||
|
||||
|
||||
def _mine(copy: dict) -> dict:
|
||||
"""줄 쌓기에서 고른 내 기계(기계='개인 EQP…') 가운데 값 사본에 없는 것만 지금 값으로 더함
|
||||
(821-3) — 그 뒤 내 기계를 고쳐도 금액 그대로 + 「단가새값」 · [단가 갱신] 으로 반영 ·
|
||||
지워도 마지막 값."""
|
||||
keys = mym.keys_in(copy.get("문서"))
|
||||
if not keys or "로직" not in copy:
|
||||
return {}
|
||||
return skc.grow(dc.values_of(copy), skc.snap([], keys))
|
||||
|
||||
|
||||
def preview(key: str, body: dict) -> dict[str, Any]:
|
||||
"""미리 셈(저장 없음) — {셈, 전, 후, 바뀐자원?, 버림?}."""
|
||||
doc = _file(key)["문서"]
|
||||
|
||||
Reference in New Issue
Block a user