diff --git a/fe-admin/src/components/Layout.tsx b/fe-admin/src/components/Layout.tsx index 202360d..9c20c85 100644 --- a/fe-admin/src/components/Layout.tsx +++ b/fe-admin/src/components/Layout.tsx @@ -191,26 +191,61 @@ function resolvePath(key: string): string | null { return null } -// Admin side: hide the per-ContractType contract submenu (Ct_*) — that's a -// user-app concern. Keep Wf_* workflow-admin leaves. -// [S57] BỎ ẩn "Danh mục" (Master/Catalogs + Cấu hình HRM re-parent vào đây) — gom -// master data về 1 chỗ cho CẢ admin lẫn nhân viên (đảo S29 hide). Admin nay quản -// master trực tiếp trên fe-admin; write vẫn khóa Admin/CatalogManager ở BE controller. -// 🔴 [K4a — S166, vá-8] RÀNG BUỘC NGƯỢC với `resolvePath` bên trên — đọc trước khi -// sửa bộ lọc này. fe-user có nhánh regex `^Khkk_G([1-8])_(WfView|List|Create|Pending| -// Approved|Deleted)$`; fe-admin CỐ Ý KHÔNG có (admin không có `WorkflowMatrixViewPage` -// — lead chốt 2026-07-27, giữ lệch). Hệ quả: 42 leaf `Khkk_G{2..8}_*` mà BE seed sẽ -// rơi vào `resolvePath → null` ⇒ MenuLeaf trả null ⇒ DROP IM LẶNG (gotcha #50). -// ⚠️ ĐO ĐĨA 2026-08-01: hàm này CHỈ ẩn `Ct_*` — `KeHoachKyKet` KHÔNG hề nằm trong tập -// ẩn, tức ràng buộc trên KHÔNG phải chuyện tương lai mà ĐANG hiệu lực: sidebar admin -// hiện root KHKK, 7 nhóm con, và 42 leaf của nhóm 2..8 im lặng biến mất (nhóm 1 sống -// nhờ 6 dòng `Khkk_*` không-infix trong `staticMap`). Đây là trạng thái ĐÃ KHAI, chấp -// nhận có chủ đích ở lượt K4a — KHÔNG phải bug mới phát sinh. -// ⇒ Ai muốn admin thấy đủ 8 nhóm (hoặc ngược lại, thêm `KeHoachKyKet` vào tập ẩn rồi -// sau đó gỡ ra) thì PHẢI nới regex `Khkk_G*` trong `resolvePath` TRƯỚC — và nới thì -// phải quyết luôn `WfView` bên admin trỏ đâu, vì Designer không nhận `?group=`. +// ============================================================================ +// [K6 — S166 2026-08-01, QĐ7] ADMIN THU VỀ VAI "NƠI-CONFIG" +// ============================================================================ +// Sidebar fe-admin chỉ còn: Tổng quan · Hệ thống (Người dùng / Vai trò / Phân +// quyền / Menu eOffice, cùng nhánh con "Quy trình duyệt (Mới)" + toàn bộ Designer). +// Mọi module NGHIỆP VỤ (4 giai đoạn HĐ, Duyệt NCC, Danh mục, HRM, Văn phòng…) +// làm việc ở fe-user; admin không phải là chỗ chạy nghiệp vụ nữa. +// +// 🔴 LỊCH SỬ ĐÃ ĐẢO 2 LẦN — đọc kỹ trước khi "sửa cho đúng": +// · S29 : ẩn "Danh mục" khỏi admin. +// · S57 : BỎ ẩn — gom master data về 1 chỗ cho cả admin lẫn nhân viên, admin +// quản master trực tiếp trên fe-admin. (Đảo lần 1.) +// · S164 : QĐ7 ẩn LẠI, lần này ẩn rộng hơn hẳn — admin thu về vai NƠI-CONFIG. +// (Đảo lần 2, chính là luật đang chạy dưới đây.) +// ⇒ Comment cũ của S57 nay KHÔNG còn hiệu lực. Ai đọc lịch sử git thấy hai +// lời ngược nhau thì đây là chỗ giải thích: cả hai đều từng đúng, mốc sau +// thắng mốc trước. Đừng "khôi phục" S57 vì tưởng gặp bug. +// +// 🔴 ĐÂY LÀ LỚP HIỂN THỊ, KHÔNG PHẢI LỚP QUYỀN (2 tầng độc lập — gotcha #82): +// Route fe-admin còn nguyên, quyền của tài khoản admin còn nguyên ⇒ deep-link +// thẳng `/purchase-evaluations`, `/khkk/list`… VẪN vào được và API vẫn trả 200. +// Thu gọn ở đây = bớt lối đi trên menu, KHÔNG phải thu hồi quyền. Muốn CHẶN +// thật thì phải làm ở BE authz (`[Authorize(Policy=…)]`), không phải ở file này. +// +// 🔴 CƠ CHẾ: `filterForAdmin` lọc ĐỆ QUY mọi tầng ⇒ ẩn 1 root là cả cây con chết +// theo. Vì vậy tập dưới chỉ liệt ROOT (+2 nhánh con của `System`), KHÔNG liệt +// từng leaf — liệt leaf vừa thừa vừa phải bảo trì lại mỗi lần BE thêm key. +// Hệ quả phụ (tốt): các leaf `Khkk_G{2..8}_*` không còn được render bên admin +// nên chuyện `resolvePath` thiếu nhánh `Khkk_G*` (khai ở K4a) hết là vấn đề — +// nay chúng bị cắt từ tầng cha chứ không "rơi im lặng" ở tầng leaf nữa. +// ⚠️ Nếu sau này gỡ `KeHoachKyKet` khỏi tập này thì PHẢI nới regex `Khkk_G*` +// trong `resolvePath` TRƯỚC, kèm quyết định `WfView` admin trỏ đâu (admin +// không có `WorkflowMatrixViewPage`; Designer không nhận `?group=`). +const ADMIN_HIDDEN_KEYS = new Set([ + 'PurchaseEvaluations', // GĐ1 root — Pe_* chết theo + 'KeHoachKyKet', // GĐ2 root — toàn bộ nhánh Khkk_G* chết theo + 'Contracts', // GĐ3 root — Ct_* vốn đã có luật prefix, nay ẩn cả root + 'HopDongCung', // GĐ4 root — Hdc_* chết theo + 'Forms', + 'Reports', + 'Master', // Danh mục root — Suppliers/Projects/Departments/Catalogs + Cấu hình HRM chết theo + 'Hrm', + 'Off', + 'Personal', + 'Workflows', // CON của System ⇒ phải liệt riêng (Wf_* chết theo) + 'PeWorkflows', // CON của System ⇒ phải liệt riêng (PeWf_* chết theo) +]) + function isAdminHidden(key: string): boolean { - return key.startsWith('Ct_') + // `Ct_*` giữ luật prefix cũ: leaf hợp đồng theo loại là chuyện của app người + // dùng. Thừa so với việc ẩn root `Contracts` ở trên, nhưng giữ để một ngày + // nào đó mở lại root thì đám leaf `Ct_*` không ùa về theo. (KHÔNG ghi số lá + // ở đây — số-đếm trong comment thối ngay khi BE thêm key [bài #84]; cần số + // thì grep `Ct_` trong MenuKeys.cs phía BE.) + return ADMIN_HIDDEN_KEYS.has(key) || key.startsWith('Ct_') } function filterForAdmin(nodes: MenuNode[]): MenuNode[] {