[CLAUDE] Contract: K4a+K4b SP-002 sidebar 8 nhom x 6 leaf + noi ?group= end-to-end (0-mig)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 6m23s

K4a (gate PASS-WITH-FLAGS 4, sub-reviewer-gate-k4a.md): 49 key Khkk_G{2-8} bo-sinh
by-construction 3-phia (All/seed/grant) MenuKeys.cs + DbInitializer 49 row + labelBackfill
G1 nhan A1 + site-2 Concat + va 7/10/11/13/15 (nhan N2 co "pha do"; comment 1893 -> mo-neo
grep). All 64->113, Policies 256->452 (test T2 khoa runtime). Test +7 KhkkGroupMenuSeedTests
(T7 revoker-khong-dung-Khkk: probe vi-phan 112->0, gotcha #84).

K4b (gate PASS-WITH-FLAGS 4M/5m 0-chan, sub-reviewer-gate-k4b.md): KhkkListPage x2 derive
phase+group tu searchParams (leaf->leaf khong F5, navKey reset) + queryKey {group,phase,
search,page,deletedView} + KhkkCreatePage preset ?group= + staticMap G1 6-leaf group=1 +
regex Khkk_G([1-8])_* fe-user (fe-admin GHI RANG BUOC isAdminHidden) + FLAG-1 lead-fix:
GET /deleted +group mirror List (Controller+Query+handler SAU-IDOR) + FE noi 2-nhanh.

2 wave 1 commit CO KHAI: Layout.tsx dinh ca 2 wave khong tach hunk phi-tuong-tac; moi dong
deu qua gate rieng. STATUS canonical 5-row dong bo (71/97/452/113/620->621) + bundle :479.
No K4c: MAJOR-A test /deleted+group filter + MAJOR-C WfView doc group. Suite 621/0
(45D+576I) + filter 41/41 + npm x2 + dotnet 0E.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-08-01 10:10:11 +07:00
parent bc1e7c937d
commit 88e7ecf263
14 changed files with 880 additions and 63 deletions

View File

@ -56,10 +56,14 @@ function resolvePath(key: string): string | null {
const staticMap: Record<string, string> = {
// [W2 KHKK S161] GĐ2 hết skeleton — 6 leaf re-point trang thật (gotcha #50:
// thiếu route = sidebar drop SILENT; filter đi qua query param, page map FILTER_TO_PHASE).
Khkk_List: '/khkk/list',
Khkk_Create: '/khkk/create',
Khkk_Pending: '/khkk/list?filter=ChoDuyet',
Khkk_Approved: '/khkk/list?filter=DaDuyet',
// [K4b S166 — spec K4b-7] 6 leaf nhóm 1 mang `group=1` TƯỜNG MINH. Chúng là 6 key
// cũ KHÔNG-infix (S159, cấm đổi tên) nên không đi qua regex `Khkk_G{n}_*` bên dưới;
// thiếu `group=1` ở đây thì "Danh sách" của nhóm 1 lại hiện phiếu của cả 8 nhóm —
// đúng một mục nói dối giữa 8 mục nói thật. Trang coi "vắng group" = xem tất cả.
Khkk_List: '/khkk/list?group=1',
Khkk_Create: '/khkk/create?group=1',
Khkk_Pending: '/khkk/list?group=1&filter=ChoDuyet',
Khkk_Approved: '/khkk/list?group=1&filter=DaDuyet',
// [W7 KHKK S161] GĐ4 hết skeleton — 7 leaf `Hdc_*` re-point trang thật
// `/hard-copies?type=N` (N = ContractType int, mirror TYPE_CODE_TO_INT ở trên).
// gotcha #50: thiếu/để sai route ở đây = leaf DROP IM LẶNG khỏi sidebar.
@ -79,8 +83,8 @@ function resolvePath(key: string): string | null {
KeHoachKyKet: '/khkk/list', // [W2 S161] root GĐ2 hết placeholder — về danh sách phiếu
HopDongCung: '/dashboard',
// [W2 S161] 2 leaf còn lại — WfView đi alias matrix type=10 (App.tsx, không đẻ page mới)
Khkk_WfView: '/khkk/workflow-matrix?type=10',
Khkk_Deleted: '/khkk/list?view=deleted',
Khkk_WfView: '/khkk/workflow-matrix?type=10&group=1',
Khkk_Deleted: '/khkk/list?group=1&view=deleted',
// [Plan CA Hotfix 1 S29 2026-05-22] 4 master + 4 catalog leaf moved từ
// fe-admin → fe-user. resolvePath PHẢI có route mapping nếu không
// MenuLeaf line 238 `if (!path) return null` → sidebar drop silent.
@ -181,6 +185,41 @@ function resolvePath(key: string): string | null {
if (action === 'Approved') return `/purchase-evaluations?type=${typeInt}&phase=7&view=approved`
if (action === 'Deleted') return `/purchase-evaluations?type=${typeInt}&deleted=1`
}
// ===================== [K4a — S166] Sidebar KHKK 8 NHÓM DUYỆT ======================
// `Khkk_G{n}_{action}` — 42 leaf của nhóm 2..8 (BE `MenuKeys.KhkkLeaf` :77, sinh từ
// `KhkkGroupNumbers = [2..8]` × `KhkkLeafActions` 6 hành động). Đây là "chỗ thứ 4"
// Pattern 16-bis: BE seed 42 row mà thiếu nhánh này thì `resolvePath` trả null ⇒
// MenuLeaf nhánh `if (!path) return null` (grep chuỗi đó — số dòng trượt theo edit) ⇒ 42 leaf DROP IM LẶNG (gotcha #50).
//
// 🔴 NHÓM 1 KHÔNG đi qua đây: 7 key cũ KHÔNG-infix (`Khkk_G1` + `Khkk_WfView` …
// `Khkk_Deleted`, seed S159) nằm trong `staticMap` bên trên và CẤM đổi tên
// (đổi = mồ côi permission-row đã cấp — bài S155). Vì thế regex dưới về mặt dữ
// liệu chỉ ăn n = 2..8; để dải `[1-8]` theo spec là CỐ Ý — rộng hơn tập seed một
// nấc, vô hại hôm nay và đúng sẵn nếu sau này nhóm 1 chuyển sang khuôn infix.
//
// 🔴 `?group=n` là DANH TÍNH điều hướng, không phải bộ lọc tuỳ hứng: nó KHÔNG nằm
// trong `TRANSIENT_QUERY_KEYS` (grep tên hằng — đừng neo số dòng) nên 6 leaf cùng nhóm và cùng leaf khác nhóm
// đều phân biệt được khi so khớp active (bài `view=approved` S155 ngay khối trên).
// Tên tham số `filter` / `view` / `group` lấy ĐÚNG từ `KhkkListPage` (grep
// `get('filter')` / `get('view')` / `get('group')` trong file đó — đừng neo số dòng,
// chính wave K4b đã làm số cũ trượt) — sai một chữ ở đây là leaf trỏ tới trang mở
// được nhưng lọc SAI, hỏng câm chứ không đỏ build.
//
// 🔴 fe-admin CỐ Ý KHÔNG nới regex này (lead chốt 2026-07-27, giữ lệch): fe-admin
// không có `WorkflowMatrixViewPage` (`App.tsx` bên đó chỉ có /khkk/list|create|:id)
// nên `WfView` bên admin sẽ là link chết; "Luồng duyệt" phía admin trỏ Designer.
// Khai lệch có chủ đích — xem ghi chú ràng buộc ngược tại `isAdminHidden` fe-admin.
const khkkMatch = key.match(/^Khkk_G([1-8])_(WfView|List|Create|Pending|Approved|Deleted)$/)
if (khkkMatch) {
const [, group, action] = khkkMatch
if (action === 'WfView') return `/khkk/workflow-matrix?type=10&group=${group}`
if (action === 'List') return `/khkk/list?group=${group}`
if (action === 'Create') return `/khkk/create?group=${group}`
if (action === 'Pending') return `/khkk/list?group=${group}&filter=ChoDuyet`
if (action === 'Approved') return `/khkk/list?group=${group}&filter=DaDuyet`
if (action === 'Deleted') return `/khkk/list?group=${group}&view=deleted`
}
return null
}