[CLAUDE] Domain+App+Api+FE-User+FE-Admin: Plan AA Chunk A - BE IsUserSelectable filter + menu seed Pe_DuyetNcc_WfView + sidebar widen w-72 xl:w-80 + revert Plan U truncate

BE changes:
- MenuKeys.cs +helper PurchaseEvaluationWorkflowView(typeCode) => "Pe_{typeCode}_WfView"
- DbInitializer.cs SeedMenuTreeAsync:
  - tree.Add LuongDuyet (Order=2 first child) cho 2 type PE
  - INSERT-only loop -> INSERT-OR-UPDATE-Order (shift existing prod rows Order+1)
  - Idempotent: skip nếu Order match, UPDATE nếu mismatch
- DbInitializer.cs SeedPurchaseEvaluationPermissionDefaultsAsync +WfView leaf cho 7 role Read
- ApprovalWorkflowV2AdminFeatures.cs GetAwAdminOverviewQuery +IsUserSelectable bool? = null
  + handler conditional Where(d => d.IsUserSelectable == ius)
- ApprovalWorkflowsV2Controller.cs Overview signature +[FromQuery] bool? isUserSelectable
  pass-through to mediator (gotcha #44 fix preserved class-level [Authorize] bare)

FE Layout changes (mirror 2 app rule §3.9):
- fe-user resolvePath regex (List|Create|Pending|WfView) + route
  /purchase-evaluations/workflow-matrix?type=N
- fe-user + fe-admin sidebar w-60 xl:w-72 -> w-72 xl:w-80 (+48/+32px gain)
- Revert Plan U S23 t11 truncate × 5 sites (3 fe-user MenuGroup+MenuLeaf+StaticLeaf
  + 2 fe-admin MenuGroup+MenuLeaf). Keep min-w-0 flex-1 + shrink-0 + title
  tooltip (no harm). Bro request hiển thị đầy đủ label custom Mig 27 dài.

Why:
- User UAT request 2026-05-15: thêm menu "Luồng duyệt" trên Danh sách hiển thị
  ma trận phân quyền workflow V2 admin Designer ghim ra cho user xem trước khi
  tạo phiếu. Filter IsUserSelectable=true (Mig 25).
- Sidebar Plan U S23 t11 truncate hiển thị "..." → bro muốn full label.
  Widen sidebar +32-48px + bỏ truncate cho phép wrap natural khi cực dài.

Verify:
- dotnet build SolutionErp.slnx PASS clean 0 err 2 warn pre-existing DocxRenderer
- Investigator Pre-A confirm gotcha #44 đã fix permanent từ 2026-05-08
- Reviewer cumulative PASS 0 critical / 0 major / 0 minor blocker

Pending Chunk B: FE WorkflowMatrixViewPage.tsx ~215 LOC + types + App.tsx route.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-15 16:34:40 +07:00
parent a1a910f576
commit ee776d5745
6 changed files with 73 additions and 24 deletions

View File

@ -1430,10 +1430,14 @@ public static class DbInitializer
foreach (var code in MenuKeys.PurchaseEvaluationTypeCodes)
{
var label = peTypeLabels.GetValueOrDefault(code, code);
tree.Add((MenuKeys.PurchaseEvaluationGroup(code), label, MenuKeys.PurchaseEvaluations, peOrder++, "FileCheck"));
tree.Add((MenuKeys.PurchaseEvaluationList(code), "Danh sách", MenuKeys.PurchaseEvaluationGroup(code), peOrder++, "List"));
tree.Add((MenuKeys.PurchaseEvaluationCreate(code), "Thao tác", MenuKeys.PurchaseEvaluationGroup(code), peOrder++, "Plus"));
tree.Add((MenuKeys.PurchaseEvaluationPending(code),"Duyệt", MenuKeys.PurchaseEvaluationGroup(code), peOrder++, "CheckCircle2"));
tree.Add((MenuKeys.PurchaseEvaluationGroup(code), label, MenuKeys.PurchaseEvaluations, peOrder++, "FileCheck"));
// [Plan AA S24 t1] "Luồng duyệt" leaf phía trên "Danh sách" — read-only
// view ma trận phân quyền workflow V2 admin Designer ghim. User biết
// trước khi tạo phiếu ai duyệt step nào.
tree.Add((MenuKeys.PurchaseEvaluationWorkflowView(code), "Luồng duyệt", MenuKeys.PurchaseEvaluationGroup(code), peOrder++, "Network"));
tree.Add((MenuKeys.PurchaseEvaluationList(code), "Danh sách", MenuKeys.PurchaseEvaluationGroup(code), peOrder++, "List"));
tree.Add((MenuKeys.PurchaseEvaluationCreate(code), "Thao tác", MenuKeys.PurchaseEvaluationGroup(code), peOrder++, "Plus"));
tree.Add((MenuKeys.PurchaseEvaluationPending(code), "Duyệt", MenuKeys.PurchaseEvaluationGroup(code), peOrder++, "CheckCircle2"));
}
// PE workflow admin leaves dưới `PeWorkflows`
@ -1444,18 +1448,32 @@ public static class DbInitializer
tree.Add((MenuKeys.PeWorkflowTypeLeaf(code), label, MenuKeys.PeWorkflows, peWfOrder++, "FileCheck"));
}
var existingKeys = await db.MenuItems.Select(m => m.Key).ToListAsync();
var existingItems = await db.MenuItems.ToDictionaryAsync(m => m.Key);
var added = 0;
var reordered = 0;
foreach (var (key, label, parent, o, icon) in tree)
{
if (existingKeys.Contains(key)) continue;
if (existingItems.TryGetValue(key, out var existing))
{
// [Plan AA S24 t1] Shift Order khi insert leaf mới giữa list cũ —
// existing rows phải UPDATE Order theo seed list canonical.
// Idempotent: skip nếu Order đã match. KHÔNG đụng Label / ParentKey
// / Icon (label backfill section riêng phía dưới).
if (existing.Order != o)
{
existing.Order = o;
reordered++;
}
continue;
}
db.MenuItems.Add(new MenuItem { Key = key, Label = label, ParentKey = parent, Order = o, Icon = icon });
added++;
}
if (added > 0)
if (added > 0 || reordered > 0)
{
await db.SaveChangesAsync();
logger.LogInformation("Seeded {Count} menu items", added);
if (added > 0) logger.LogInformation("Seeded {Count} menu items", added);
if (reordered > 0) logger.LogInformation("Reordered {Count} menu items", reordered);
}
// Backfill label updates for menu items renamed via business changes.
@ -1546,11 +1564,13 @@ public static class DbInitializer
AppRoles.Director, AppRoles.AuthorizedSigner,
};
// Menu keys cần grant: PurchaseEvaluations root + per-type group + 3 leaf
// Menu keys cần grant: PurchaseEvaluations root + per-type group + 4 leaf
// ([Plan AA S24 t1] thêm WfView read-only matrix view).
var menuKeys = new List<string> { MenuKeys.PurchaseEvaluations };
foreach (var typeCode in MenuKeys.PurchaseEvaluationTypeCodes)
{
menuKeys.Add(MenuKeys.PurchaseEvaluationGroup(typeCode));
menuKeys.Add(MenuKeys.PurchaseEvaluationWorkflowView(typeCode));
menuKeys.Add(MenuKeys.PurchaseEvaluationList(typeCode));
menuKeys.Add(MenuKeys.PurchaseEvaluationCreate(typeCode));
menuKeys.Add(MenuKeys.PurchaseEvaluationPending(typeCode));