Merge remote-tracking branch 'origin/sub_laptop_6' into sub_laptop_5
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
"""프로젝트 집계 항목 복사본 완전체 (PLAN 25-2b · 25-2e · 임시 저장소 · 임시 마스터 사본).
|
||||
"""프로젝트 집계 항목 복사본 완전체 (PLAN 25-2b · 25-2e · 26-2b · 임시 저장소 · 임시 마스터 사본).
|
||||
|
||||
복사본은 구조물마다(`templates/structures/{구조물 id}/` · 관은 `pipe@측점`).
|
||||
|
||||
- 지정 → [저장] → 폴더에 새 파일(입력연결 · 입력값 · 고른자재 · 단가) · manifest 가져온날 · 원본판
|
||||
- 단가 묶음이 닫혀 있음 — 조합 37개 · 로직 170개를 마스터와 복사본으로 돌려 같은 값
|
||||
@@ -32,7 +34,8 @@ from M02_MasterTemplete import M02_Template_Layers as layers
|
||||
REAL = config_system.PROJECT_ROOT / "resources/master_template"
|
||||
MASTER = config_system.PROJECT_ROOT / "resources/master_data"
|
||||
PIPE = {"layer": "system", "owner": None, "key": "SS000011", "name": "관공 관매설"}
|
||||
FOLDER = "system_none_SS000011"
|
||||
FOLDER = "pipe@40.0" # 관 지점 복사본 폴더 = 구조물 id(26-2b)
|
||||
PIPE_PATH = ["관공", "(관종·관경마다)", "관매설"]
|
||||
LABOR_PRICE = "LB000002" # 보통인부 — 되메우기 · 파형강관 부설 호표가 씀
|
||||
|
||||
|
||||
@@ -82,7 +85,7 @@ def _read(path: Path) -> Any:
|
||||
|
||||
def _auto_values(root: Path) -> dict[str, Any]:
|
||||
"""담은 로직마다 자동값을 확인한 값으로 — 사용자가 다 채운 것과 같게."""
|
||||
labor = _read(root / "templates/items" / FOLDER / "일위대가.json")
|
||||
labor = _read(root / "templates/structures" / FOLDER / "일위대가.json")
|
||||
_, whole = m01.loaded()
|
||||
out: dict[str, Any] = {}
|
||||
for row in labor["로직"]:
|
||||
@@ -104,7 +107,7 @@ def _fill_values(root: Path) -> dict[str, Any]:
|
||||
def test_지정하면_새_파일까지_복사(world):
|
||||
root = world["root"]
|
||||
assert _save(root, [_pipe()])["만듦"] == [FOLDER]
|
||||
folder = root / "templates/items" / FOLDER
|
||||
folder = root / "templates/structures" / FOLDER
|
||||
assert _read(folder / "입력연결.json") == {"판": None, "줄": []} # 층 연결이 아직 없음
|
||||
assert _read(folder / "입력값.json") == {} and _read(folder / "고른자재.json") == {}
|
||||
price = _read(folder / "단가.json")
|
||||
@@ -118,7 +121,7 @@ def test_지정하면_새_파일까지_복사(world):
|
||||
{
|
||||
"폴더": FOLDER,
|
||||
"이름": "관공 관매설",
|
||||
"원본": PIPE,
|
||||
"원본": {**PIPE, "경로": PIPE_PATH},
|
||||
"원본판": manifest["원본판"],
|
||||
"가져온날": manifest["가져온날"],
|
||||
"마스터바뀜": False,
|
||||
@@ -221,7 +224,7 @@ def test_마스터_단가를_바꿔도_계산_그대로_새로_가져오면_바
|
||||
def test_새로_가져오면_없는_키는_버림(world):
|
||||
root = world["root"]
|
||||
_save(root, [_pipe()])
|
||||
folder = root / "templates/items" / FOLDER
|
||||
folder = root / "templates/structures" / FOLDER
|
||||
(folder / "입력값.json").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
@@ -267,31 +270,37 @@ def test_쓰기_뒤_다시_읽기_같음_판_다르면_409(world):
|
||||
copies.read_file(root, "../../etc", "입력값")
|
||||
|
||||
|
||||
def test_고친_복사본은_구조물에서_빠져도_안_지움(world):
|
||||
def test_고친_복사본은_구조물에서_빠지면_지난에_남김(world):
|
||||
root = world["root"]
|
||||
_save(root, [_pipe()])
|
||||
assert _save(root, [_pipe(None)])["지움"] == [FOLDER] # 안 고쳤으면 지움(지금 규칙)
|
||||
assert _save(root, [_pipe(None)])["지움"] == [FOLDER] # 안 고쳤으면 지움
|
||||
assert not (root / "templates/structures/_지난").exists()
|
||||
_save(root, [_pipe()])
|
||||
current = copies.read_file(root, FOLDER, "입력값")
|
||||
copies.write_file(root, FOLDER, "입력값", current["판"], {"GF000176": {"관경": {"값": 600}}})
|
||||
assert _save(root, [_pipe(None)])["지움"] == []
|
||||
assert copies.list_items(root)[0]["구조물"] == [] and copies.list_items(root)[0]["고침"]
|
||||
assert _save(root, [_pipe(None)])["지움"] == [FOLDER]
|
||||
assert copies.list_items(root) == []
|
||||
past = list((root / "templates/structures/_지난").iterdir())
|
||||
assert len(past) == 1 and past[0].name.startswith("pipe@40.0_")
|
||||
assert _read(past[0] / "입력값.json") == {"GF000176": {"관경": {"값": 600}}}
|
||||
|
||||
|
||||
def test_미리_가져오기(world):
|
||||
root = world["root"]
|
||||
_save(root, [])
|
||||
made = copies.prefetch(root, PIPE)
|
||||
made = copies.prefetch(root, FOLDER, PIPE)
|
||||
assert made["폴더"] == FOLDER and made["만듦"] is True
|
||||
assert copies.prefetch(root, PIPE)["만듦"] is False # 있으면 그대로
|
||||
assert copies.list_items(root)[0]["구조물"] == []
|
||||
assert _save(root, [])["지움"] == [FOLDER] # 안 고쳤으면 [저장] 때 지움
|
||||
assert copies.prefetch(root, FOLDER, PIPE)["만듦"] is False # 같은 항목이면 그대로
|
||||
assert copies.list_items(root)[0]["구조물"] == [FOLDER]
|
||||
assert _save(root, [])["지움"] == [FOLDER] # [저장] 뒤에도 안 쓰면 지움
|
||||
with pytest.raises(ValueError):
|
||||
copies.prefetch(root, "../x", PIPE)
|
||||
|
||||
|
||||
def test_옛_복사본은_읽을_때_채움(world):
|
||||
root = world["root"]
|
||||
_save(root, [_pipe()])
|
||||
folder = root / "templates/items" / FOLDER
|
||||
folder = root / "templates/structures" / FOLDER
|
||||
for name in ("입력연결.json", "입력값.json", "고른자재.json", "단가.json"):
|
||||
(folder / name).unlink()
|
||||
manifest = _read(folder / "manifest.json")
|
||||
@@ -331,12 +340,185 @@ def test_길_권한_남의_프로젝트는_403(world, monkeypatch):
|
||||
assert stale.status_code == 409 and stale.json()["detail"]["판"] == put.json()["판"]
|
||||
assert client.get(f"{base}/{FOLDER}/모름").status_code == 422
|
||||
assert client.post(f"{base}/{FOLDER}/calc").json()["멈춤"]
|
||||
assert client.post(base, json={"summary_item": {"layer": "x"}}).status_code == 400
|
||||
made = client.post(base, json={"layer": "system", "owner": None, "key": "SS000022"}).json()
|
||||
assert made["폴더"] == "system_none_SS000022" and made["만듦"] is True
|
||||
wall = {"structure": "st9", "layer": "system", "owner": None}
|
||||
assert client.post(base, json={**wall, "summary_item": {"layer": "x"}}).status_code == 400
|
||||
assert client.post(base, json={"layer": "system", "key": "SS000022"}).status_code == 400
|
||||
made = client.post(base, json={**wall, "key": "SS000022"}).json()
|
||||
assert made["폴더"] == "st9" and made["만듦"] is True
|
||||
names = {i["폴더"]: i["이름"] for i in client.get(base).json()["항목"]}
|
||||
assert names["system_none_SS000022"] == "돌쌓기 (찰·메마다) H=(높이마다)" # 층 SS 줄 이름
|
||||
assert client.post(base, json={"layer": "system", "key": "SS999999"}).status_code == 404
|
||||
assert names["st9"] == "돌쌓기 (찰·메마다) H=(높이마다)" # 층 SS 줄 이름(경로 이음)
|
||||
assert client.post(base, json={**wall, "key": "SS999999"}).status_code == 404
|
||||
assert client.post(f"{base}/{FOLDER}/reapply").json()["덮임"] == []
|
||||
session["company_id"] = 4
|
||||
assert client.get(base).status_code == 403
|
||||
assert client.post(f"{base}/{FOLDER}/refresh").status_code == 403
|
||||
|
||||
|
||||
# ── 구조물마다 복사본 (26-2b) ─────────────────────────
|
||||
|
||||
|
||||
MS = {"layer": "system", "owner": None, "key": "SS000022", "name": "돌쌓기"}
|
||||
|
||||
|
||||
def _wall(sid: str, summary: dict | None = MS) -> dict[str, Any]:
|
||||
return {
|
||||
"structure_id": sid,
|
||||
"type_id": "masonry_dry",
|
||||
"placement": "interval",
|
||||
"chainage_m": 85,
|
||||
"start_m": 80,
|
||||
"end_m": 90,
|
||||
"options": {"height_m": 2.0, "length_m": 10},
|
||||
"summary_item": summary,
|
||||
}
|
||||
|
||||
|
||||
def _save_all(root: Path, walls: list[dict], pipes: list[dict]) -> dict[str, list[str]]:
|
||||
(root / "B05_Profile/route/structures.json").write_text(
|
||||
json.dumps({"revision": 1, "structures": walls}, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
(root / "B04_PreProcess/drainage/edits/pipe_points.json").write_text(
|
||||
json.dumps({"points": pipes}, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
return snap.sync_snapshots(root)
|
||||
|
||||
|
||||
def _memo(root: Path, folder: str, text: str) -> None:
|
||||
"""면적 시트에 표식 한 칸 — 한쪽만 고쳤는지 보려는 것(계산값 풀이는 건너뜀)."""
|
||||
area = copies.read_file(root, folder, "면적")
|
||||
body = {**area["내용"], "메모": text}
|
||||
copies.write_file(root, folder, "면적", area["판"], body, recalc=lambda doc: doc)
|
||||
|
||||
|
||||
def test_같은_항목_구조물_둘은_따로(world):
|
||||
root = world["root"]
|
||||
second = {**_pipe(), "chainage_m": 60.0}
|
||||
made = _save_all(root, [_wall("a1"), _wall("a2")], [_pipe(), second])["만듦"]
|
||||
assert made == ["a1", "a2", FOLDER, "pipe@60.0"]
|
||||
_memo(root, "a1", "a1 만 고침")
|
||||
assert copies.read_file(root, "a1", "면적")["내용"]["메모"] == "a1 만 고침"
|
||||
assert "메모" not in copies.read_file(root, "a2", "면적")["내용"] # 다른 쪽 그대로
|
||||
_fill_values(root) # pipe@40.0 에만 값
|
||||
assert copies.calc(root, FOLDER)["멈춤"] == [] and copies.calc(root, FOLDER)["계"] > 0
|
||||
assert len(copies.calc(root, "pipe@60.0")["멈춤"]) == 3 # 계산도 각자
|
||||
flags = {i["폴더"]: i["고침"] for i in copies.list_items(root)}
|
||||
assert flags == {"a1": True, "a2": False, FOLDER: True, "pipe@60.0": False}
|
||||
|
||||
|
||||
def test_원본_항목을_지워도_복사본_계산_그대로(world):
|
||||
root, system = world["root"], world["system"]
|
||||
_save(root, [_pipe()])
|
||||
_fill_values(root)
|
||||
before = copies.calc(root, FOLDER)
|
||||
combo = _read(system / layers.COMBO_FILE)
|
||||
combo["줄"] = [r for r in combo["줄"] if r["키"] != PIPE["key"]]
|
||||
(system / layers.COMBO_FILE).write_text(json.dumps(combo, ensure_ascii=False), "utf-8")
|
||||
assert copies.calc(root, FOLDER) == before
|
||||
row = copies.list_items(root)[0]
|
||||
assert row["원본없음"] is True and row["마스터바뀜"] is False
|
||||
assert _save(root, [_pipe()])["만듦"] == [] # 다시 저장해도 복사본 그대로
|
||||
with pytest.raises(LookupError):
|
||||
copies.reapply(root, FOLDER) # 원본이 없으면 재적용 못 함(404)
|
||||
|
||||
|
||||
def test_재적용은_시트_고침을_덮고_알림_입력값은_살림(world):
|
||||
root = world["root"]
|
||||
_save(root, [_pipe()])
|
||||
values = _fill_values(root)
|
||||
_memo(root, FOLDER, "x")
|
||||
assert copies.reapply(root, FOLDER)["덮임"] == ["면적"]
|
||||
assert "메모" not in copies.read_file(root, FOLDER, "면적")["내용"]
|
||||
assert copies.read_file(root, FOLDER, "입력값")["내용"] == values
|
||||
assert copies.reapply(root, FOLDER)["덮임"] == []
|
||||
|
||||
|
||||
def test_개인에_저장하면_개인_층에_항목(world):
|
||||
root = world["root"]
|
||||
_save(root, [_pipe()])
|
||||
rows = [{"로직": "GF000176", "입력": "관경", "자리": "선택"}]
|
||||
current = copies.read_file(root, FOLDER, "입력연결")
|
||||
copies.write_file(root, FOLDER, "입력연결", current["판"], {"판": 3, "줄": rows})
|
||||
made = copies.save_as(root, FOLDER, 3, 12, ["관공", "우리 현장"], "파형강관 매설")
|
||||
assert made["summary_item"] == {
|
||||
"layer": "personal",
|
||||
"owner": "3/12",
|
||||
"key": made["key"],
|
||||
"name": "관공 우리 현장 파형강관 매설",
|
||||
}
|
||||
folder = layers.personal_dir(3, 12)
|
||||
row = next(r for r in _read(folder / layers.COMBO_FILE)["줄"] if r["키"] == made["key"])
|
||||
assert [row["종류"], row["분류1"], row["분류2"]] == ["관공", "우리 현장", "파형강관 매설"]
|
||||
assert row["일위대가"] == "UA000036" and row["단위"] == "m"
|
||||
copy = root / "templates/structures" / FOLDER
|
||||
drawing = _read(folder / "structure" / f"{made['열']}.json")
|
||||
assert drawing["도면"] == _read(copy / "도면.json")["도면"]
|
||||
assert _read(folder / "inputs" / f"{made['열']}.json") == {"판": 1, "줄": rows}
|
||||
assert not list(folder.rglob("단가.json")) # 단가 묶음은 안 가져감
|
||||
# 개인 층 항목을 다른 구조물에 지정하면 그 내용으로 복사본이 섬
|
||||
assert _save_all(root, [_wall("b1", made["summary_item"])], [])["만듦"] == ["b1"]
|
||||
|
||||
|
||||
def test_프로젝트에서_새_항목(world):
|
||||
root = world["root"]
|
||||
_save_all(root, [_wall("c1")], [])
|
||||
made = copies.new_item(root, "c1", 3, 12, ["신규 공사"], "돌붙임", "㎡")
|
||||
assert made["폴더"] == "c1" and made["summary_item"]["layer"] == "personal"
|
||||
origin = _read(root / "templates/structures/c1/manifest.json")["원본"]
|
||||
assert origin["key"] == made["key"] and origin["경로"] == ["신규 공사", "돌붙임"]
|
||||
assert copies.list_items(root)[0]["이름"] == "신규 공사 돌붙임"
|
||||
# 화면이 새 항목을 지정해 [저장] 하면 그대로 남음
|
||||
assert _save_all(root, [_wall("c1", made["summary_item"])], [])["만듦"] == []
|
||||
with pytest.raises(ValueError):
|
||||
copies.new_item(root, "c2", 3, 12, [], "", None) # 경로 · 이름 빈 값
|
||||
|
||||
|
||||
def test_옛_항목_폴더는_쓰는_구조물마다_옮겨_받음(world):
|
||||
root = world["root"]
|
||||
_save_all(root, [_wall("d1"), _wall("d2")], [])
|
||||
base = root / "templates/structures"
|
||||
old = root / "templates/items/system_none_SS000022"
|
||||
old.parent.mkdir(parents=True)
|
||||
shutil.move(str(base / "d1"), str(old))
|
||||
shutil.rmtree(base / "d2")
|
||||
manifest = _read(old / "manifest.json")
|
||||
manifest.update({"구조물": ["d1", "d2"], "고침": True})
|
||||
(old / "manifest.json").write_text(json.dumps(manifest, ensure_ascii=False), "utf-8")
|
||||
(old / "입력값.json").write_text(json.dumps({"GF": {"a": {"값": 1}}}), "utf-8")
|
||||
assert [i["폴더"] for i in copies.list_items(root)] == ["d1", "d2"]
|
||||
assert not (root / "templates/items").exists()
|
||||
for sid in ("d1", "d2"):
|
||||
assert _read(base / sid / "입력값.json") == {"GF": {"a": {"값": 1}}} # 고친 값 유지
|
||||
assert _read(base / sid / "manifest.json")["구조물"] == [sid]
|
||||
assert _save_all(root, [_wall("d1"), _wall("d2")], [])["만듦"] == []
|
||||
|
||||
|
||||
def test_지정을_바꾸면_고친_옛_복사본은_지난에(world):
|
||||
root = world["root"]
|
||||
_save_all(root, [_wall("e1")], [])
|
||||
_memo(root, "e1", "y")
|
||||
rv = {"layer": "system", "owner": None, "key": "SS000001", "name": "돌기슭막이"}
|
||||
result = _save_all(root, [_wall("e1", rv)], [])
|
||||
assert result["만듦"] == ["e1"] and result["지움"] == ["e1"]
|
||||
assert _read(root / "templates/structures/e1/manifest.json")["원본"]["key"] == "SS000001"
|
||||
past = list((root / "templates/structures/_지난").iterdir())
|
||||
assert len(past) == 1 and _read(past[0] / "면적.json")["메모"] == "y"
|
||||
|
||||
|
||||
def test_새_항목_길_회사_없으면_409(world, monkeypatch):
|
||||
root = world["root"]
|
||||
_save_all(root, [_wall("f1")], [])
|
||||
|
||||
async def fake_row(project_id: str) -> dict[str, Any]:
|
||||
return {"company_id": None, "storage_path": str(root)}
|
||||
|
||||
monkeypatch.setattr(layer_routes, "_project_row", fake_row)
|
||||
monkeypatch.setattr(layer_routes, "resolve_stored_project_path", lambda path: path)
|
||||
app = FastAPI()
|
||||
app.include_router(items_router.router)
|
||||
session = {"role": "SYSTEM_ADMIN", "company_id": None, "user_id": 12}
|
||||
app.dependency_overrides[verify_session] = lambda: session
|
||||
client = TestClient(app)
|
||||
body = {"structure": "f1", "경로": ["새"], "이름": "것"}
|
||||
assert client.post("/api/projects/p1/items/new", json=body).status_code == 409
|
||||
save_as = client.post("/api/projects/p1/items/f1/save-as", json={"경로": ["a"], "이름": "b"})
|
||||
assert save_as.status_code == 409
|
||||
|
||||
@@ -82,7 +82,8 @@ def _pipe(summary: dict | None) -> dict[str, Any]:
|
||||
|
||||
|
||||
def _items(root: Path) -> Path:
|
||||
return root / "templates" / "items"
|
||||
"""구조물 복사본 뿌리(26-2b) — 구조물마다 폴더(`structure_id` · 관은 `pipe@측점`)."""
|
||||
return root / "templates" / "structures"
|
||||
|
||||
|
||||
# ── 칸 모양 ──────────────────────────────────────────
|
||||
@@ -126,12 +127,8 @@ def test_옛_파일은_칸_없음_그대로_읽고_씀():
|
||||
def test_지정하면_폴더가_생기고_내용이_원본과_같음(world):
|
||||
root = world["root"]
|
||||
result = _save(root, [_dry(MS), _wet()], [_pipe(PIPE)])
|
||||
assert result == {
|
||||
"만듦": ["system_none_SS000011", "system_none_SS000022"],
|
||||
"지움": [],
|
||||
"못만듦": [],
|
||||
}
|
||||
folder = _items(root) / "system_none_SS000022"
|
||||
assert result == {"만듦": ["pipe@40.0", "st0"], "지움": [], "못만듦": [], "옮겨받음": []}
|
||||
folder = _items(root) / "st0"
|
||||
got = {path.name for path in folder.iterdir()}
|
||||
assert {"집계.json", "도면.json", "면적.json", "재료.json", "manifest.json"} <= got
|
||||
total = json.loads((folder / "집계.json").read_text(encoding="utf-8"))
|
||||
@@ -139,15 +136,12 @@ def test_지정하면_폴더가_생기고_내용이_원본과_같음(world):
|
||||
drawing = json.loads((world["system"] / "structure/ms.json").read_text(encoding="utf-8"))
|
||||
assert json.loads((folder / "도면.json").read_text(encoding="utf-8")) == drawing
|
||||
manifest = json.loads((folder / "manifest.json").read_text(encoding="utf-8"))
|
||||
assert manifest["원본"] == MS and manifest["구조물"] == ["st0"] and len(manifest["판"]) == 16
|
||||
pipe = json.loads(
|
||||
(_items(root) / "system_none_SS000011/manifest.json").read_text(encoding="utf-8")
|
||||
)
|
||||
assert manifest["원본"] == {**MS, "경로": ["돌쌓기", "(찰·메마다)", "H=(높이마다)"]}
|
||||
assert manifest["구조물"] == ["st0"] and len(manifest["판"]) == 16
|
||||
pipe = json.loads((_items(root) / "pipe@40.0/manifest.json").read_text(encoding="utf-8"))
|
||||
assert pipe["구조물"] == ["pipe@40.0"]
|
||||
# 일위대가 UA 줄 + 담은 로직 줄(M01 시스템)
|
||||
labor = json.loads(
|
||||
(_items(root) / "system_none_SS000011/일위대가.json").read_text(encoding="utf-8")
|
||||
)
|
||||
labor = json.loads((_items(root) / "pipe@40.0/일위대가.json").read_text(encoding="utf-8"))
|
||||
assert labor["줄"]["키"] == "UA000036"
|
||||
assert [row["키"] for row in labor["로직"]] + labor["빠진로직"] == [
|
||||
entry["로직"] for entry in labor["줄"]["담은로직"]
|
||||
@@ -157,7 +151,7 @@ def test_지정하면_폴더가_생기고_내용이_원본과_같음(world):
|
||||
def test_원본을_바꿔도_프로젝트_값은_그대로(world):
|
||||
root, system = world["root"], world["system"]
|
||||
_save(root, [_dry(MS)], [])
|
||||
before = (_items(root) / "system_none_SS000022/집계.json").read_text(encoding="utf-8")
|
||||
before = (_items(root) / "st0/집계.json").read_text(encoding="utf-8")
|
||||
table = json.loads((system / "table/구조물집계표.json").read_text(encoding="utf-8"))
|
||||
for column in table["열"]:
|
||||
if column["id"] == "ms":
|
||||
@@ -166,7 +160,7 @@ def test_원본을_바꿔도_프로젝트_값은_그대로(world):
|
||||
json.dumps(table, ensure_ascii=False), encoding="utf-8"
|
||||
)
|
||||
assert _save(root, [_dry(MS)], [])["만듦"] == [] # 다시 저장해도 안 다시 씀
|
||||
after = (_items(root) / "system_none_SS000022/집계.json").read_text(encoding="utf-8")
|
||||
after = (_items(root) / "st0/집계.json").read_text(encoding="utf-8")
|
||||
assert after == before
|
||||
doc = fill.fill_table(root, table)
|
||||
heads = [c["머리"][0] for c in doc["열"] if c["id"].startswith("ms|")]
|
||||
@@ -174,16 +168,20 @@ def test_원본을_바꿔도_프로젝트_값은_그대로(world):
|
||||
|
||||
|
||||
def test_지정_바꿈_해제_삭제면_옛_폴더를_지움(world):
|
||||
"""같은 항목을 고른 구조물 둘 = 폴더 둘 · 한쪽만 바꾸면 그쪽만 새로 · 해제 · 삭제면 지움."""
|
||||
root = world["root"]
|
||||
_save(root, [_dry(MS), _dry(MS)], [])
|
||||
manifest = _items(root) / "system_none_SS000022/manifest.json"
|
||||
assert json.loads(manifest.read_text(encoding="utf-8"))["구조물"] == ["st0", "st1"]
|
||||
# 한 구조물만 바꿈 — 같은 항목을 쓰는 구조물이 남으면 폴더 유지 · 목록만 줄어듦
|
||||
assert sorted(p.name for p in _items(root).iterdir()) == ["st0", "st1"]
|
||||
result = _save(root, [_dry(RV), _dry(MS)], [])
|
||||
assert result["만듦"] == ["system_none_SS000001"] and result["지움"] == []
|
||||
assert json.loads(manifest.read_text(encoding="utf-8"))["구조물"] == ["st1"]
|
||||
assert result["만듦"] == ["st0"] and result["지움"] == ["st0"] # 안 고쳤으니 옛 것은 지움
|
||||
assert json.loads((_items(root) / "st0/manifest.json").read_text("utf-8"))["원본"]["key"] == (
|
||||
"SS000001"
|
||||
)
|
||||
assert json.loads((_items(root) / "st1/manifest.json").read_text("utf-8"))["원본"]["key"] == (
|
||||
"SS000022"
|
||||
)
|
||||
# 해제 · 삭제
|
||||
assert _save(root, [_dry(None)], [])["지움"] == ["system_none_SS000001", "system_none_SS000022"]
|
||||
assert _save(root, [_dry(None)], [])["지움"] == ["st0", "st1"]
|
||||
assert list(_items(root).iterdir()) == []
|
||||
|
||||
|
||||
@@ -197,8 +195,8 @@ def test_회사_층_항목은_회사_폴더에서_복사(world):
|
||||
row["분류3"] = "회사 것"
|
||||
(company / layers.COMBO_FILE).write_text(json.dumps(combo, ensure_ascii=False), "utf-8")
|
||||
owned = {**MS, "layer": "company", "owner": "3"}
|
||||
assert _save(root, [_dry(owned)], [])["만듦"] == ["company_3_SS000022"]
|
||||
total = json.loads((_items(root) / "company_3_SS000022/집계.json").read_text("utf-8"))
|
||||
assert _save(root, [_dry(owned)], [])["만듦"] == ["st0"]
|
||||
total = json.loads((_items(root) / "st0/집계.json").read_text("utf-8"))
|
||||
assert total["줄"]["분류3"] == "회사 것"
|
||||
# 채움 — 회사 항목은 시스템 열과 안 겹치는 새 열
|
||||
doc = fill.fill_table(
|
||||
@@ -210,7 +208,7 @@ def test_회사_층_항목은_회사_폴더에서_복사(world):
|
||||
|
||||
def test_원본에_없는_항목은_못만듦으로_남김(world):
|
||||
gone = {**MS, "key": "SS999999"}
|
||||
assert _save(world["root"], [_dry(gone)], [])["못만듦"] == ["system_none_SS999999"]
|
||||
assert _save(world["root"], [_dry(gone)], [])["못만듦"] == ["st0"]
|
||||
|
||||
|
||||
# ── 채움 ─────────────────────────────────────────────
|
||||
@@ -245,4 +243,4 @@ def test_스냅샷이_없으면_알림(world):
|
||||
def test_초기화는_templates_를_안_건드리고_복제는_통째로():
|
||||
assert not any(tree.startswith("templates") for tree in initial._FILE_TREES)
|
||||
tool = (config_system.PROJECT_ROOT / "db_management/tools_clone_project.py").read_text("utf-8")
|
||||
assert '"robocopy",' in tool and '"/E",' in tool # 프로젝트 폴더 전체(templates/items 포함)
|
||||
assert '"robocopy",' in tool and '"/E",' in tool # 프로젝트 폴더 전체(templates 포함)
|
||||
|
||||
Reference in New Issue
Block a user