[CLAUDE] FE-Admin: K6 SP-002 admin thu gon menu 12-key ADMIN_HIDDEN_KEYS + comment lineage 2-dao (gate PASS-WITH-FLAGS 5)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m28s

C1 15-la liet ten 16/16 assert + control-am 15->63; C2 fe-user 0-diff; C4 display-only #82.
Gate MAJOR-1 fixed truoc commit: bo 3 so-dem trong comment (28-leaf da SAI luc land; luat #84).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-01 11:54:30 +07:00
parent d82c5a8175
commit 1c6d77a6cc

View File

@ -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<string>([
'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[] {