[CLAUDE] Workflow: sua quy trinh duyet TAI CHO + co F6 AllowApproverDelete (dot 1)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m31s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m31s
Nen cho tinh nang "xoa phieu PE o man duyet" (UAT: phieu bam sai goi thau dang
an luy ke). Dot 1 lam NEN, dot 2 moi lam nut xoa.
Vi sao phai lam nen truoc: phieu dang chay pin ApprovalWorkflowId va doc workflow
SONG theo Id do. Moi POST tao workflow moi = Id MOI, nen tick co tren ban moi
KHONG BAO GIO toi duoc phieu dang treo. Phai co lenh sua-tai-cho giu nguyen Id.
- Domain: ApprovalWorkflowLevel + AllowApproverDelete (F6, per-NGUOI) + Mig
20260727033522_AddPeAllowApproverDelete (AddColumn bit default false, no new table)
- Application: UpdateAwDefinitionCommand + Validator + Handler
- 2 phep thu: (T1) khung khong doi - Order tung row bat bien
(T2) luat choi khong doi - cam CeoApprovalThreshold, AllowApproverFinalize,
Code, ApplicableType => 409 bao tao ban moi
- diff theo Level.Id (CAM delete-then-insert: no FK Restrict + mo coi LevelOpinion)
- guard 2 tang chu ky: tang 1 chu ky tren ho so CON SONG; tang 2 chu ky CON LUU
(cha xoa mem hoac opinion xoa mem) - ca hai deu CHAN, khong xoa cung
- purge chi khi ho so cha KHONG CON ROW; boc transaction (ExecuteDelete tu commit)
- KHONG tang Version, KHONG dung IsActive, KHONG doi Id
- Api: PUT /api/approval-workflows-v2/{id} + [Authorize(Policy="Workflows.Create")]
- Infra: message 403 in TEN NGUOI thay GUID tran
- FE: Designer tach "Sua tai cho" (PUT) vs "Tao phien ban moi" (POST) + o tick F6
- Tests: +21 (551 tong, 0 fail) - gom F12 chung minh phieu dang chay nhan thay doi ngay
Review: 14 FLAG, 3 HIGH da va (ExecuteDelete ngoai transaction / purge xoa cung
chu ky phieu xoa mem / endpoint khong co day FE goi toi).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@ -702,7 +702,18 @@ public class PurchaseEvaluationWorkflowService(
|
||||
var allowedUserIds = pendingLevelGroup.Select(l => l.ApproverUserId).ToHashSet();
|
||||
if (!allowedUserIds.Contains(actorUserId.Value))
|
||||
{
|
||||
var names = string.Join(", ", allowedUserIds);
|
||||
// [S155 F-6] Trước đây in THẲNG GUID (`string.Join(", ", allowedUserIds)`)
|
||||
// dù biến đã tên là `names` — người dùng cuối đọc được một dãy GUID và
|
||||
// không hiểu phải nhờ AI duyệt. Nay resolve sang tên thật; fallback về
|
||||
// GUID nếu không tra được để thông điệp không bao giờ rỗng.
|
||||
var allowedIdList = allowedUserIds.ToList();
|
||||
var resolved = await userManager.Users.AsNoTracking()
|
||||
.Where(u => allowedIdList.Contains(u.Id))
|
||||
.Select(u => u.FullName ?? u.Email)
|
||||
.ToListAsync(ct);
|
||||
var names = resolved.Count > 0
|
||||
? string.Join(", ", resolved)
|
||||
: string.Join(", ", allowedIdList);
|
||||
throw new ForbiddenException(
|
||||
$"Bước {currentIdx + 1} ({currentStep.Name}) — Cấp {currentLevelOrder}: bạn không có trong danh sách NV duyệt ({names}).");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user