- 새 M02_Sangeun_Copy — 사본 = 로직 · 하위 로직 · 찾기 표 · 그 밖 요소(로직 갈래) + 자원 단가 LB · MT · EQ · MO · FX(단가 기준 시점 갈래) - 셈 = M01 색인 위 사본 줄 덮개(Copy) · Calc 바탕 줄 · run · 저장 · 셈 길 첫머리만 고리(줄 수 그대로) - 사본은 서버가 정함(저장본 사본 · 없으면 받은 사본 · 그것도 없으면 저장 때 찍음) · 할일 칸 사본할일 = [저장] 때 적용 · 자동 갱신 없음 - 지워진 M01 키 = 사본 마지막 값 · 표지 지운키 · 사본 없는 옛 SK = 옛 길 - 같은 내용 지문에 사본 몫(지금 M01 과 다른 판만) · 길 POST …/sangeun/copy/price|regen - 시험 test_795_1_sk_copy 6 · 기존 SK · 지문 시험 294 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
214 lines
8.9 KiB
Python
214 lines
8.9 KiB
Python
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
|
"""795-1 SK 로직 사본 — 저장 때 M01 닫힌 묶음을 찍고 셈은 사본으로(임시 storage · M01 은 메모리 덮개).
|
|
|
|
① M01 로직 줄 바꿔도 사본 SK 금액 그대로 ② 노임 바꿔도 [단가 갱신] 전엔 그대로 · 누르면 따라감
|
|
③ [재생성] 뒤 고친 칸 다시 얹힘 · 못 얹은 칸 알림 ④ M01 새 판 배지 ⑤ 지워진 키 = 마지막 값
|
|
⑥ 옛 SK(사본 없음) = 옛 길 · 지문 그대로 ⑦ 가져온 식 SK 같은 규칙.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import copy
|
|
import json
|
|
|
|
import pytest
|
|
|
|
from M01_MasterData import M01_MasterData_Store as m01
|
|
from M02_MasterTemplete import M02_Labor_Doc as labor
|
|
from M02_MasterTemplete import M02_Labor_Ref as refs
|
|
from M02_MasterTemplete import M02_Library_Same as same
|
|
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
|
from M02_MasterTemplete import M02_Sangeun_Calc as calc
|
|
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
|
from M02_MasterTemplete import M02_Sangeun_Imported as imp
|
|
from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층
|
|
|
|
PCT = "GC001109" # 원/㎡ · 인력 둘 + 「노무비 * 3 / 100」
|
|
MAN = "LB000002" # 보통인부
|
|
|
|
|
|
def _live():
|
|
return m01.loaded()[1]
|
|
|
|
|
|
def _fake(monkeypatch, rows=(), drop=()):
|
|
"""M01 바꿈 흉내 — 지금 색인 위에 바뀐 줄 · 지운 키(정본 파일 안 고침)."""
|
|
files, live = m01.loaded()
|
|
fake = skc.Copy(live, [copy.deepcopy(r) for r in rows])
|
|
for key in drop:
|
|
skc.Copy._own(fake.index, live.index, key[:2]).pop(key, None)
|
|
monkeypatch.setattr(m01, "loaded", lambda: (files, fake))
|
|
return fake
|
|
|
|
|
|
def _sk(folder, **doc):
|
|
with store.at(folder):
|
|
body = {"이름": "sub2임시 사본", "단위": "㎡", "더한줄": [], **doc}
|
|
return refs.create("sangeun", body)["이름"]
|
|
|
|
|
|
def _doc(folder, key):
|
|
with store.at(folder):
|
|
return store.read("sangeun", key)["문서"]
|
|
|
|
|
|
def _save(folder, key, doc):
|
|
with store.at(folder):
|
|
store.write("sangeun", key, store.read("sangeun", key)["판"], doc)
|
|
|
|
|
|
def _calc(folder, doc):
|
|
with store.at(folder):
|
|
return calc.calc_doc(doc, None, False)
|
|
|
|
|
|
def _sum(folder, key):
|
|
return _calc(folder, _doc(folder, key))["기준"]["계"]
|
|
|
|
|
|
def _cids(folder, key):
|
|
return [x["cid"] for x in _calc(folder, _doc(folder, key))["줄"]]
|
|
|
|
|
|
def _changed(row, at=0):
|
|
row = copy.deepcopy(row)
|
|
row["호표"][at]["수량"] = f"({row['호표'][at]['수량']}) * 2"
|
|
return row
|
|
|
|
|
|
def test_copy_stamped_and_logic_change_kept(world, monkeypatch):
|
|
"""① · ④ 저장 때 사본(로직 · 단가 갈래) · M01 로직 바꿔도 금액 그대로 · 배지만."""
|
|
me = world["personal"]
|
|
key = _sk(me, 바탕={"로직": PCT})
|
|
got = _doc(me, key)["사본"]
|
|
assert PCT in {r["키"] for r in got["로직"]}
|
|
assert got["단가"] and all(r["키"][:2] in skc.RES for r in got["단가"])
|
|
assert not any(r["키"][:2] in skc.RES for r in got["로직"])
|
|
first = _calc(me, _doc(me, key))
|
|
assert first["사본"]["M01새판"] is False and first["사본"]["지운키"] == []
|
|
was = first["기준"]["계"]
|
|
plain = labor.run_line(_live(), PCT, {})["기준"]["계"]
|
|
_fake(monkeypatch, [_changed(_live().logic(PCT))])
|
|
assert labor.run_line(m01.loaded()[1], PCT, {})["기준"]["계"] != plain # M01 셈은 바뀜
|
|
now = _calc(me, _doc(me, key))
|
|
assert now["기준"]["계"] == was
|
|
assert now["사본"]["M01새판"] is True
|
|
|
|
|
|
def test_price_refresh_only_on_press(world, monkeypatch):
|
|
"""② 노임 바꿈 → 그대로 · [단가 갱신] 미리 셈 · 저장 = 새 SK 와 같은 값 · 바뀐자원."""
|
|
me = world["personal"]
|
|
key = _sk(me, 바탕={"로직": PCT})
|
|
was = _sum(me, key)
|
|
lb = _cids(me, key)[0].split(":")[1].split("#")[0]
|
|
row = copy.deepcopy(_live().get(lb))
|
|
row["값"] = row["값"] * 2
|
|
_fake(monkeypatch, [row])
|
|
assert _sum(me, key) == was # 누르기 전 = 단가 기준 시점 값
|
|
fresh = _sum(me, _sk(me, 바탕={"로직": PCT})) # 지금 M01 로 새로 찍은 SK
|
|
assert fresh != was
|
|
with store.at(me):
|
|
got = skc.preview(_doc(me, key), skc.PRICE)
|
|
assert got["전"]["계"] == was and got["후"]["계"] == fresh
|
|
assert [x["키"] for x in got["바뀐자원"]] == [lb]
|
|
assert got["문서"][skc.JOB] == skc.PRICE
|
|
_save(me, key, got["문서"]) # [저장] = 서버가 할일 적용
|
|
saved = _doc(me, key)
|
|
assert skc.JOB not in saved and _sum(me, key) == fresh
|
|
assert saved["사본"]["단가시점"] >= saved["사본"]["시점"]
|
|
|
|
|
|
def test_regen_reapplies_covers(world, monkeypatch):
|
|
"""③ [재생성] — 덮개 · 까닭 새 사본에 다시 얹힘 · 없어진 줄 덮개 = 못얹은 · 배지 꺼짐."""
|
|
me = world["personal"]
|
|
probe = _sk(me, 바탕={"로직": PCT})
|
|
one, two = _cids(me, probe)[:2]
|
|
covers = {one: {"qty": 0.5}, two: {"qty": 0.7}}
|
|
key = _sk(me, 바탕={"로직": PCT}, 덮개=covers, 까닭={one: "현장 실측"})
|
|
row = copy.deepcopy(_live().logic(PCT))
|
|
row["호표"] = [x for n, x in enumerate(row["호표"]) if n != 1] # 둘째 줄 없앤 새 판
|
|
_fake(monkeypatch, [row])
|
|
with store.at(me):
|
|
got = skc.preview(_doc(me, key), skc.REGEN)
|
|
assert [x["cid"] for x in got["못얹은"]] == [two]
|
|
assert got["전"]["계"] != got["후"]["계"]
|
|
_save(me, key, got["문서"])
|
|
doc = _doc(me, key)
|
|
assert doc["덮개"][one]["qty"] == 0.5 and doc["까닭"][one] == "현장 실측"
|
|
now = _calc(me, doc)
|
|
assert now["줄"][0]["덮개"] == ["qty"]
|
|
assert now["사본"]["M01새판"] is False
|
|
assert now["기준"]["계"] == got["후"]["계"]
|
|
|
|
|
|
def test_deleted_keys_keep_last_value(world, monkeypatch):
|
|
"""⑤ 사본이 부르는 M01 키(바탕 로직 · 노임)가 지워져도 마지막 값 · 지운키 표지."""
|
|
me = world["personal"]
|
|
key = _sk(me, 바탕={"로직": PCT})
|
|
was = _sum(me, key)
|
|
lb = _cids(me, key)[0].split(":")[1].split("#")[0]
|
|
_fake(monkeypatch, drop=[PCT, lb])
|
|
with pytest.raises(Exception):
|
|
m01.loaded()[1].logic(PCT)
|
|
now = _calc(me, _doc(me, key))
|
|
assert now["기준"]["계"] == was
|
|
assert {PCT, lb} <= set(now["사본"]["지운키"])
|
|
with store.at(me):
|
|
got = skc.preview(_doc(me, key), skc.PRICE)
|
|
assert {"키": lb, "이름": got["바뀐자원"][0]["이름"], "지워짐": True} in got["바뀐자원"]
|
|
assert got["후"]["계"] == was
|
|
|
|
|
|
def test_old_sk_without_copy_old_path(world, monkeypatch):
|
|
"""⑥ 사본 없는 옛 SK = M01 지금 값(옛 길) · 같은 내용 지문 = 새 사본 SK 와 같음."""
|
|
me = world["personal"]
|
|
key = _sk(me, 바탕={"로직": PCT})
|
|
path = me / "sangeun" / f"{key}.json"
|
|
raw = json.loads(path.read_bytes())
|
|
old = {k: v for k, v in raw.items() if k != "사본"}
|
|
path.write_text(json.dumps(old, ensure_ascii=False), encoding="utf-8")
|
|
fresh = _sk(me, 바탕={"로직": PCT})
|
|
assert _sum(me, key) == _sum(me, fresh)
|
|
assert "사본" not in _calc(me, _doc(me, key))
|
|
with store.at(me):
|
|
assert same.Same().finger("sangeun", old) == same.Same().finger("sangeun", _doc(me, fresh))
|
|
_fake(monkeypatch, [_changed(_live().logic(PCT))])
|
|
moved = labor.run_line(m01.loaded()[1], PCT, {})["기준"]["계"]
|
|
assert _sum(me, key) == pytest.approx(moved, abs=1) # 옛 길 = 따라감
|
|
assert _sum(me, fresh) != _sum(me, key) # 사본 SK = 그대로
|
|
with store.at(me): # 판 다른 두 SK = 지문 다름(오판 막음)
|
|
assert same.Same().finger("sangeun", _doc(me, key)) != same.Same().finger(
|
|
"sangeun", _doc(me, fresh)
|
|
)
|
|
|
|
|
|
def _imported_row():
|
|
man = {"종류": "인력", "이름": "보통인부", "단위": "인", "수량": "0.5", "비목": "노무비"}
|
|
mat = {"종류": "재료", "이름": "각재", "단위": "㎥", "수량": "0.01", "비목": "재료비"}
|
|
return {
|
|
"이름": "sub2임시 가져온",
|
|
"결과단위": "원/㎡",
|
|
"호표": [{**man, "단가": 165545, "이음": MAN}, {**mat, "단가": 500661}],
|
|
}
|
|
|
|
|
|
def test_imported_same_rule(world, monkeypatch):
|
|
"""⑦ 가져온 식 SK(단가기준 우리) — 이음 노임 바꿔도 그대로 · [단가 갱신] 뒤 따라감."""
|
|
me = world["personal"]
|
|
with store.at(me):
|
|
key = imp.create(_imported_row(), None, "sub2임시 가져온")["이름"]
|
|
doc = _doc(me, key)
|
|
assert MAN in {r["키"] for r in doc["사본"]["단가"]}
|
|
with store.at(me):
|
|
ours = imp.to_price(doc, "우리")["문서"]
|
|
_save(me, key, ours)
|
|
was = _sum(me, key)
|
|
row = copy.deepcopy(_live().get(MAN))
|
|
row["값"] = row["값"] * 2
|
|
_fake(monkeypatch, [row])
|
|
assert _sum(me, key) == was
|
|
with store.at(me):
|
|
got = skc.preview(_doc(me, key), skc.PRICE)
|
|
assert [x["키"] for x in got["바뀐자원"]] == [MAN]
|
|
assert got["후"]["노무비"] == pytest.approx(got["전"]["노무비"] * 2, abs=1)
|