[CLAUDE] Infra · Scripts: xóa hết User test khỏi prod (38) + gỡ seed — chỉ giữ 17 User Solutions thật
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m51s

anh Kiệt FDC: "Xóa hết các User test ko liên quan, lấy User Solution thật vào".
Recon prod: 55 user → GIỮ 17 (admin + 16 real) → XÓA 38 (37 test rõ + 1 typo
chuong.phan@solution.com.vn — anh chốt xóa, anh Chương dùng bản @solutions).
An toàn FK: KHÔNG user test nào là ApproverUserId (NO_ACTION không bị chặn — recon verified);
5 bảng con CASCADE (EmployeeProfiles/UserRoles/Claims/Logins/Tokens); nv.test 1 PE loose-Guid xóa kèm.

- DbInitializer: gỡ 16 user mẫu khỏi SeedDemoUsersAsync + gỡ LockDemoSampleUsersAsync (call+method).
  Seed giờ chỉ tạo/reconcile 17 user thật. SeedItDepartmentStaff + sample-workflow seeds null-guard
  (skip user đã xóa) → deploy KHÔNG resurrect/crash. ⚠ PHẢI deploy để binary mới không tái tạo test.
- scripts/s89-delete-test-users.sql: whitelist-keep 17 + BACKUP + XACT_ABORT + count-guard[30,45].
  ĐÃ CHẠY prod (backup SolutionErp_S89_preuserdelete.bak): count=38, PE=1, còn đúng 17 user. Build slnx xanh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-06-25 16:25:00 +07:00
parent fef4c33527
commit 681b1edc7e
2 changed files with 88 additions and 68 deletions

View File

