feat(795-2): 일위대가 · 사전조합 로직 사본 — 저장 때 찍음 · [단가 갱신] · [재생성] · 줄 덮개 다시 얹힘
- 새 M02_Labor_Copy — SK 사본(795-1) 한 벌 · 담은로직 로직 줄 · 줄 덮개 더한줄 · 고정 이음 · 자재 MT 가 닿는 M01 닫힌 묶음
- 셈 = Labor_Doc.calc 층 셈 첫머리 사본 덮개 · SC 1 단위 값(Expand) = 그 SC 사본 · 프로젝트 층 · B09 = 옛 길(795-4)
- 사본 정함 = 받은 사본 먼저(열 복사 · 층 복사 = 원본 사본 그대로) → 저장본 → [저장] 때 찍음 · 새 줄만 더함
- 길 POST …/labor/{열 | SC 키}/copy/price|regen · 셈 답 덧칸 사본 표지 · 같은 내용 지문 SC 사본 몫
- Sangeun_Copy 찍기 갈래 나눔(reach · snap · grow) · SK 더한줄 인력 · 재료 · 기계 요소도 사본에
- Labor_Doc 줄 수 그대로(686) · 시험 test_795_2_sc_copy 6 · 기존 일위대가 · SC · SK 시험 통과
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
"""M02 일위대가 · 사전조합(SC) 로직 사본(PLAN 795-2 · 요구 655 · 656 · 요구서_655) — 서버 단독.
|
||||
|
||||
SK 사본(`M02_Sangeun_Copy` · 795-1) 한 벌 — 문서 칸 `사본` 꼴 · 판 · 단가 · 할일 칸 `사본할일`
|
||||
(단가갱신 | 재생성) · [단가 갱신] = 자원 단가 줄만 · 자동 갱신 없음 · 지워진 M01 키 = 마지막 값.
|
||||
사본에 담는 것 = 담은로직 로직 줄 · 줄 덮개(`M02_Labor_Patch`) 더한줄(로직 · 요소 · 고정 이음) ·
|
||||
고정 줄 이음 · 사용자 자재(MT) 가 닿는 M01 닫힌 묶음(참조 줄 = 그 문서 제 사본).
|
||||
셈 = `M02_Labor_Doc.calc` 층 셈(whole 안 줌) 첫머리 `live` — M01 색인 위 사본 줄(`skc.Copy`) ·
|
||||
줄 덮개 = 사본 위 고친 칸(cid 열쇠 · [재생성] 뒤 다시 얹힘 · 못 얹은 칸 = 짝잃음) ·
|
||||
사전조합 1 단위 값(`Expand`) = 그 SC 사본(`combo`) ·
|
||||
프로젝트 층 · B09(단가 책 · 굳힌 참조사본) = 옛 길(795-4).
|
||||
사본 정함(`settle` · 셈 · 저장 첫머리) = 받은 사본 먼저(열 복사 · 층 복사 = 원본 사본 그대로 · 판은
|
||||
서버가 다시 셈) → 없으면 저장본(일위대가 = labor/<열> · SC = precombo/<키>) → [저장] 때 없으면 새로
|
||||
찍음 · 사본에 없는 새 줄만 지금 M01 에서 더함 · 사본 없는 옛 문서 = 셈은 옛 길.
|
||||
길(`M02_Labor_Router`) POST …/labor/{열 | SC 키}/copy/{price|regen} {doc, 수량?} →
|
||||
{doc(사본할일), 전, 후, 바뀐자원 | 못얹은}(저장 없음).
|
||||
짝(CLAUDE.md 5장 ①) `M02_MasterTemplete_Labor_Calc.ts` = 서버 기준 값을 받아 수량 · 반영 · 합만 —
|
||||
사본은 기준 값에만 닿음(짝 안 고침 · 거울 시험 `test_795_2_sc_copy`).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
||||
|
||||
KEY, JOB, PRICE, REGEN = skc.KEY, skc.JOB, skc.PRICE, skc.REGEN
|
||||
_SC = re.compile(r"^SC-\d{6}$")
|
||||
|
||||
|
||||
def _project() -> bool:
|
||||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||||
|
||||
return refs.here()[0] == "project"
|
||||
|
||||
|
||||
def stamp(doc: dict) -> dict | None:
|
||||
"""지금 M01 로 새 사본 — 닿을 것 없음(참조 줄 · 손 단가 고정 줄만) = None."""
|
||||
lines = [x for x in doc.get("담은로직") or [] if isinstance(x, dict)]
|
||||
keys = [str(x["로직"]) for x in lines if x.get("로직")]
|
||||
links = [str(v) for x in lines for v in ((x.get("고정") or {}).get("이음") or {}).values() if v]
|
||||
for x in lines:
|
||||
more = skc.reach((x.get("패치") or {}).get("더한줄"))
|
||||
keys, links = keys + more[0], links + more[1]
|
||||
links += [
|
||||
str(m["코드"]) for m in doc.get("자재") or [] if isinstance(m, dict) and m.get("코드")
|
||||
]
|
||||
return skc.snap(list(dict.fromkeys(keys)), list(dict.fromkeys(links)))
|
||||
|
||||
|
||||
def _stored(doc: dict) -> dict | None:
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
|
||||
key = str(doc.get("키") or doc.get("열") or "")
|
||||
kind = "precombo" if _SC.match(key) else "labor"
|
||||
try:
|
||||
got = json.loads(store._path(kind, key).read_bytes())
|
||||
except (OSError, ValueError, store.StoreError):
|
||||
return None
|
||||
return got[KEY] if skc.has(got) else None
|
||||
|
||||
|
||||
def settle(doc: Any, save: bool = False) -> Any:
|
||||
"""셈 · 저장 첫머리 — 서버가 정한 사본으로 갈음(할일 · 저장 때 찍음 · 새 줄 · 할일 칸 뗌)."""
|
||||
if not isinstance(doc, dict) or _project():
|
||||
return doc
|
||||
job = doc.get(JOB) # 모르는 할일 = 없음
|
||||
out = {k: v for k, v in doc.items() if k not in (KEY, JOB)}
|
||||
copy = skc.taken(doc.get(KEY)) or _stored(doc)
|
||||
if job == REGEN or (copy is None and save):
|
||||
copy = stamp(out)
|
||||
elif job == PRICE and copy:
|
||||
copy = skc.refresh(copy, skc.whole_())[0]
|
||||
if save and copy:
|
||||
copy = skc.grow(copy, stamp(out))
|
||||
return {**out, KEY: copy} if copy else out
|
||||
|
||||
|
||||
def keep(raw: Any, out: dict) -> dict:
|
||||
"""정리한 문서에 사본 · 할일 칸을 실어 보냄(꼴 검사는 `settle` 몫)."""
|
||||
if not isinstance(raw, dict):
|
||||
return out
|
||||
got = {k: raw[k] for k in (KEY, JOB) if raw.get(k) is not None}
|
||||
return {**out, **got}
|
||||
|
||||
|
||||
def live(doc: dict) -> Any:
|
||||
"""층 셈 색인 — 사본 있는 문서 = M01 위 사본 줄 · 없거나 프로젝트 층 = 지금 M01."""
|
||||
from M01_MasterData import M01_MasterData_Store as m01
|
||||
|
||||
whole = m01.loaded()[1]
|
||||
return whole if _project() else skc.over(settle(doc), whole)
|
||||
|
||||
|
||||
def combo(expand: Any, doc: dict, trail: tuple[str, ...]) -> dict[str, Any]:
|
||||
"""사전조합 1 단위 값 — 그 SC 사본 색인으로(층 셈만 · 프로젝트 = 굳힌 단가 그대로)."""
|
||||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||||
|
||||
was = expand.whole
|
||||
if expand.read is refs.read_ref and skc.has(doc):
|
||||
expand.whole = skc.over(doc, was)
|
||||
try:
|
||||
return expand._combo(doc, trail)
|
||||
finally:
|
||||
expand.whole = was
|
||||
|
||||
|
||||
def mark(ans: dict, doc: dict) -> dict:
|
||||
"""셈 답 덧칸 `사본` {시점, 단가시점, M01새판, 지운키, 단가새값} — 사본 없음 = 칸 없음."""
|
||||
return skc.mark(ans, doc)
|
||||
|
||||
|
||||
# ── [단가 갱신] · [재생성] 미리 셈(저장 없음) ──────────────────────────
|
||||
def _money(ans: dict) -> dict:
|
||||
return {k: ans.get(k) for k in ("기준합", "반영합")}
|
||||
|
||||
|
||||
def _lost(ans: dict) -> dict[str, dict]:
|
||||
got = {}
|
||||
for n, line in enumerate(ans.get("줄") or []):
|
||||
for x in line.get("짝잃음") or []:
|
||||
if isinstance(x, dict):
|
||||
got[f"{n}|{x.get('cid')}"] = {**x, "줄": n}
|
||||
return got
|
||||
|
||||
|
||||
def preview(doc: dict, job: str, given: dict | None = None) -> dict[str, Any]:
|
||||
"""{doc(할일 얹음), 전, 후, 바뀐자원 · 못얹은} — `doc` = 정리한 문서 · 재생성 ⊃ 단가갱신."""
|
||||
from M02_MasterTemplete import M02_Labor_Doc as labor
|
||||
|
||||
new = REGEN if REGEN in (doc.get(JOB), job) else job
|
||||
after_doc = {**doc, JOB: new}
|
||||
before, after = labor.calc(doc, given), labor.calc(after_doc, given)
|
||||
out: dict[str, Any] = {"doc": after_doc, "전": _money(before), "후": _money(after)}
|
||||
if job == PRICE:
|
||||
copy = skc.taken(doc.get(KEY)) or _stored(doc)
|
||||
out["바뀐자원"] = skc.refresh(copy, skc.whole_())[1] if copy else []
|
||||
else:
|
||||
was = _lost(before)
|
||||
out["못얹은"] = [
|
||||
{"줄": x["줄"], "cid": x.get("cid"), "까닭": x.get("까닭") or "새 사본에 그 줄 없음"}
|
||||
for c, x in _lost(after).items()
|
||||
if c not in was
|
||||
]
|
||||
return out
|
||||
@@ -42,7 +42,7 @@ from M01_MasterData import M01_MasterData_Store as m01
|
||||
from M01_MasterData import M01_MasterData_Store_Combo as combo_store
|
||||
from M02_MasterTemplete import M02_Labor_Fixed as fixed
|
||||
from M02_MasterTemplete import M02_Labor_Inputs as labor_inputs
|
||||
from M02_MasterTemplete import M02_Labor_Patch as patch
|
||||
from M02_MasterTemplete import M02_Labor_Copy as lc, M02_Labor_Patch as patch
|
||||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||||
from M02_MasterTemplete import M02_Labor_Spec as spec
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
@@ -102,7 +102,7 @@ def clean(doc: Any) -> dict[str, Any]:
|
||||
모르는 입력 이름 · 빈 입력값은 버림 · 자재 이름 · 규격 · 단위는 M01 것."""
|
||||
if not isinstance(doc, dict):
|
||||
raise _bad("일위대가 문서가 묶음 아님")
|
||||
whole = m01.loaded()[1]
|
||||
whole = lc.live(doc) # 로직 사본(795-2) — 지워진 M01 키도 사본 줄로
|
||||
lines, seen, here = [], set(), None
|
||||
for at, one in enumerate(doc.get("담은로직") or [], start=1):
|
||||
where = f"단가산출 기초 {at}째"
|
||||
@@ -203,7 +203,7 @@ def clean(doc: Any) -> dict[str, Any]:
|
||||
cols = spec.clean(doc.get("규격"), {spec.line_key(x) for x in [*lines, *mats]})
|
||||
except spec.SpecError as e:
|
||||
raise _bad(str(e)) from e
|
||||
return {**out, "규격": cols} if cols else out
|
||||
return lc.keep(doc, {**out, "규격": cols} if cols else out) # 사본 칸(795-2)
|
||||
|
||||
|
||||
def _alias(alias: Any, where: str) -> str | None:
|
||||
@@ -501,7 +501,7 @@ def calc(
|
||||
|
||||
프로젝트 사본 셈(142-1)도 이 한 벌 — `whole` = 사본 `단가.json`(`M02_Item_Prices.load_prices`) ·
|
||||
`read` = 참조 → 굳힌 `참조사본` · `pills` = 사본 `알약`(가져온 때 것). 없으면 지금 M01 · 층."""
|
||||
whole, have = m01.loaded()[1] if whole is None else whole, _area_of(doc.get("열")) if given is None else given # fmt: skip
|
||||
whole, have = lc.live(doc) if whole is None else whole, _area_of(doc.get("열")) if given is None else given # fmt: skip
|
||||
expand = refs.Expand(whole, read or refs.read_ref, have) # 사전조합 안 줄 수량 = 알약 값(723-1)
|
||||
if pills is None:
|
||||
pills = combo_store.combo_pills({"담은로직": doc.get("담은로직") or []})["물량"]
|
||||
@@ -665,7 +665,7 @@ def _json(value: Any) -> Any:
|
||||
def server(doc: Any) -> dict[str, Any]:
|
||||
"""[저장] · 복사 때 서버 정본 — 정리 + 지금 면적 값으로 `계산값`(브라우저 값 버림) ·
|
||||
사용자 자재가 로직 자재 품목과 같으면 400(103-1 · 같은 품목 두 번 셈)."""
|
||||
got = clean(doc)
|
||||
got = lc.settle(clean(doc), True) # 로직 사본(795-2) — 찍기 · 할일 · 새 줄
|
||||
out = calc(got)
|
||||
no_twice(got, out)
|
||||
return {**got, "계산값": {**out, **spec_sums(got, out)}}
|
||||
|
||||
@@ -13,6 +13,7 @@ from collections.abc import Callable
|
||||
from decimal import Decimal
|
||||
from typing import Any
|
||||
|
||||
from M02_MasterTemplete import M02_Labor_Copy as lc
|
||||
from M02_MasterTemplete import M02_Labor_Fixed as fixed
|
||||
from M02_MasterTemplete import M02_Labor_Patch as patch
|
||||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||||
@@ -68,8 +69,8 @@ class Expand:
|
||||
self.memo[rid] = self._promote(doc)
|
||||
elif refs.kind_of(ref["키"]) == "sangeun": # 단가산출(715-2) = 고친 줄 셈 1 단위
|
||||
self.memo[rid] = calc.unit(doc, self.whole, self, (*trail, rid))
|
||||
else:
|
||||
self.memo[rid] = self._combo(doc, (*trail, rid))
|
||||
else: # 사전조합 = 그 SC 로직 사본(795-2)
|
||||
self.memo[rid] = lc.combo(self, doc, (*trail, rid))
|
||||
return self.memo[rid]
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -214,7 +214,9 @@ def clean_doc(kind: str, doc: Any) -> dict[str, Any]:
|
||||
out["자재"] = _combo_mats(doc, out["담은로직"])
|
||||
out.update({k: str(doc.get(k) or "").strip() for k in ("구분", "상세구분")})
|
||||
out["본뜬"] = doc["본뜬"] if isinstance(doc.get("본뜬"), dict) else None
|
||||
return out
|
||||
from M02_MasterTemplete import M02_Labor_Copy as lc
|
||||
|
||||
return lc.settle(lc.keep(doc, out), True) # 로직 사본(795-2)
|
||||
|
||||
|
||||
def is_rate(one: Any) -> bool:
|
||||
|
||||
@@ -18,6 +18,7 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from common_util.common_util_auth import verify_session
|
||||
from M02_MasterTemplete import M02_Labor_Copy as lc
|
||||
from M02_MasterTemplete import M02_Labor_Doc as labor
|
||||
from M02_MasterTemplete import M02_Labor_Ref as refs
|
||||
from M02_MasterTemplete import M02_Layer_Access as access
|
||||
@@ -53,7 +54,34 @@ def _doc(column: str, sent: dict[str, Any] | None) -> dict[str, Any]:
|
||||
|
||||
def _calc(column: str, body: CalcBody) -> dict[str, Any]:
|
||||
doc = _doc(column, body.doc)
|
||||
return {**labor.calc(doc, body.수량), "알약": labor.pills(doc)}
|
||||
got = lc.mark(labor.calc(doc, body.수량), lc.settle(doc)) # 사본 표지(795-2)
|
||||
return {**got, "알약": labor.pills(doc)}
|
||||
|
||||
|
||||
_JOBS = {"price": lc.PRICE, "regen": lc.REGEN}
|
||||
|
||||
|
||||
@router.post("/layers/{layer}/labor/{column}/copy/{how}")
|
||||
def labor_copy(
|
||||
layer: Layer,
|
||||
column: str,
|
||||
how: str,
|
||||
body: CalcBody,
|
||||
owner: str | None = None,
|
||||
session: Session = Depends(verify_session),
|
||||
) -> dict:
|
||||
"""로직 사본(795-2) — price [단가 갱신] · regen [재생성] · 일위대가 열 · 사전조합 SC 키 ·
|
||||
답 = 할일 얹은 doc(화면 캐시 · [저장] 때 서버가 적용) + 전 · 후 합 + 바뀐자원 | 못얹은."""
|
||||
if how not in _JOBS:
|
||||
raise HTTPException(status_code=404, detail="price · regen")
|
||||
return _call(_root(session, layer, owner), _copy_job, column, body, _JOBS[how])
|
||||
|
||||
|
||||
def _copy_job(column: str, body: CalcBody, job: str) -> dict[str, Any]:
|
||||
"""미리 셈은 정리한 문서로 · 답 doc = 보낸 화면 문서 + 할일(SC · 일위대가 꼴 그대로)."""
|
||||
got = lc.preview(_doc(column, body.doc), job, body.수량)
|
||||
sent = body.doc if body.doc is not None else store.read("labor", column)["문서"]
|
||||
return {**got, "doc": {**sent, lc.JOB: got["doc"][lc.JOB]}}
|
||||
|
||||
|
||||
def _pills(column: str) -> dict[str, Any]:
|
||||
|
||||
@@ -150,6 +150,7 @@ class Same:
|
||||
"담은로직": _sorted([self._line(x, trail, False) for x in doc.get("담은로직") or []]),
|
||||
"자재": _sorted(mats),
|
||||
"규격": norm(doc.get("규격")),
|
||||
"사본": skc.same_part(doc), # 로직 사본(795-2) — 지금 M01 과 다른 판만
|
||||
}
|
||||
return {k: v for k, v in body.items() if v not in EMPTY}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ RES = ("LB", "MT", "EQ", "MO", "FX") # 자원 단가 = 단가 기준 시점 묶
|
||||
_MASTER = prices.mf.Master
|
||||
|
||||
|
||||
def _whole() -> Any:
|
||||
def whole_() -> Any:
|
||||
return prices.m01.loaded()[1]
|
||||
|
||||
|
||||
@@ -142,17 +142,29 @@ def stamp(doc: dict) -> dict | None:
|
||||
base = doc.get("바탕") or {}
|
||||
if "참조" in base:
|
||||
return None
|
||||
adds = doc.get("더한줄") or []
|
||||
keys = [str(base["로직"])] if base.get("로직") else []
|
||||
keys += [str(x["로직"]) for x in adds if x.get("종류") == "로직" and x.get("로직")]
|
||||
links = [v for x in adds for v in ((x.get("고정") or {}).get("이음") or {}).values() if v]
|
||||
keys, links = reach(doc.get("더한줄"))
|
||||
keys = [str(base["로직"]), *keys] if base.get("로직") else keys
|
||||
extra = [row] if (row := imp.row_of(doc)) else []
|
||||
return snap(keys, links, extra)
|
||||
|
||||
|
||||
def reach(adds: Any) -> tuple[list[str], list[str]]:
|
||||
"""더한줄이 닿는 (로직 키, 요소 키) — 로직 줄 · 인력 · 재료 · 기계 요소 · 고정 줄 이음."""
|
||||
adds = [x for x in adds or [] if isinstance(x, dict)]
|
||||
keys = [str(x["로직"]) for x in adds if x.get("종류") == "로직" and x.get("로직")]
|
||||
links = [str(x["요소"]) for x in adds if x.get("종류") in sd.ADD_PART and x.get("요소")]
|
||||
links += [str(v) for x in adds for v in ((x.get("고정") or {}).get("이음") or {}).values() if v]
|
||||
return keys, links
|
||||
|
||||
|
||||
def snap(keys: list[str], links: list[str], extra: list[dict] | None = None) -> dict | None:
|
||||
"""키 · 요소 · 마스터 밖 줄이 닿는 M01 닫힌 묶음 → 사본(닿을 것 없음 = None)."""
|
||||
if not (keys or links or extra):
|
||||
return None
|
||||
got = prices.collect(keys, [str(v) for v in links], extra)
|
||||
got = prices.collect(keys, links, extra)
|
||||
lost = got.pop("_빠진", None)
|
||||
keys = [str(r.get("키")) for data in got.values() for r in data[prices.m01.items_key(data)]]
|
||||
whole = _whole() # 줄 = 셈 색인 것(파일 묶음과 같은 판)
|
||||
whole = whole_() # 줄 = 셈 색인 것(파일 묶음과 같은 판)
|
||||
rows = [whole.index[k[:2]][k] for k in keys if k in whole.index.get(k[:2], {})]
|
||||
out = _split(prices.to_json(rows))
|
||||
return out | ({"빠진": lost} if lost else {})
|
||||
@@ -177,9 +189,8 @@ def refresh(copy: dict, whole: Any) -> tuple[dict, list[dict]]:
|
||||
return {**copy, "단가": rows, "단가판": _fp(rows), "단가시점": _now()}, changed
|
||||
|
||||
|
||||
def _grow(copy: dict, doc: dict) -> dict:
|
||||
"""저장 때 — 사본에 없는 키 줄만 지금 M01 에서 더함(있는 줄 = 사본 그대로)."""
|
||||
fresh = stamp(doc)
|
||||
def grow(copy: dict, fresh: dict | None) -> dict:
|
||||
"""저장 때 — 사본에 없는 키 줄만 새 사본(`fresh` = 지금 M01)에서 더함(있는 줄 = 그대로)."""
|
||||
have = {str(r.get("키")) for r in [*copy["로직"], *(copy.get("단가") or [])]}
|
||||
new = [
|
||||
r
|
||||
@@ -193,7 +204,7 @@ def _grow(copy: dict, doc: dict) -> dict:
|
||||
return {**copy, "로직": logic, "판": _fp(logic), "단가": cost, "단가판": _fp(cost)}
|
||||
|
||||
|
||||
def _taken(raw: Any) -> dict | None:
|
||||
def taken(raw: Any) -> dict | None:
|
||||
"""받은 사본(층 복사 · 새로) — 줄 꼴만 보고 판은 서버가 다시 셈."""
|
||||
if not has({KEY: raw}):
|
||||
return None
|
||||
@@ -223,13 +234,13 @@ def settle(doc: Any, save: bool = False) -> Any:
|
||||
out = {k: v for k, v in doc.items() if k not in (KEY, JOB)}
|
||||
if "참조" in (doc.get("바탕") or {}):
|
||||
return out
|
||||
copy = _stored(doc.get("키")) or _taken(doc.get(KEY))
|
||||
copy = _stored(doc.get("키")) or taken(doc.get(KEY))
|
||||
if job == REGEN or (copy is None and save):
|
||||
copy = stamp(out)
|
||||
elif job == PRICE and copy:
|
||||
copy = refresh(copy, _whole())[0]
|
||||
copy = refresh(copy, whole_())[0]
|
||||
if save and copy:
|
||||
copy = _grow(copy, out)
|
||||
copy = grow(copy, stamp(out))
|
||||
return {**out, KEY: copy} if copy else out
|
||||
|
||||
|
||||
@@ -259,7 +270,7 @@ def mark(ans: dict, doc: dict) -> dict:
|
||||
return ans
|
||||
copy = doc[KEY]
|
||||
head = {"시점": copy.get("시점"), "단가시점": copy.get("단가시점")}
|
||||
return {**ans, KEY: {**head, **state(copy, _whole())}}
|
||||
return {**ans, KEY: {**head, **state(copy, whole_())}}
|
||||
|
||||
|
||||
def same_part(doc: Any) -> str | None:
|
||||
@@ -267,7 +278,7 @@ def same_part(doc: Any) -> str | None:
|
||||
if not has(doc):
|
||||
return None
|
||||
copy = doc[KEY]
|
||||
seen = state(copy, _whole())
|
||||
seen = state(copy, whole_())
|
||||
fresh = not (seen["M01새판"] or seen["지운키"] or seen["단가새값"])
|
||||
return None if fresh else f"{copy.get('판')}:{copy.get('단가판')}"
|
||||
|
||||
@@ -296,8 +307,8 @@ def preview(doc: Any, job: str, given: dict | None = None) -> dict[str, Any]:
|
||||
after = calc.calc_doc(after_doc, given, False)
|
||||
out: dict[str, Any] = {"문서": after_doc, "전": _money(before), "후": _money(after)}
|
||||
if job == PRICE:
|
||||
copy = _stored(doc.get("키")) or _taken(doc.get(KEY))
|
||||
out["바뀐자원"] = refresh(copy, _whole())[1] if copy else []
|
||||
copy = _stored(doc.get("키")) or taken(doc.get(KEY))
|
||||
out["바뀐자원"] = refresh(copy, whole_())[1] if copy else []
|
||||
else:
|
||||
was = _lost(before)
|
||||
out["못얹은"] = [
|
||||
|
||||
Reference in New Issue
Block a user