feat(796-2e-1): 더한 기초 블록 [연결 끊기] · [다시 잇기] 서버 — 끊음 = 이 SK 안 자기 사본 줄 · 수식 고침 · 재생성 때 줄 안 바꿈
- M02_Sangeun_Block 신설: 끊기(닫힌 묶음 굳힘 · 금액 그대로) · 다시 잇기(고침 버림 + 원본 갈음) · 끊은 기초 수식 읽기 · 미리 셈 · 저장 검사 - Calc.sub_run 이 끊은 기초 자기 줄 + 수식 고침을 얹어 셈 · Copy.settle 이 다시 잇기 표지 처리 · [단가 갱신] · [재생성] 응답 끊은기초 한 줄 - Router: block/unlink · relink · equation 몸 블록 · 새 시험 test_796_2e_unlink_basis 6 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀
|
||||
"""796-2e M02 단가산출 더한 기초 블록 [연결 끊기] · [다시 잇기] (임시 storage · M01 은 메모리 덮개).
|
||||
|
||||
① 연결 블록 = 원본(M01) 바뀜을 [재생성] 에서 따라감 ② [연결 끊기] = 금액 그대로 · 이 SK 안 자기 사본 ·
|
||||
원본 바뀜 안 따라감([재생성] 도) ③ 끊은 기초 줄 고침 = 금액 바뀜(미리 셈 = 저장 뒤 서버 셈 · 틀린 고침 400 ·
|
||||
M01 안 바뀜) ④ [다시 잇기] = 고친 것 버림 · 원본 따라감 ⑤ [단가 갱신] = 연결 · 끊은 둘 다 자원 단가 따라감
|
||||
⑥ 꼴 검사(연결 기초에 고침 · 이미 끊음 · 차례 밖).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
|
||||
import pytest
|
||||
|
||||
from M02_MasterTemplete import M02_MasterTemplete_Store as store
|
||||
from M02_MasterTemplete import M02_Sangeun_Block as blk
|
||||
from M02_MasterTemplete import M02_Sangeun_Copy as skc
|
||||
from M02_MasterTemplete import M02_Sangeun_Doc as sd
|
||||
from M02_MasterTemplete import M02_Sangeun_Equation_Full as full
|
||||
from resources.tester.test_795_1_sk_copy import _calc, _changed, _doc, _fake, _live, _save, _sk
|
||||
from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층
|
||||
|
||||
FORM = "GC000211" # 합판거푸집
|
||||
BASIC = "GC001148" # 굴착기 시간당 — 호표 0 = 시간당 기계 × (1 / 작업량)
|
||||
ADD = {"종류": "로직", "로직": BASIC, "수량": 2, "입력값": {}, "이름": "sub3임시 굴착기"}
|
||||
ONLY = "LB000048" # 굴착기 기초에만 닿는 노임(거푸집엔 안 닿음)
|
||||
DOUBLE = [{"할일": "식", "자리": "호표:0", "식": "3 / 작업량", "까닭": "sub3임시 시험"}]
|
||||
|
||||
|
||||
def _sum(folder, doc):
|
||||
return _calc(folder, doc)["기준"]["계"]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def made(world):
|
||||
me = world["personal"]
|
||||
key = _sk(me, 바탕={"로직": FORM}, 더한줄=[copy.deepcopy(ADD)])
|
||||
return me, key
|
||||
|
||||
|
||||
def _cut(me, key):
|
||||
"""끊어서 저장한 SK — (끊기 전 금액, 끊은 문서)."""
|
||||
doc = _doc(me, key)
|
||||
with store.at(me):
|
||||
got = blk.change(doc, 0, "unlink")
|
||||
assert got["전"]["계"] == got["후"]["계"] # 끊기 전후 같음
|
||||
_save(me, key, got["문서"])
|
||||
return got["전"]["계"], _doc(me, key)
|
||||
|
||||
|
||||
def test_unlink_keeps_amount_and_freezes_rows(made):
|
||||
"""② 끊기 = 금액 그대로 · 닫힌 묶음(하위 로직 포함) 이 SK 안에 · 저장 뒤도 같음 · 수식 탭 표지."""
|
||||
me, key = made
|
||||
was = _sum(me, _doc(me, key))
|
||||
plain = _calc(me, _doc(me, key))
|
||||
assert plain["기준"]["계"] == was
|
||||
row_before = copy.deepcopy(_live().logic(BASIC))
|
||||
price, doc = _cut(me, key)
|
||||
assert price == was and _sum(me, doc) == was
|
||||
cut = doc["더한줄"][0]["끊음"]
|
||||
keys = {r["키"] for r in cut["로직"]}
|
||||
assert BASIC in keys and "GC000267" in keys and "GC001147" in keys # 하위 로직까지
|
||||
assert not any(k[:2] in skc.RES for k in keys) # 단가는 SK 사본 한 곳
|
||||
assert _live().logic(BASIC) == row_before # M01 안 바뀜
|
||||
with store.at(me):
|
||||
eq = full.attach({"줄": []}, doc, skc.over(doc, skc.whole_()), {}, None, _calc(me, doc))
|
||||
block = next(r for r in eq["소계"]["줄"] if r.get("블록") == 0)
|
||||
assert block["끊음"] is True and block["나무"] and block["상태"] == "더함"
|
||||
assert not block.get("덮개") # 끊기만으로 「세부」 고침 표지 없음
|
||||
|
||||
|
||||
def test_connected_follows_original_on_regen_cut_does_not(made, monkeypatch):
|
||||
"""①·② 원본 바뀜 — 연결 = [재생성] 에서 따라감 · 끊음 = [재생성] 도 안 따라감."""
|
||||
me, key = made
|
||||
was = _sum(me, _doc(me, key))
|
||||
_fake(monkeypatch, [_changed(_live().logic(BASIC))]) # 호표 0 수량 × 2 (원본 바뀜)
|
||||
assert _sum(me, _doc(me, key)) == was # 누르기 전 = 그대로(자동 갱신 없음)
|
||||
with store.at(me):
|
||||
got = skc.preview(_doc(me, key), skc.REGEN)
|
||||
assert got["후"]["계"] > was and "끊은기초" not in got # 연결 = 원본 따라감
|
||||
monkeypatch.undo()
|
||||
price, doc = _cut(me, key)
|
||||
assert price == was
|
||||
_fake(monkeypatch, [_changed(_live().logic(BASIC))])
|
||||
with store.at(me):
|
||||
got = skc.preview(doc, skc.REGEN)
|
||||
assert got["전"]["계"] == got["후"]["계"] == was # 끊음 = 안 따라감
|
||||
assert got["끊은기초"] == ["sub3임시 굴착기"] # 보고 한 줄
|
||||
_save(me, key, got["문서"])
|
||||
assert _sum(me, _doc(me, key)) == was
|
||||
|
||||
|
||||
def test_price_refresh_follows_in_both(made, monkeypatch):
|
||||
"""⑤ [단가 갱신] — 연결 · 끊은 기초 모두 자원 단가는 따라감(요구 656-1) · 끊은 기초 줄은 그대로."""
|
||||
me, key = made
|
||||
was = _sum(me, _doc(me, key))
|
||||
row = copy.deepcopy(_live().get(ONLY))
|
||||
row["값"] = row["값"] * 2
|
||||
_fake(monkeypatch, [row])
|
||||
with store.at(me):
|
||||
fresh = skc.preview(_doc(me, key), skc.PRICE)
|
||||
assert fresh["후"]["계"] > was and [x["키"] for x in fresh["바뀐자원"]] == [ONLY]
|
||||
monkeypatch.undo()
|
||||
_, doc = _cut(me, key)
|
||||
_fake(monkeypatch, [row])
|
||||
with store.at(me):
|
||||
cut = skc.preview(doc, skc.PRICE)
|
||||
assert cut["후"]["계"] == fresh["후"]["계"] and cut["끊은기초"] == ["sub3임시 굴착기"]
|
||||
_save(me, key, cut["문서"])
|
||||
assert _sum(me, _doc(me, key)) == fresh["후"]["계"]
|
||||
|
||||
|
||||
def test_edit_cut_block_changes_amount_and_saves(made):
|
||||
"""③ 끊은 기초 줄 고침 — 미리 셈 = 금액 바뀜 · 저장 뒤 서버 셈 같음 · 틀린 고침 400 · M01 안 바뀜."""
|
||||
me, key = made
|
||||
price, doc = _cut(me, key)
|
||||
row_before = copy.deepcopy(_live().logic(BASIC))
|
||||
with store.at(me):
|
||||
got = blk.preview(doc, 0, DOUBLE)
|
||||
read = blk.read(doc, 0)
|
||||
assert read["ok"] and got["되나"], got
|
||||
assert got["금액전"]["계"] == price and got["금액후"]["계"] > price
|
||||
assert got["수식"]["합계"]["계"] > got["전"]["계"] # 기초 1 단위 시간당 값
|
||||
item = {**doc["더한줄"][0], blk.EDIT: DOUBLE}
|
||||
_save(me, key, {**doc, "더한줄": [item]})
|
||||
saved = _doc(me, key)
|
||||
assert saved["더한줄"][0][blk.EDIT][0]["까닭"] == "sub3임시 시험"
|
||||
assert _sum(me, saved) == got["금액후"]["계"] # 서버 셈 = 미리 셈
|
||||
assert _live().logic(BASIC) == row_before
|
||||
with store.at(me):
|
||||
eq = full.attach(
|
||||
{"줄": []}, saved, skc.over(saved, skc.whole_()), {}, None, _calc(me, saved)
|
||||
)
|
||||
block = next(r for r in eq["소계"]["줄"] if r.get("블록") == 0)
|
||||
assert block["나무"]["합계"]["계"] == got["수식"]["합계"]["계"] # 접힘 블록 = 고친 수식
|
||||
bad = [{"할일": "식", "자리": "호표:0", "식": "없는값 / 작업량"}]
|
||||
with store.at(me):
|
||||
assert not blk.preview(saved, 0, bad)["되나"]
|
||||
with pytest.raises(store.StoreError):
|
||||
_save(me, key, {**saved, "더한줄": [{**saved["더한줄"][0], blk.EDIT: bad}]})
|
||||
assert _sum(me, _doc(me, key)) == got["금액후"]["계"]
|
||||
|
||||
|
||||
def test_relink_drops_edits_and_follows_original(made, monkeypatch):
|
||||
"""④ [다시 잇기] — 고친 것 버림 · 원본 따라감(저장 뒤 표지 없음) · 금액 = 새로 찍은 SK."""
|
||||
me, key = made
|
||||
was = _sum(me, _doc(me, key))
|
||||
_, doc = _cut(me, key)
|
||||
item = {**doc["더한줄"][0], blk.EDIT: DOUBLE}
|
||||
_save(me, key, {**doc, "더한줄": [item]})
|
||||
edited = _doc(me, key)
|
||||
assert _sum(me, edited) > was
|
||||
_fake(monkeypatch, [_changed(_live().logic(BASIC))]) # 원본 바뀜
|
||||
fresh = _sum(me, _doc(me, _sk(me, 바탕={"로직": FORM}, 더한줄=[copy.deepcopy(ADD)])))
|
||||
assert fresh > was
|
||||
with store.at(me):
|
||||
got = blk.change(edited, 0, "relink")
|
||||
one = got["문서"]["더한줄"][0]
|
||||
assert "끊음" not in one and blk.EDIT not in one and one[blk.REJOIN] is True
|
||||
assert got["전"]["계"] > was and got["후"]["계"] == fresh # 고침 버림 + 원본 따라감
|
||||
_save(me, key, got["문서"])
|
||||
saved = _doc(me, key)
|
||||
assert blk.REJOIN not in saved["더한줄"][0] and "끊음" not in saved["더한줄"][0]
|
||||
assert _sum(me, saved) == fresh
|
||||
|
||||
|
||||
def test_shape_checks(made):
|
||||
"""⑥ 연결 기초에 고침 · 이미 끊음 · 차례 밖 · 연결 기초 다시 잇기 · 끊은 기초 줄 모양."""
|
||||
me, key = made
|
||||
doc = _doc(me, key)
|
||||
with store.at(me):
|
||||
with pytest.raises(sd.DocError, match="연결을 끊은 기초만"):
|
||||
sd.clean({**doc, "더한줄": [{**ADD, blk.EDIT: DOUBLE}]})
|
||||
with pytest.raises(sd.DocError, match="없음"):
|
||||
blk.unlink(doc, 3)
|
||||
with pytest.raises(sd.DocError, match="연결된 기초"):
|
||||
blk.relink(doc, 0)
|
||||
with pytest.raises(sd.DocError, match="연결된 기초"):
|
||||
blk.read(doc, 0)
|
||||
cut = blk.unlink(doc, 0)
|
||||
with pytest.raises(sd.DocError, match="이미 연결을 끊은"):
|
||||
blk.unlink(cut, 0)
|
||||
broken = {**cut["더한줄"][0], "끊음": {"로직": [{"키": "GC999999"}]}}
|
||||
with pytest.raises(sd.DocError, match="줄 없음"):
|
||||
sd.clean({**cut, "더한줄": [broken]}, None, skc.whole_())
|
||||
Reference in New Issue
Block a user