# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀 """827-3 지킴 — 불러오기 재료 고름(요구 811-2 · 812-1 · 임시 storage). ① 파일 고름 → 그 파일 같은 종 줄 전부 이음(블록 둘) · 고른 줄 = 우리 값(엑셀 값 기억 없음) · 문서 머리 `가져온.재료` ② 다른 파일 영향 0 · 별칭 · 마스터 안 바뀜 · 고름 풀기 · [끝내기] 뒤 같은 파일 다시 올림 = 고름 그대로 ③ 이미 만든 SK = 물음 예(`apply_made`)일 때만 · 사람이 따로 바꾼 줄 그대로 · 풀면 가져온 그대로로 ④ 별도계상 줄 = 품목 「별도계상 · 품목: 이름 규격」 + 단가 0 그대로(줄 이음 없음) """ from __future__ import annotations import copy as cp import json from functools import lru_cache from pathlib import Path import pytest from M02_MasterTemplete import M02_Doc_Import as dim from M02_MasterTemplete import M02_Doc_Sk_Path as skpath from M02_MasterTemplete import M02_Elem_Alias as ea from M02_MasterTemplete import M02_Hopyo_Forget as forget from M02_MasterTemplete import M02_MasterTemplete_Store as store from M02_MasterTemplete import M02_San_MatPick as mp from M02_MasterTemplete import M02_Sangeun_FromHopyo as fh from M02_MasterTemplete import M02_Sangeun_Imported as imp from resources.tester import test_810_1_stc as stc from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층 WIRE = "결속선(철선)|#20 , 0.9M/M|KG|" # 봉화 산근 98 · 99 — 후보 여럿 PIPE_BLOCK = 71 # 동부청영월 파형강관(별도계상) Φ800 머리 @lru_cache(maxsize=2) def _raw(tag: str) -> bytes: p = stc.FILES[tag] if not p.exists(): pytest.skip(f"STC 없음 {tag}") return p.read_bytes() def _upload(folder: Path, tag: str) -> str: return fh.upload_native(folder, stc.FILES[tag].name, _raw(tag), {"이름": "sub3임시"})["키"] def _lines(doc: dict, kind: str) -> list[dict]: return [x for x in doc[imp.KEY]["로직"]["호표"] if mp.kind_of(x.get("자원") or {}) == kind] def _var(conv: dict, sym: str) -> dict: return next(v for v in conv["변수"] if dim.dc.md.var_id(v) == sym) def _entry(conv: dict, kind: str) -> dict: return next(e for e in conv["가져온"]["재료"] if e["종"] == kind) def test_pick_whole_file(world) -> None: me = world["personal"] me.mkdir(parents=True, exist_ok=True) alias = json.dumps(ea.book()["별칭"], ensure_ascii=False, sort_keys=True, default=str) with store.at(me): hp = _upload(me, "봉화") fp, name = mp.fingerprint(me, hp) groups = {g["종"]: g for g in mp.census(me, hp)} wire = groups[WIRE] assert wire["판정"] == "후보 여럿" and wire["블록"] == [98, 99] and len(wire["후보"]) > 1 assert all(g["판정"] == "이어짐" or g["후보"] is not None for g in groups.values()) pick = wire["후보"][1] assert mp.write(me, fp, name, {WIRE: pick})[WIRE]["키"] == pick["키"] assert mp.tally(me, fp, WIRE) == {"블록": 2, "줄": 2} with mp.using(mp.read(me, fp)["고름"]): made = [fh.make(me, hp, no)["이름"] for no in (98, 99)] for key in made: doc = store.read("sangeun", key)["문서"] assert doc[imp.KEY]["원본"]["지문"] == fp lines = _lines(doc, WIRE) assert lines and all(x["이음"] == pick["키"] for x in lines) assert all(x["자원"]["재료찾기"]["고름"]["키"] == pick["키"] for x in lines) assert all( x["자원"]["재료찾기"]["판정"] == "후보 여럿" for x in lines ) # 엔진 판정 그대로 conv = dim.derive(doc, None, imp._whole()) e = _entry(conv, WIRE) assert e["고름"]["키"] == pick["키"] and e["처음"]["갈래"] == "숫자" assert _var(conv, e["기호"])["연결"] == {"갈래": "요소", "키": pick["키"]} # 우리 값 assert sorted(mp.made(me, fp)) == sorted(made) assert mp.uses(fp, WIRE, (made[0],)) == [made[1]] # 다른 파일 = 영향 0 other = _upload(me, "울진대흥") fp2, _ = mp.fingerprint(me, other) assert fp2 != fp and mp.read(me, fp2)["고름"] == {} # 고름 풀기 assert mp.write(me, fp, name, {WIRE: None}) == {} assert mp.read(me, fp)["고름"] == {} # [끝내기] 뒤 같은 파일 다시 올림 = 고름 그대로 mp.write(me, fp, name, {WIRE: pick}) forget.finish(me, hp) again = _upload(me, "봉화") assert again != hp and mp.fingerprint(me, again)[0] == fp assert mp.read(me, fp)["고름"][WIRE]["키"] == pick["키"] # 별칭 · 마스터 안 바뀜 · 고름 자리 = 개인 층 실무자료/재료고름 한 파일씩 assert json.dumps(ea.book()["별칭"], ensure_ascii=False, sort_keys=True, default=str) == alias assert sorted(p.name for p in (me / "실무자료" / mp.DIRNAME).iterdir()) == [f"{fp}.json"] assert not list(world["system"].rglob(f"{fp}*")) def test_made_only_on_yes_and_keeps_user_lines(world) -> None: me = world["personal"] me.mkdir(parents=True, exist_ok=True) with store.at(me): hp = _upload(me, "봉화") fp, name = mp.fingerprint(me, hp) sk98, sk99 = (fh.make(me, hp, no)["이름"] for no in (98, 99)) # 고름 전에 만듦 conv = skpath.current(store.read("sangeun", sk98)["문서"])["문서"] e = _entry(conv, WIRE) before = _var(conv, e["기호"])["연결"] assert before["갈래"] == "숫자" and "고름" not in e pick = e["후보"][0] mp.write(me, fp, name, {WIRE: pick}) # 판 [저장](물음 아니오) = SK 그대로 assert _var(skpath.current(store.read("sangeun", sk98)["문서"])["문서"], e["기호"])["연결"] == before # fmt: skip # 99 = 사람이 그 줄을 따로 고름(줄 쌓기 이름 단추) got = store.read("sangeun", sk99) doc = cp.deepcopy(skpath.current(got["문서"])["문서"]) other = e["후보"][2]["키"] _var(doc, _entry(doc, WIRE)["기호"])["연결"] = {"갈래": "요소", "키": other} skpath.save(sk99, {"문서": doc, "판": got["판"]}) money = skpath.read(sk98)["셈"] out = mp.apply_made(fp, mp.read(me, fp)["고름"], {WIRE}) # 물음 예 assert out == {"고침": [sk98], "그대로": [sk99]} now = skpath.read(sk98) e98 = _entry(now["문서"], WIRE) assert _var(now["문서"], e98["기호"])["연결"] == {"갈래": "요소", "키": pick["키"]} assert e98["고름"]["키"] == pick["키"] and now["셈"] != money # 우리 값으로 다시 셈 assert ( _var(skpath.read(sk99)["문서"], e["기호"])["연결"]["키"] == other ) # 따로 고친 줄 그대로 # 풂 = 가져온 그대로(엑셀 값) mp.write(me, fp, name, {WIRE: None}) assert mp.apply_made(fp, {}, {WIRE})["고침"] == [sk98] back = skpath.read(sk98) assert _num(_var(back["문서"], e98["기호"])["연결"]) == _num(before) assert "고름" not in _entry(back["문서"], WIRE) and back["셈"] == money def _num(link: dict) -> tuple: return link["갈래"], float(link["값"]) def test_apart_item_zero(world) -> None: me = world["personal"] me.mkdir(parents=True, exist_ok=True) with store.at(me): hp = _upload(me, "동부청영월") out = fh.emit(me, hp, PIPE_BLOCK) line = next(x for x in out["로직"]["호표"] if "파형강관" in str((x.get("자원") or {}).get("이름"))) # fmt: skip kind = mp.kind_of(line["자원"]) found = line["자원"]["재료찾기"] assert found["판정"] == "규격 없음 — 고르기" and line["이음"] is None gov = next(c for c in found["후보"] if "관급" in c["이름"]) fp, name = mp.fingerprint(me, hp) plain = fh.make(me, hp, PIPE_BLOCK) mp.write(me, fp, name, {kind: gov}) with mp.using(mp.read(me, fp)["고름"]): got = fh.make(me, hp, PIPE_BLOCK) assert got["이름"] != plain["이름"] and got["검산"] == plain["검산"] # 금액 그대로(단가 0) doc = store.read("sangeun", got["이름"])["문서"] mine = _lines(doc, kind)[0] assert mine["이음"] is None and mine["자원"]["재료찾기"]["고름"]["키"] == gov["키"] conv = dim.derive(doc, None, imp._whole()) e = _entry(conv, kind) var = _var(conv, e["기호"]) assert e["별도계상"] and var["연결"]["갈래"] == "숫자" assert f"별도계상 · 품목: {gov['이름']} {gov['규격']} · 셈은 프로젝트에서" in var["설명"] assert mp.item_key(mine["자원"]) == gov["키"] assert skpath.read(got["이름"])["셈"] == skpath.read(plain["이름"])["셈"] # 이미 만든(고름 전) SK 에 물음 예 = 품목 설명만 · 단가 0 그대로 money = skpath.read(plain["이름"])["셈"] assert plain["이름"] in mp.apply_made(fp, {kind: gov}, {kind})["고침"] now = skpath.read(plain["이름"]) assert _entry(now["문서"], kind)["고름"]["키"] == gov["키"] and now["셈"] == money assert "품목: 파형강관(관급)" in _var(now["문서"], e["기호"])["설명"] # 이음 없는 줄 목록(가져온 식 머리 [이음 고르기]) = 종 열쇠(같은 파일 물음) assert any( u.get("종") == kind for u in imp.unlinked(store.read("sangeun", plain["이름"])["문서"]) )