[CLAUDE] PE: rename menu + workflow Phuong An -> Giai phap
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m27s

User request session 3 mở đầu: đổi label menu:
  'Quy trình Duyệt NCC - Phương Án' -> 'Duyệt NCC và Giải pháp'
  'Quy trình Duyệt NCC' -> 'Duyệt NCC' (bỏ prefix 'Quy trình')

Giữ nguyên (không breaking):
  - Enum value PurchaseEvaluationType.DuyetNccPhuongAn = 2
  - Menu key Pe_DuyetNccPhuongAn_* (FK ref)
  - typeCode string 'DuyetNccPhuongAn' (URL routing)
  - Policy name 'NccWithPlan' + WorkflowDefinition.Code QT-DN-B

Changed (display-only):
  - DbInitializer SeedMenuTreeAsync peTypeLabels: 2 entry
  - DbInitializer SeedPurchaseEvaluationWorkflowsAsync WF name B
  - PurchaseEvaluationPolicy.cs NccWithPlan Description
  - fe-admin + fe-user types PurchaseEvaluationTypeLabel[2]

Backfill existing DB (seed idempotent skip-if-exists không update):
  - MenuItems Pe_DuyetNcc group + Pe_DuyetNccPhuongAn group + PeWf_* leaf
    → UPDATE Label nếu khác expected
  - WorkflowDefinitions QT-DN-B v01 → UPDATE Name Replace 'Phương Án' → 'và Giải pháp'
  Run mỗi start API — idempotent, fast no-op sau lần đầu.
This commit is contained in:
pqhuy1987
2026-04-24 10:43:26 +07:00
parent de1ddc233d
commit 7ee105df12
4 changed files with 41 additions and 6 deletions

View File

