Merge remote-tracking branch 'origin/sub_laptop_5' into sub_laptop_1

This commit is contained in:
2026-10-04 17:38:06 +09:00
8 changed files with 400 additions and 8 deletions
+59
View File
@@ -0,0 +1,59 @@
"""실무문서(PLAN 39-2) — 옛 마스터 일위대가 조합 표 통째 · 시스템 관리자만 통째 지우기.
못박는 것
- `DELETE /api/m02/practice?판=` = 시스템 관리자만(그 밖 403) · 판 다르면 409 ·
구조물이 쓰는 조합이 있으면 409(아무것도 안 지움) · 지우면 줄 0 · 마스터 틀 검사 그대로.
- 화면(`Practice.ts`) = 마스터 층 · 시스템 관리자만 · 물음 두 번 · 상세 읽기만.
정본(마스터)은 읽기만 · 쓰기는 임시 사본.
"""
from __future__ import annotations
import json
from pathlib import Path
from M01_MasterData import M01_MasterData_Store as m01
from M01_MasterData import M01_MasterData_Store_Combo as combo_store
from M02_MasterTemplete import M02_MasterTemplete_Combo_Store as combos
from resources.tester.test_m02_combo_layers import _as, _list, master_copy, world # noqa: F401
ROOT = Path(__file__).resolve().parents[2]
M02 = ROOT / "M02_MasterTemplete"
def _drop(client, 판: str, want: int) -> dict:
res = client.delete("/api/m02/practice", params={"판": 판})
assert res.status_code == want, res.text
return res.json()
def test_통째_지우기_시스템_관리자만_판_쓰는_곳(world, master_copy, monkeypatch): # noqa: F811
admin = _as(world, "SYSTEM_ADMIN")
before = _list(admin, "system")
assert before["줄"] # 사본에 옛 조합이 있음
for role in ("USER", "ADMIN"):
_drop(_as(world, role), before["판"], 403)
admin = _as(world, "SYSTEM_ADMIN")
_drop(admin, "옛판", 409)
used = before["줄"][0]["키"]
monkeypatch.setattr(combo_store, "combo_users", lambda k: ["항목 하나"] if k == used else [])
got = _drop(admin, before["판"], 409)
assert "항목 하나" in json.dumps(got, ensure_ascii=False)
assert len(_list(admin, "system")["줄"]) == len(before["줄"]) # 아무것도 안 지움
monkeypatch.setattr(combo_store, "combo_users", lambda k: [])
got = _drop(admin, before["판"], 200)
assert got["줄"] == [] and len(got["지운조합"]) == len(before["줄"])
doc = json.loads((master_copy / combos.FILE).read_text(encoding="utf-8"))
assert doc["줄"] == [] and m01.cm.check_form(combos.FILE, doc) == []
again = _list(admin, "system")
assert _drop(admin, again["판"], 200)["지운조합"] == [] # 빈 표 = 그대로
def test_화면_시스템_관리자_마스터만_물음_두_번_읽기만():
side = (M02 / "M02_MasterTemplete_UI_Side.ts").read_text("utf-8")
assert 'layer === "system" && opt.isAdmin' in side
order = side.split('className: "m02-side__lists ui-sidebar-panel",')[1].split("});")[0]
assert order.index("extras.도면") < order.index("practice") # 도면 양식 아래
view = (M02 / "M02_MasterTemplete_Practice.ts").read_text("utf-8")
assert view.count("showConfirmDialog(") == 2
assert "dropPractice(" in view and "createInputField" not in view # 고칠 칸 없음
@@ -120,11 +120,14 @@ def test_좌측_줄은_구조물_집계_양식_아래_한_줄_같은_한_곳에
assert side.index("옵션: section(options.title") < side.index(
'도면: section(L("M02_KindDrawing")'
)
# 차례 = 구조물 조합(일위대가는 그 하위 · 39-2) → 옵션 → 도면 양식
assert "children: [summary, ...(extras ? [extras.옵션, extras.도면" in side
# 자재 조합을 열면 이 줄 · 「전체 항목」 고름 지움 / 이 줄을 열면 자재 조합 · 「전체 항목」 고름 지움
assert "onOpen: () => (options.clear(), (allPicked = null), paint())" in side
assert "onOpen: () => (matset.clear(), (allPicked = null), paint())" in side
# 차례 = 구조물 조합(일위대가는 그 하위 · 39-2) → 옵션 → 도면 양식 → 실무문서
order = side.split('className: "m02-side__lists ui-sidebar-panel",')[1].split("});")[0]
assert (
order.index("summary") < order.index("extras.옵션, extras.도면") < order.index("practice")
)
# 자재 조합을 열면 이 줄 · 실무문서 · 「전체 항목」 고름 지움 / 이 줄을 열면 자재 조합 · … 지움
assert "onOpen: () => (options.clear(), practice?.clear(), (allPicked = null), paint())" in side
assert "onOpen: () => (matset.clear(), practice?.clear(), (allPicked = null), paint())" in side
paint = side.split("function paint(): void {")[1].split("\n }\n")[0]
assert "if (opt.getOpen()) options.clear();" in paint # 양식을 열면 이 줄 고름 지움
api = (ROOT / "M02_MasterTemplete/M02_MasterTemplete_Api_Fetch.ts").read_text("utf-8")