From 937eb2449c20dfa5f286caeaf8734b5ee3b64512 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 8 May 2026 18:07:56 +0700 Subject: [PATCH] [CLAUDE] Workflow V2: clone leaf Designer + sample seed cho DuyetNccPhuongAn (B) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mở rộng V2 schema cho type B mirror type A đã chốt S17. Phần lớn đã chung qua ApplicableType discriminator — chỉ thêm menu key + sample seed. Changes: - MenuKeys.cs: +const ApprovalWorkflowDuyetNccPhuongAnV2 (AwV2_DuyetNccPhuongAn) + add vào All array - DbInitializer.SeedMenusAsync: +leaf "Duyệt NCC và Giải pháp (Mới)" dưới root ApprovalWorkflowsV2 - DbInitializer +SeedSampleApprovalWorkflowsV2Async: seed QT-DN-PA-V2-001 v01 (1 Bước Phòng CCM × 1 Cấp NV test) Idempotent — skip nếu admin đã tạo bất kỳ workflow B nào hoặc thiếu test user - fe-admin/lib/menuKeys.ts: +AwV2_DuyetNccPhuongAn KHÔNG đụng: - Migration (V2 schema chung qua ApplicableType — Mig 22-24 đã hỗ trợ B) - Service ApproveV2Async (không hardcode type) - Designer page ApprovalWorkflowsV2Page (TYPE_CODE_TO_INT đã có B=2) - Layout/App.tsx (regex AwV2_(.+) match dynamic) - Permission default (admin bypass + role khác không cần Designer access) Verify: dotnet build pass · 81 test pass · npm build fe-admin pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- fe-admin/src/lib/menuKeys.ts | 1 + .../SolutionErp.Domain/Identity/MenuKeys.cs | 3 +- .../Persistence/DbInitializer.cs | 58 ++++++++++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/fe-admin/src/lib/menuKeys.ts b/fe-admin/src/lib/menuKeys.ts index 84e32ed..e1844e6 100644 --- a/fe-admin/src/lib/menuKeys.ts +++ b/fe-admin/src/lib/menuKeys.ts @@ -17,6 +17,7 @@ export const MenuKeys = { // Quy trình duyệt MỚI (Mig 22 — Session 17, 2026-05-08) ApprovalWorkflowsV2: 'ApprovalWorkflowsV2', AwV2_DuyetNcc: 'AwV2_DuyetNcc', + AwV2_DuyetNccPhuongAn: 'AwV2_DuyetNccPhuongAn', } as const export type MenuKey = typeof MenuKeys[keyof typeof MenuKeys] diff --git a/src/Backend/SolutionErp.Domain/Identity/MenuKeys.cs b/src/Backend/SolutionErp.Domain/Identity/MenuKeys.cs index 413af2d..c3d4a43 100644 --- a/src/Backend/SolutionErp.Domain/Identity/MenuKeys.cs +++ b/src/Backend/SolutionErp.Domain/Identity/MenuKeys.cs @@ -64,6 +64,7 @@ public static class MenuKeys // ============================================================ public const string ApprovalWorkflowsV2 = "ApprovalWorkflowsV2"; // root admin (mới) public const string ApprovalWorkflowDuyetNccV2 = "AwV2_DuyetNcc"; // leaf cho Duyệt NCC mới + public const string ApprovalWorkflowDuyetNccPhuongAnV2 = "AwV2_DuyetNccPhuongAn"; // leaf cho Duyệt NCC và Giải pháp mới // ============================================================ // Module Ngân sách (Phase 7) — 4 bảng quản lý ngân sách dự án/gói thầu. @@ -95,7 +96,7 @@ public static class MenuKeys PurchaseEvaluations, Budgets, BudgetList, BudgetCreate, BudgetPending, System, Users, Roles, Permissions, Workflows, PeWorkflows, - ApprovalWorkflowsV2, ApprovalWorkflowDuyetNccV2, // Mig 22 + ApprovalWorkflowsV2, ApprovalWorkflowDuyetNccV2, ApprovalWorkflowDuyetNccPhuongAnV2, // Mig 22 ]; public static readonly string[] Actions = ["Read", "Create", "Update", "Delete"]; diff --git a/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs b/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs index 7c80889..bc1ecef 100644 --- a/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs +++ b/src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs @@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using SolutionErp.Application.Contracts.Services; +using SolutionErp.Domain.ApprovalWorkflowsV2; using SolutionErp.Domain.Contracts; using SolutionErp.Domain.Forms; using SolutionErp.Domain.Identity; @@ -81,10 +82,62 @@ public static class DbInitializer await SeedDemoContractsAsync(db, userManager, codeGen, logger); await SeedDemoPurchaseEvaluationsAsync(db, userManager, logger); + await SeedSampleApprovalWorkflowsV2Async(db, userManager, logger); await WarnDefaultAdminPasswordAsync(userManager, logger); } + // Seed sample workflow V2 cho ApplicableType=DuyetNccPhuongAn (B), giúp UAT + // type B nhanh không cần admin tạo qua Designer trước. Idempotent — skip nếu + // đã có ANY workflow B (admin đã tạo) HOẶC nếu thiếu test user / phòng CCM. + // KHÔNG seed cho A (admin đã tạo + chốt qua Designer S17 — không clobber). + private static async Task SeedSampleApprovalWorkflowsV2Async( + ApplicationDbContext db, UserManager userManager, ILogger logger) + { + var hasAnyB = await db.ApprovalWorkflows + .AnyAsync(w => w.ApplicableType == ApprovalWorkflowApplicableType.DuyetNccPhuongAn); + if (hasAnyB) return; + + var testUser = await userManager.FindByEmailAsync("nv.test@solutions.com.vn"); + if (testUser is null) + { + logger.LogWarning("SeedSampleApprovalWorkflowsV2Async: skip — test user nv.test@solutions.com.vn not found"); + return; + } + + var ccmDept = await db.Departments.FirstOrDefaultAsync(d => d.Code == "CCM"); + + var wf = new ApprovalWorkflow + { + Code = "QT-DN-PA-V2-001", + Version = 1, + ApplicableType = ApprovalWorkflowApplicableType.DuyetNccPhuongAn, + Name = "Quy trình duyệt NCC và Giải pháp (mẫu UAT)", + Description = "Sample seed cho UAT B — 1 Bước Phòng CCM × 1 Cấp NV test. Admin có thể clone tạo version mới qua Designer.", + IsActive = true, + ActivatedAt = DateTime.UtcNow, + }; + var step = new ApprovalWorkflowStep + { + ApprovalWorkflow = wf, + Order = 1, + Name = "Phòng CCM", + DepartmentId = ccmDept?.Id, + }; + var level = new ApprovalWorkflowLevel + { + Step = step, + Order = 1, + Name = "Cấp 1", + ApproverUserId = testUser.Id, + }; + wf.Steps.Add(step); + step.Levels.Add(level); + db.ApprovalWorkflows.Add(wf); + await db.SaveChangesAsync(); + logger.LogInformation("Seeded sample ApprovalWorkflow V2 for DuyetNccPhuongAn: QT-DN-PA-V2-001 v01"); + } + // Seed 4 master catalogs với defaults cho user nhập liệu Details. Idempotent: // skip per-table nếu đã có row (admin có thể đã thêm/sửa — không clobber). private static async Task SeedCatalogsAsync(ApplicationDbContext db, ILogger logger) @@ -1310,8 +1363,9 @@ public static class DbInitializer (MenuKeys.PeWorkflows, "Quy trình Duyệt NCC", MenuKeys.System, 95, "GitCompareArrows"), // Quy trình duyệt MỚI (Mig 22 — Session 17, 2026-05-08): schema riêng // UAT trước khi migrate hoàn toàn. Cấu trúc: Quy trình > Bước (Phòng) > Cấp (NV cụ thể). - (MenuKeys.ApprovalWorkflowsV2, "Quy trình duyệt (Mới)", MenuKeys.System, 96, "Workflow"), - (MenuKeys.ApprovalWorkflowDuyetNccV2, "Duyệt NCC (Mới)", MenuKeys.ApprovalWorkflowsV2, 1, "FileCheck"), + (MenuKeys.ApprovalWorkflowsV2, "Quy trình duyệt (Mới)", MenuKeys.System, 96, "Workflow"), + (MenuKeys.ApprovalWorkflowDuyetNccV2, "Duyệt NCC (Mới)", MenuKeys.ApprovalWorkflowsV2, 1, "FileCheck"), + (MenuKeys.ApprovalWorkflowDuyetNccPhuongAnV2, "Duyệt NCC và Giải pháp (Mới)", MenuKeys.ApprovalWorkflowsV2, 2, "FileCheck"), // Module Ngân sách (Phase 7) (MenuKeys.Budgets, "Ngân sách", null, 27, "Wallet"), (MenuKeys.BudgetList, "Danh sách", MenuKeys.Budgets, 1, "List"),