Files
Aislo/resources/tester/test_263_2_haul_lib_copy.py
T
eomsangdonandClaude Opus 5.5 2c8c715cc2 feat(B09): 263-2 사전조합 · 구조물 조합 운반 = 담은 로직 입력 + 거리 값 사본
- 모달 = 담은 로직 이름별 입력(library-inputs) · 거리 칸 거리에서 · 손 값(own) 이김
- 사본 폴더 = 종류@층@주인@키~값해시8 · 같은 값 = 같은 사본 · 다른 거리 = 따로 · 옛 이름 읽힘
- 셈 때 서버가 거리로 사본 다시 고름(resolve_hauls · fix_keys) · [저장] = 바뀐 연결 저장 값에도 · prune
- 연결 {tab dg, key, lib, given, own} 저장 꼴 · 원본 읽기 전 모양 검사

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JywHxQuWPk6UYXTebyrBoU
2026-10-11 16:50:28 +09:00

141 lines
6.5 KiB
Python

"""263-2 운반 값 사본 — 사전조합 · 구조물 조합 담은 로직 거리 칸 = 거리이정표 거리 ·
같은 값 = 사본 하나 · 다른 거리 = 사본 둘 · 거리 바뀐 뒤 셈 = 새 사본 · 옛 사본 prune ·
옛 이름(해시 없음) 폴더 읽힘 · 손 값(own) 이김."""
import shutil
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from B08_Quantity.B08_Quantity_Haul_Cycle import cycle_time # noqa: E402
from B09_Estimation import B09_Estimation_Bill_Library as library # noqa: E402
from B09_Estimation.B09_Estimation_Labor_Source import daega_inputs # noqa: E402
from B09_Estimation.B09_Estimation_Store import _clean_ref # noqa: E402
from M02_MasterTemplete import M02_Labor_Ref as refs # noqa: E402
KEY = "SC-999263"
DOC = {
"종류": "사전조합",
"키": KEY,
"이름": "시험 덤프운반 조합",
"단위": "㎥",
"담은로직": [
{"로직": "GF000284", "입력값": {"재료": "토사", "지역": "전국평균",
"보정작업": "해당 없음"}, "수량": {"손": 1}},
{"로직": "GF000134", "입력값": {"qt": 15, "f": 1, "E": 0.9, "지역": "전국평균"},
"수량": {"손": 1}},
],
} # fmt: skip
NEAR = {"L1": 10, "L2": 2}
FAR = {"L1": 30, "L2": 2}
LID = f"{refs.ref_id({'층': 'system', '주인': None, '키': KEY})}#0"
LID2 = LID[:-1] + "1"
@pytest.fixture(autouse=True)
def fake_precombo(monkeypatch):
real = refs.read_ref
monkeypatch.setattr(refs, "read_ref", lambda ref: DOC if ref.get("키") == KEY else real(ref))
def _import(root, dist, given=None, own=None):
haul = {"given": given, "own": own, "dist": dist}
return library.import_copy(root, "precombo", "system", None, KEY, None, haul)["폴더"]
def _given(root, folder):
files = library._read_copy(library.library_dir(root) / folder)
manifest = library.read_json(library.library_dir(root) / folder / library.MANIFEST_NAME)
return manifest.get("값") or {}, files
def test_거리_칸_채움_같은_값_사본_하나_다른_거리_둘(tmp_path):
a = _import(tmp_path, NEAR)
b = _import(tmp_path, NEAR)
c = _import(tmp_path, FAR)
assert a == b and a != c and "~" in a
values, _ = _given(tmp_path, a)
assert values[LID] == {"운반거리": 12} # L1 + L2
assert values[LID2] == {"Cm": cycle_time(NEAR)["cm"]}
# 사본 안 로직 줄 입력값 = 덮은 값 · 원값 = 덮기 전(없던 칸)
labor = library.read_json(library.library_dir(tmp_path) / c / library.LABOR_FILE)
doc = labor["참조사본"][LID.split("#")[0]]
assert (
doc["담은로직"][0]["입력값"]["운반거리"] == 32
and doc["담은로직"][0]["입력값"]["재료"] == "토사"
)
# 대가 블록 둘(값 다름 = 블록 다름)
libs = daega_inputs(tmp_path)["libs"]
assert set(libs) == {a, c} and libs[a] != libs[c]
def test_손_값_이김(tmp_path):
own = [f"{LID}|운반거리"]
folder = _import(tmp_path, NEAR, {LID: {"운반거리": 5, "재료": "암절취"}}, own)
values, _ = _given(tmp_path, folder)
assert values[LID] == {"운반거리": 5, "재료": "암절취"}
lines = library.library_inputs(tmp_path, "precombo", "system", None, KEY, folder)
first = next(x for x in lines if x["id"] == LID)
assert first["로직"] == "GF000284" and first["값"]["재료"] == "토사" # 덮기 전 값
assert [i["이름"] for i in first["입력"]] == ["재료", "운반거리", "지역", "보정작업"]
def test_거리_바뀐_뒤_셈_새_사본_옛_사본_prune(tmp_path):
old = _import(tmp_path, NEAR)
ref = {"tab": "dg", "key": "DG:x", "lib": old, "given": {}, "own": []}
user = {"haul_refs": {"haul:r-u1": ref}, "haul_dist": {"haul:r-u1": FAR}}
calc = library.resolve_hauls(tmp_path, user)
new = calc["haul_refs"]["haul:r-u1"]["lib"]
assert new != old and new == _import(tmp_path, FAR)
libs = daega_inputs(tmp_path)["libs"]
library.fix_keys(calc, libs)
assert calc["haul_refs"]["haul:r-u1"]["key"] == libs[new]
assert library.prune(tmp_path, calc) == [old]
# 같은 거리 다시 = 그대로
assert library.resolve_hauls(tmp_path, user)["haul_refs"]["haul:r-u1"]["lib"] == new
# 설계내역서 덮개 줄도 같이
bill = {"bill": {"rows": [{"key": "haul:r-u1", "ref": ref}]}, "haul_dist": {"haul:r-u1": NEAR}}
assert library.resolve_hauls(tmp_path, bill)["bill"]["rows"][0]["ref"]["lib"] == old
def test_옛_이름_폴더_읽힘(tmp_path):
hashed = _import(tmp_path, NEAR)
plain = library.import_copy(tmp_path, "precombo", "system", None, KEY)["폴더"]
assert "~" not in plain and library.NAME.match(plain)
ref = {"tab": "dg", "key": "DG:x", "lib": plain}
assert library.resolve(tmp_path, ref, NEAR) == hashed # 옛 사본에서 거리 값 사본
shutil.rmtree(library.library_dir(tmp_path) / hashed)
assert library.resolve(tmp_path, ref, NEAR) == hashed # 없으면 옛 사본에서 다시 만듦
assert library.resolve(tmp_path, ref, None) == plain # 거리 없음 = 그대로
assert {f.name for f, _m in library.copies(tmp_path)} == {plain, hashed}
def test_연결_손_값_저장_꼴():
ref = {"tab": "dg", "key": "DG:x", "lib": "precombo@system@-@SC-1~abcdef12",
"given": {LID: {"운반거리": 5, "x": [1]}}, "own": [f"{LID}|운반거리", 3]} # fmt: skip
got = _clean_ref(ref)
assert got["given"] == {LID: {"운반거리": 5}} and got["own"] == [f"{LID}|운반거리"]
assert "given" not in _clean_ref({"tab": "dg", "key": "DG:x"})
def test_있는_사본에서_다시_적용(tmp_path, monkeypatch):
near = _import(tmp_path, NEAR)
monkeypatch.setattr(refs, "read_ref", lambda ref: None) # 원본 지워짐 = 굳힌 사본에서
haul = {"given": {}, "own": [], "dist": FAR, "lib": near}
got = library.import_copy(tmp_path, "precombo", "system", None, KEY, None, haul)
values, _ = _given(tmp_path, got["폴더"])
assert got["폴더"] != near and values[LID] == {"운반거리": 32}
def test_모달_조합_입력():
modal = (ROOT / "B09_Estimation/B09_Estimation_UI_Haul_Modal.ts").read_text("utf-8")
for want in ("fetchLibInputs(p)", "libRows()", "st.libOwn.has(id)", "parseLib(",
"importLib(o, { kind, layer, owner, key, lib, haul })"): # fmt: skip
assert want in modal, want
link = (ROOT / "B09_Estimation/B09_Estimation_UI_Tabs_Bill_Link.ts").read_text("utf-8")
assert '"library-inputs"' in link and "...lib.haul" in link