[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:
@ -78,8 +78,20 @@ public class ApprovalWorkflowStep : BaseEntity
|
||||
public List<ApprovalWorkflowLevel> Levels { get; set; } = new();
|
||||
}
|
||||
|
||||
// Cấp = 1 NV cụ thể. 1 bước có nhiều cấp theo Order. Approver = ApproverUserId
|
||||
// chính xác (KHÔNG OR-of-many). Sequential trong cùng bước: cấp 1 → cấp 2 → ...
|
||||
// Cấp = tập các row CÙNG Order trong 1 Bước. MỖI ROW = 1 NV cụ thể
|
||||
// (ApproverUserId), nhưng 1 Cấp có thể có N row ⇒ N người duyệt **OR-of-N**:
|
||||
// bất kỳ ai trong Cấp duyệt là Cấp đó xong. Sequential giữa các Cấp trong cùng
|
||||
// bước: cấp 1 → cấp 2 → ...
|
||||
//
|
||||
// [F-10 S155 2026-07-27] Comment cũ ghi "Cấp = 1 NV cụ thể ... (KHÔNG OR-of-many)"
|
||||
// — SAI, ngược với mã lẫn tài liệu. Bằng chứng: service group Levels theo Order
|
||||
// rồi cho phép BẤT KỲ ai trong nhóm duyệt
|
||||
// (`PurchaseEvaluationWorkflowService.cs:689` `GroupBy(l => l.Order)` + `:702`
|
||||
// `allowedUserIds.Contains(actorUserId)`); validator chỉ cấm TRÙNG cặp
|
||||
// {Order, ApproverUserId} chứ không cấm nhiều row cùng Order
|
||||
// (`ApprovalWorkflowV2AdminFeatures.cs:309-314`); CLAUDE.md + skill
|
||||
// contract-workflow đều ghi "N NV cụ thể (OR-of-N cùng cấp)". Ảnh UAT prod:
|
||||
// Cấp 2 Phòng Cung ứng có 3 người.
|
||||
public class ApprovalWorkflowLevel : BaseEntity
|
||||
{
|
||||
public Guid ApprovalWorkflowStepId { get; set; }
|
||||
@ -141,5 +153,20 @@ public class ApprovalWorkflowLevel : BaseEntity
|
||||
/// nhất, KHÔNG threshold/role check). Mirror F2/F3/F4 admin opt-in per-slot pattern.
|
||||
public bool AllowApproverFinalize { get; set; }
|
||||
|
||||
/// F6 (Mig 68 2026-07-27 — S155, UAT Tra Sol/anh Kiệt) — Cho phép NV slot này,
|
||||
/// khi đang tới lượt duyệt của mình, XÓA MỀM phiếu đang treo ở ChoDuyet. Sinh ra
|
||||
/// vì phiếu bấm sai gói thầu đang **ăn lũy kế** ngân sách hạng mục sai mà không
|
||||
/// có cửa nào dừng: "Trả lại" chỉ DỜI số sang dòng khác chứ không triệt tiêu
|
||||
/// (`PeBudgetAccumulator.cs:104-126`), còn xóa thì allow-list chỉ nhận
|
||||
/// {DangSoanThao, TuChoi} (`PurchaseEvaluationFeatures.cs:1404-1406`).
|
||||
/// Default false (admin opt-in per slot). Đọc **PER-ROW** `matchingLevel.
|
||||
/// AllowApproverDelete` (khuôn F5 `PurchaseEvaluationWorkflowService.cs:859`),
|
||||
/// KHÔNG đọc per-Cấp `g.Any(...)` — 1 Cấp có N người (OR-of-N), đọc `Any` sẽ
|
||||
/// phát quyền huỷ chứng-từ cho CẢ Cấp thay vì đúng 1 người admin chỉ đích danh
|
||||
/// (owner chốt 2026-07-27). Mirror F2/F3/F4/F5 admin opt-in per-slot pattern.
|
||||
/// ⚠️ Cờ này chỉ là 1 trong 3 rào: policy `PurchaseEvaluations.Delete` ∧ đúng
|
||||
/// lượt ∧ F6 — xem hạng mục B spec S155 (đợt 2).
|
||||
public bool AllowApproverDelete { get; set; }
|
||||
|
||||
public ApprovalWorkflowStep? Step { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user