# ruff: noqa: F811 — 임시 층 fixture(world)를 test_m02_labor_ref 에서 받아 씀 """792-2 시트 다시 셈 서버 다듬기 — 자재 색인 · 찾기 답을 M01 색인에 한 번만. - 셈마다 새 `_Over` 덮개를 지어도 자재 색인(`_market` · `_by_class`) · 찾기 답(`_found`)은 속 M01 색인에 붙음 — 두 번째 셈은 다시 안 지음 - M01 파일 자국이 바뀌면 새 색인 = 새로 지음(지문 열쇠 = `M01_MasterData_Store_Cache.loaded`) - 층 섞임 없음 — 기억은 M01 자재품목 키만 · 개인 자재(PM)는 그때 층에서만 찾음 - 셈 답 같음 — 기억한 찾기 = 날 찾기 · SK 금액 견본(합판거푸집 51,419 · 공구손료 2 % 51,802) """ from __future__ import annotations import json import os from decimal import Decimal from M01_MasterData import M01_MasterData_Store as m01 from M01_MasterData import M01_MasterData_Store_Cache as cache from M02_MasterTemplete import M02_Labor_Doc as labor from M02_MasterTemplete import M02_MasterTemplete_Store as store from M02_MasterTemplete import M02_Material_Own as own from M02_MasterTemplete import M02_Sangeun_Calc as calc from resources.tester.test_m02_labor_ref import world # noqa: F401 — 같은 임시 층 mm = m01.cm.mf.mp.mm mp = m01.cm.mf.mp F211 = { "자재지역": "포항", "유형": "보통", "사용횟수": "6회", "높이감률": 0, "지붕슬래브": "아님", "폼타이": "아님", "폼타이규격": "12.7㎜", "측압": "3t/㎡", "구멍땜": 0, } def _sk(**more): doc = {"키": "SK-000001", "이름": "속도", "단위": "식", "바탕": {"로직": "GC000211"}} return {**doc, "입력값": F211, **more} def test_색인은_M01_색인에_한_번_두번째_셈은_안_지음(monkeypatch): first = calc.calc_doc(_sk()) whole = m01.loaded()[1] held = {n: vars(whole)[n] for n in ("_market", "_found")} fresh = mp._search found = [] monkeypatch.setattr(mp, "_search", lambda *a: found.append(a) or fresh(*a)) again = calc.calc_doc(_sk()) assert again["기준"] == first["기준"] and first["기준"]["계"] == 51419 assert all(vars(whole)[n] is v for n, v in held.items()) assert found == [] # 같은 조건 찾기 = 기억한 답(자재품목 3만 줄을 안 훑음) over = calc._Over(whole, "SK-000001", {}) assert over._market is whole._market and "_market" not in vars(over) over.mine = 1 # 그 밖 칸은 덮개에만 assert "mine" not in vars(whole) def test_M01_파일이_바뀌면_새_색인_새로_지음(tmp_path): def write(rows): path = tmp_path / "자재품목.json" path.write_text(json.dumps({"그룹": "재료", "줄": rows}, ensure_ascii=False), "utf-8") return path one = {"키": "MT000001", "이름": "합판", "규격": "12mm", "단위": "장", "물가자료": 100} two = {**one, "키": "MT000002", "이름": "각재"} try: write([one]) old = cache.loaded(tmp_path)[1] assert [k for *_, k in mm._market_index(old)] == ["MT000001"] path = write([one, two]) os.utime(path, ns=(1, 1)) # 자국(시각 · 크기)이 꼭 바뀌게 new = cache.loaded(tmp_path)[1] assert new is not old and not hasattr(new, "_market") assert [k for *_, k in mm._market_index(new)] == ["MT000001", "MT000002"] assert cache.loaded(tmp_path)[1] is new # 안 바뀌면 그대로 finally: cache.forget() # 다음 시험은 M01 폴더를 다시 읽음 def test_기억한_찾기_답은_날_찾기와_같고_사본을_줌(): whole = m01.loaded()[1] conds = [ ({"검색어": "합판 12mm", "구분": "목재"}, {}, "㎡"), ({"검색어": "철선"}, {mm.REGION: "포항"}, "kg"), ({"검색어": "레미콘"}, {mm.REGION: "서울"}, None), ] for cond, env, unit in conds: got = mp.search(whole, cond, env, unit) assert got == mp._search(whole, cond, env, unit) got.append("MT999999") assert "MT999999" not in mp.search(whole, cond, env, unit) assert mp.search(whole, conds[1][0], {mm.REGION: "서울"}, "kg") == mp._search( whole, conds[1][0], {mm.REGION: "서울"}, "kg" ) def test_층_섞임_없음_개인_자재는_그때_층에서만(world): calc.calc_doc(_sk()) # M01 색인에 기억이 생긴 뒤 whole = m01.loaded()[1] assert all(k.startswith(mm.MARKET) for *_, k in whole._market) assert all(k.startswith(mm.MARKET) for keys in whole._found.values() for k in keys) with store.at(world["personal"]): code = own.add(world["personal"], {"이름": "내 자재", "단위": "개", "값": 1234})["키"] mine = labor.material_price(whole, code, "개") other = world["personal"].parent.parent / "43" / world["personal"].name other.mkdir(parents=True) with store.at(other): theirs = labor.material_price(whole, code, "개") assert Decimal(str(mine["기준단가"])) == 1234 assert theirs["기준단가"] is None assert code not in whole.index.get(code[:2], {}) def test_상수_덮개_셈_답_전후_같음(): got = calc.calc_doc(_sk(상수덮개={"pct:공구손료 및 경장비#0": {"0": 2}})) assert got["기준"]["계"] == 51802 assert got["원래"]["계"] == 51419 assert got["시트"]["자리"]["pct:공구손료 및 경장비#0"]["덮개"] == ["상수"]