@ -92,10 +92,9 @@ public static class DbInitializer
// cho round-robin auto-assign ticket. PHẢI sau SeedDemoUsersAsync (reconcile dept
// trước → method này override về IT). Infrastructure data (NOT gated DemoSeed).
await SeedItDepartmentStaffAsync(db, userManager, logger);
// [S57bis 2026-06-11] Khóa 14 demo sample user (sếp yêu cầu clear dữ liệu cũ —
// anh chốt scope CHỈ user). PHẢI sau SeedDemoUsers + SeedItDepartmentStaff
// (chạy sau cùng mỗi startup → khóa BỀN, seed fix-drift không resurrect được).
await LockDemoSampleUsersAsync(userManager, logger);
// [S89 2026-06-25 — anh Kiệt FDC chốt] LockDemoSampleUsersAsync ĐÃ GỠ: 16 user mẫu +
// ~21 user UAT-matrix đã XÓA hẳn khỏi prod (scripts/s89-delete-test-users.sql) + gỡ khỏi
// SeedDemoUsersAsync → không còn user test để khóa (S57bis lock thay bằng xóa thật).
// Plan B G-H1 (Mig 34 S33 2026-05-26) — seed EmployeeProfile 1-1 với
// mọi user @solutions.com.vn. Idempotent. NOT gated DemoSeed flag
// (infrastructure data, mirror Mig 32 SeedSampleContractWorkflowV2
@ -1542,47 +1541,10 @@ public static class DbInitializer
// - chuong.phan@solution.com.vn (domain thiếu 's', không trong seed): typo-dup của bản
// @solutions nhưng có thể là login thật anh Chương đang dùng — giữ, xác nhận rồi dọn sau.
// Muốn mở lại 1 user có chủ đích → gỡ email khỏi list này + admin re-activate.
private static async Task LockDemoSampleUsersAsync(
UserManager<User> userManager, ILogger logger)
{
string[] emails =
[
// Population Dev — named-person sample seed (16 trừ nv.cao/nv.truong)
"bod.huynh@solutions.com.vn", "bod.le@solutions.com.vn", "bod.tran@solutions.com.vn",
"pm.nguyen@solutions.com.vn", "pm.le@solutions.com.vn",
"ccm.tran@solutions.com.vn", "pro.pham@solutions.com.vn", "fin.do@solutions.com.vn",
"act.vu@solutions.com.vn", "equ.bui@solutions.com.vn", "hra.dang@solutions.com.vn",
"qs.hoang@solutions.com.vn", "qs.ngo@solutions.com.vn", "nv.dinh@solutions.com.vn",
// Population prod — UAT-matrix tạo tay 2026-05-13 (S58)
"act.nv@solutions.com.vn", "act.pp@solutions.com.vn", "act.tp@solutions.com.vn",
"bod.1@solutions.com.vn", "bod.2@solutions.com.vn",
"equ.nv@solutions.com.vn", "equ.pp@solutions.com.vn", "equ.tp@solutions.com.vn",
"fin.nv@solutions.com.vn", "fin.pp@solutions.com.vn", "fin.tp@solutions.com.vn",
"hra.nv@solutions.com.vn", "hra.pp@solutions.com.vn", "hra.tp@solutions.com.vn",
"pm.nv@solutions.com.vn", "pm.pp@solutions.com.vn", "pm.tp@solutions.com.vn",
"qs.nv@solutions.com.vn", "qs.pp@solutions.com.vn", "qs.tp@solutions.com.vn",
];
var locked = 0;
foreach (var email in emails)
{
var user = await userManager.FindByEmailAsync(email);
if (user is null) continue;
if (!user.IsActive && user.LockoutEnd == DateTimeOffset.MaxValue) continue; // đã khóa — idempotent skip
user.IsActive = false;
user.LockoutEnabled = true;
user.LockoutEnd = DateTimeOffset.MaxValue;
await userManager.UpdateAsync(user);
// Rotate SecurityStamp → vô hiệu refresh-token flow của account bị khóa
// (JWT đang sống tự hết hạn ≤1h theo expiry).
await userManager.UpdateSecurityStampAsync(user);
locked++;
}
if (locked > 0)
logger.LogInformation("Locked {Count} demo sample users (S57bis clear-old-data)", locked);
}
// [S89 2026-06-25 — anh Kiệt FDC] LockDemoSampleUsersAsync ĐÃ XÓA: 16 user mẫu + ~21 user
// UAT-matrix được XÓA HẲN khỏi prod (scripts/s89-delete-test-users.sql, backup trước) + gỡ
// khỏi SeedDemoUsersAsync. S57bis "khóa demo sample" thay bằng "xóa thật" — chỉ còn 17 user
// Solutions thật (admin + 16 real). Không còn user test để khóa.
private static async Task SeedDemoUsersAsync(
ApplicationDbContext db, UserManager<User> userManager, ILogger logger)
@ -1600,29 +1562,11 @@ public static class DbInitializer
var demoUsers = new[]
{
// (Email, FullName, DeptCode, Position, RoleNames[])
// BOD (3) — director + signer + admin assistant
("bod.huynh@solutions.com.vn", "Huỳnh Văn Hùng", "BOD", "Tổng Giám đốc", new[] { AppRoles.Director }),
("bod.le@solutions.com.vn", "Lê Thị Mai", "BOD", "Phó Giám đốc (NĐUQ)", new[] { AppRoles.AuthorizedSigner }),
("bod.tran@solutions.com.vn", "Trần Quốc Bảo", "BOD", "Phó Giám đốc Kỹ thuật (NĐUQ)", new[] { AppRoles.AuthorizedSigner }),
// PM (2) — giám đốc dự án
("pm.nguyen@solutions.com.vn", "Nguyễn Quốc Cường", "PM", "Giám đốc Dự án FLOCK 01", new[] { AppRoles.ProjectManager }),
("pm.le@solutions.com.vn", "Lê Thanh Tùng", "PM", "Giám đốc Dự án Vinhomes Ocean Park", new[] { AppRoles.ProjectManager }),
// CCM/PRO/FIN/ACT/EQU/HRA — Trưởng phòng các phòng ban (1 mỗi)
("ccm.tran@solutions.com.vn", "Trần Văn Bình", "CCM", "Trưởng phòng Kiểm soát chi phí", new[] { AppRoles.CostControl, AppRoles.DeptManager }),
("pro.pham@solutions.com.vn", "Phạm Thị Hồng", "PRO", "Trưởng phòng Cung ứng", new[] { AppRoles.Procurement, AppRoles.DeptManager }),
("fin.do@solutions.com.vn", "Đỗ Minh Tuấn", "FIN", "Trưởng phòng Tài chính", new[] { AppRoles.Finance, AppRoles.DeptManager }),
("act.vu@solutions.com.vn", "Vũ Thị Lan", "ACT", "Kế toán trưởng", new[] { AppRoles.Accounting, AppRoles.DeptManager }),
("equ.bui@solutions.com.vn", "Bùi Văn Khánh", "EQU", "Trưởng phòng Thiết bị", new[] { AppRoles.Equipment, AppRoles.DeptManager }),
("hra.dang@solutions.com.vn", "Đặng Thị Thanh", "HRA", "Trưởng phòng Nhân sự - Hành chính", new[] { AppRoles.HrAdmin, AppRoles.DeptManager }),
// Drafter (5) — soạn thảo HĐ ở các phòng khác nhau
("qs.hoang@solutions.com.vn", "Hoàng Văn Đức", "QS", "QS công trường — soạn thảo HĐ", new[] { AppRoles.Drafter }),
("qs.ngo@solutions.com.vn", "Ngô Thị Hà", "QS", "QS dự án FLOCK 01", new[] { AppRoles.Drafter }),
("nv.cao@solutions.com.vn", "Cao Văn Long", "PRO", "Nhân viên Cung ứng", new[] { AppRoles.Drafter }),
("nv.dinh@solutions.com.vn", "Đinh Thị Yến", "FIN", "Nhân viên Tài chính", new[] { AppRoles.Drafter }),
("nv.truong@solutions.com.vn", "Trương Minh Quân", "CCM", "Nhân viên Kiểm soát chi phí", new[] { AppRoles.Drafter }),
// [S89 2026-06-25 — anh Kiệt FDC chốt] ĐÃ GỠ 16 user MẪU TEST (tên giả: bod.huynh/le/
// tran · pm.nguyen/le · ccm.tran · pro.pham · fin.do · act.vu · equ.bui · hra.dang ·
// qs.hoang/ngo · nv.cao/dinh/truong) — chỉ giữ user Solutions THẬT bên dưới. Đã xóa
// khỏi prod qua scripts/s89-delete-test-users.sql (kèm ~21 user UAT-matrix tạo tay).
// LockDemoSampleUsersAsync cũng đã gỡ (không còn user test để khóa).
// ===== Solutions company users (real names — added 2026-04-25) =====
// PRO — Phòng Cung ứng (5 user)