# 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 = "GF000089" # 토사깍기(기계) · 굴착기 시간당 — 호표 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 "GF000088" 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_())