@ -8,7 +8,7 @@ export type PurchaseEvaluationType = typeof PurchaseEvaluationType[keyof typeof
export const PurchaseEvaluationTypeLabel: Record<number, string> = { export const PurchaseEvaluationTypeLabel: Record<number, string> = {
1: 'Duyệt NCC', 1: 'Duyệt NCC',
2: 'Duyệt NCC - Phương án', 2: 'Duyệt NCC và Giải pháp',
} }
export const PurchaseEvaluationTypeCode: Record<number, string> = { export const PurchaseEvaluationTypeCode: Record<number, string> = {

View File

@ -8,7 +8,7 @@ export type PurchaseEvaluationType = typeof PurchaseEvaluationType[keyof typeof
export const PurchaseEvaluationTypeLabel: Record<number, string> = { export const PurchaseEvaluationTypeLabel: Record<number, string> = {
1: 'Duyệt NCC', 1: 'Duyệt NCC',
2: 'Duyệt NCC - Phương án', 2: 'Duyệt NCC và Giải pháp',
} }
export const PurchaseEvaluationTypeCode: Record<number, string> = { export const PurchaseEvaluationTypeCode: Record<number, string> = {

View File

@ -79,7 +79,7 @@ public static class PurchaseEvaluationPolicies
// B — DuyetNccPhuongAn (5 step thực + Drafter): Drafter → Purchasing → Dự án → CCM → CEO(PA) → CEO(NCC) // B — DuyetNccPhuongAn (5 step thực + Drafter): Drafter → Purchasing → Dự án → CCM → CEO(PA) → CEO(NCC)
public static readonly PurchaseEvaluationPolicy NccWithPlan = new( public static readonly PurchaseEvaluationPolicy NccWithPlan = new(
Name: "NccWithPlan", Name: "NccWithPlan",
Description: "Duyệt NCC + Phương án — 5 step (Purchasing → Dự án → CCM → CEO duyệt PA → CEO duyệt NCC).", Description: "Duyệt NCC và Giải pháp — 5 step (Purchasing → Dự án → CCM → CEO duyệt Giải pháp → CEO duyệt NCC).",
Transitions: new Dictionary<(PurchaseEvaluationPhase, PurchaseEvaluationPhase), string[]> Transitions: new Dictionary<(PurchaseEvaluationPhase, PurchaseEvaluationPhase), string[]>
{ {
[(PurchaseEvaluationPhase.DangSoanThao, PurchaseEvaluationPhase.ChoPurchasing)] = [AppRoles.Drafter, AppRoles.DeptManager], [(PurchaseEvaluationPhase.DangSoanThao, PurchaseEvaluationPhase.ChoPurchasing)] = [AppRoles.Drafter, AppRoles.DeptManager],

View File

@ -328,7 +328,7 @@ public static class DbInitializer
var typeLabels = new Dictionary<PurchaseEvaluationType, (string Code, string Name)> var typeLabels = new Dictionary<PurchaseEvaluationType, (string Code, string Name)>
{ {
[PurchaseEvaluationType.DuyetNcc] = ("QT-DN-A", "Quy trình Duyệt NCC"), [PurchaseEvaluationType.DuyetNcc] = ("QT-DN-A", "Quy trình Duyệt NCC"),
[PurchaseEvaluationType.DuyetNccPhuongAn] = ("QT-DN-B", "Quy trình Duyệt NCC - Phương Án"), [PurchaseEvaluationType.DuyetNccPhuongAn] = ("QT-DN-B", "Quy trình Duyệt NCC và Giải pháp"),
}; };
var phaseNames = new Dictionary<PurchaseEvaluationPhase, string> var phaseNames = new Dictionary<PurchaseEvaluationPhase, string>
@ -1278,8 +1278,8 @@ public static class DbInitializer
// Pe_* group per PurchaseEvaluationType + 3 action leaves each // Pe_* group per PurchaseEvaluationType + 3 action leaves each
var peTypeLabels = new Dictionary<string, string> var peTypeLabels = new Dictionary<string, string>
{ {
["DuyetNcc"] = "Quy trình Duyệt NCC", ["DuyetNcc"] = "Duyệt NCC",
["DuyetNccPhuongAn"] = "Quy trình Duyệt NCC - Phương Án", ["DuyetNccPhuongAn"] = "Duyệt NCC và Giải pháp",
}; };
var peOrder = 1; var peOrder = 1;
foreach (var code in MenuKeys.PurchaseEvaluationTypeCodes) foreach (var code in MenuKeys.PurchaseEvaluationTypeCodes)
@ -1312,6 +1312,41 @@ public static class DbInitializer
await db.SaveChangesAsync(); await db.SaveChangesAsync();
logger.LogInformation("Seeded {Count} menu items", added); logger.LogInformation("Seeded {Count} menu items", added);
} }
// Backfill label updates for menu items renamed via business changes.
// Add new entries here khi có rename — key → expected label. Idempotent.
var labelBackfill = new Dictionary<string, string>
{
[MenuKeys.PurchaseEvaluationGroup("DuyetNcc")] = "Duyệt NCC",
[MenuKeys.PurchaseEvaluationGroup("DuyetNccPhuongAn")] = "Duyệt NCC và Giải pháp",
[MenuKeys.PeWorkflowTypeLeaf("DuyetNcc")] = "Duyệt NCC",
[MenuKeys.PeWorkflowTypeLeaf("DuyetNccPhuongAn")] = "Duyệt NCC và Giải pháp",
};
var updatedLabels = 0;
foreach (var (key, expectedLabel) in labelBackfill)
{
var item = await db.MenuItems.FirstOrDefaultAsync(m => m.Key == key);
if (item != null && item.Label != expectedLabel)
{
item.Label = expectedLabel;
updatedLabels++;
}
}
if (updatedLabels > 0)
{
await db.SaveChangesAsync();
logger.LogInformation("Backfilled {Count} menu labels", updatedLabels);
}
// Backfill WorkflowDefinition name cho B (Phương Án → Giải pháp rename).
var wfB = await db.PurchaseEvaluationWorkflowDefinitions
.FirstOrDefaultAsync(w => w.Code == "QT-DN-B" && w.Version == 1);
if (wfB != null && wfB.Name.Contains("Phương Án"))
{
wfB.Name = wfB.Name.Replace("Quy trình Duyệt NCC - Phương Án", "Quy trình Duyệt NCC và Giải pháp");
await db.SaveChangesAsync();
logger.LogInformation("Backfilled WorkflowDefinition QT-DN-B name");
}
} }
private static async Task SeedAdminPermissionsAsync(ApplicationDbContext db, RoleManager<Role> roleManager, ILogger logger) private static async Task SeedAdminPermissionsAsync(ApplicationDbContext db, RoleManager<Role> roleManager, ILogger logger)