From 2640fb4c60ed671d10d3fcd0a0fbad51aee784ab Mon Sep 17 00:00:00 2001 From: umsangdon Date: Fri, 9 Oct 2026 15:03:30 +0900 Subject: [PATCH] =?UTF-8?q?feat(M02):=20=EA=B8=B0=EB=B3=B8=20=EC=B8=B5=20?= =?UTF-8?q?=3D=20=EA=B0=9C=EC=9D=B8=20=E2=80=94=20=EC=B8=B5=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=A3=BC=EC=86=8C=20=C2=B7=20=EC=82=AC=EC=A0=84?= =?UTF-8?q?=EC=A1=B0=ED=95=A9=EB=8F=84=20=C2=B7=20=ED=9A=8C=EC=82=AC=20?= =?UTF-8?q?=EC=97=86=EC=9C=BC=EB=A9=B4=20=EB=A7=88=EC=8A=A4=ED=84=B0(134-4?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01SE9MxeXTu2uaDZ55BJowAY --- M02_MasterTemplete/M02_MasterTemplete_Layer.ts | 12 +++++++++--- M02_MasterTemplete/M02_MasterTemplete_UI_Page.ts | 2 +- resources/tester/test_b01_settings_cards.py | 12 +++++++++--- resources/tester/test_m02_layer_screen.py | 4 +++- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/M02_MasterTemplete/M02_MasterTemplete_Layer.ts b/M02_MasterTemplete/M02_MasterTemplete_Layer.ts index 496792475..77736b7d4 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Layer.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_Layer.ts @@ -34,11 +34,17 @@ const ROOTS: Root[] = ["master", "company", "personal"]; export const layerOfRoot = (root: Root): ManageLayer => (root === "master" ? "system" : root); -/** 주소 인자에서 진입 — 모르는 값 · 없음 = 마스터 · 구조물 조합 */ -export function entryFromHash(): Entry { +/** 주소 인자에서 진입 — 층 모르는 값 · 없음 = 기본 층(134-4 · 개인 · 회사 없으면 마스터 · 사용자를 안 주면 + * 마스터) · 열 곳 없음 = 구조물 조합 */ +export function entryFromHash(user?: SessionUser | null): Entry { const query = currentQuery(); const raw = query.get("root") ?? query.get("layer"); - const root: Root = raw === "company" || raw === "personal" ? raw : "master"; + const root: Root = + raw === "master" || raw === "company" || raw === "personal" + ? raw + : user === undefined + ? "master" + : defaultRoot(user); const open = OPENS.find((one) => one === query.get("open")) ?? "구조물조합"; const owner = root === "master" ? null : query.get("owner") || null; const pre = ROOTS.find((one) => one === query.get("pre")) ?? null; diff --git a/M02_MasterTemplete/M02_MasterTemplete_UI_Page.ts b/M02_MasterTemplete/M02_MasterTemplete_UI_Page.ts index 8547d25ff..95f647195 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_UI_Page.ts +++ b/M02_MasterTemplete/M02_MasterTemplete_UI_Page.ts @@ -52,7 +52,7 @@ const NEW_ASK = export async function renderM02MasterTemplate(root: HTMLElement): Promise { const user = await fetchSessionUser().catch(() => null); - const entry = entryFromHash(); + const entry = entryFromHash(user); // 134-4 — 해시에 층 없음 = 개인(회사 없으면 마스터) const company = viewCompany(entry, user); // 볼 회사(시스템 관리자는 고른 회사) let layer = layerOfRoot(entry.root); // 회사 층 주인 = 볼 회사 · 자기 층 주인을 적어도 자기 층 · 회사 없는 사람의 회사 · 개인 = 마스터(단추 자리에 안내) diff --git a/resources/tester/test_b01_settings_cards.py b/resources/tester/test_b01_settings_cards.py index 82c61a547..004a0013d 100644 --- a/resources/tester/test_b01_settings_cards.py +++ b/resources/tester/test_b01_settings_cards.py @@ -217,7 +217,8 @@ def test_회사_찾기_거르기(): @pytest.mark.skipif(shutil.which("node") is None, reason="node 가 없음") def test_구조물_조합_기본_층_개인(): - """123-1 — 회사 있는 사람은 역할 무관 구조물 조합 = 개인 · 회사 없으면 지금 규칙 · 다른 곳 그대로.""" + """123-1 — 회사 있는 사람은 역할 무관 구조물 조합 = 개인 · 회사 없으면 지금 규칙 · 다른 곳 그대로 · + 134-4 — 층 없는 주소도 개인(회사 없으면 마스터) · 사전조합 기본 층도 같은 규칙.""" m = "B01_Dashboard_PermMasterWrite" combo = f"{M02}?open=구조물조합&root=personal" assert _cards({"role": "SYSTEM_ADMIN", "is_master": False, "company_id": 1}, 3) == [ @@ -238,7 +239,12 @@ def test_구조물_조합_기본_층_개인(): assert _cards({"role": "ADMIN", "is_master": False, "company_id": None})[0][2] == ( f"{M02}?open=구조물조합&root=company" ) - # 다른 곳 기본 그대로 — 고르기 탭(일위대가 · 복사 생성 · 복사해 가져오기) · 층 없는 주소 + # 다른 곳 기본 그대로 — 고르기 탭(일위대가 · 복사 생성 · 복사해 가져오기) layer = _text(ROOT / "M02_MasterTemplete" / "M02_MasterTemplete_Layer.ts") assert 'return { tabs, first: isSystem || !own ? "master" : "personal" };' in layer - assert 'raw === "company" || raw === "personal" ? raw : "master";' in layer + # 134-4 — 층 없는 주소 = 기본 층(개인 · 회사 없으면 마스터) · 사전조합 층도 같은 기본 + assert 'ownOwner("personal", user) ? "personal" : "master";' in layer + assert ': user === undefined\n ? "master"\n : defaultRoot(user);' in layer + page = _text(ROOT / "M02_MasterTemplete" / "M02_MasterTemplete_UI_Page.ts") + assert "const entry = entryFromHash(user);" in page + assert "let pre = preScope(entry.pre ?? defaultRoot(user));" in page diff --git a/resources/tester/test_m02_layer_screen.py b/resources/tester/test_m02_layer_screen.py index a1f9b249c..0b4034b86 100644 --- a/resources/tester/test_m02_layer_screen.py +++ b/resources/tester/test_m02_layer_screen.py @@ -86,7 +86,9 @@ def test_주소_인자를_라우트에서_뗌(): layer = _text(LAYER) # 진입 해시 `?open=&root=&owner=`(PLAN 27-1d) · 옛 `?layer=` 도 root 로 assert 'query.get("root") ?? query.get("layer")' in layer - assert 'raw === "company" || raw === "personal" ? raw : "master"' in layer + assert ( + 'raw === "master" || raw === "company" || raw === "personal"' in layer + ) # 없음 = 기본(134-4) assert '["구조물조합", "옵션", "도면", "일위대가조합"]' in layer # 일위대가 조합 서고 = 50-3 picker = _text(ROOT / "ui_template" / "ui_template_item_picker.ts") assert 'open: "구조물조합", root: "personal"' in picker and "layer=personal" not in picker