[CLAUDE] PurchaseEvaluation: require quy trinh duyet V2 o create+submit (dong lo hong quy-trinh-cu)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m58s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m58s
Validator NotEmpty(ApprovalWorkflowId) + submit guard (sau Section-3, truoc mutate phase). Dong lo hong validate FE-only -> phieu null-workflow ket nhanh V1-legacy "quy trinh cu" (khong Buoc/Cap, khong route duyet). Test-before (RED confirmed): +2 validator test (PeWorkItemGuardTests) + rewrite test 7/13 PeSubmitGuardAndBypass (V1-submit deprecated, data V1 wipe S59). 356 pass (45D+311I). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -41,6 +41,12 @@ public class CreatePurchaseEvaluationCommandValidator : AbstractValidator<Create
|
||||
// async-db; mirror S43 CreateLeaveRequestHandler FK-invariant guard).
|
||||
RuleFor(x => x.WorkItemId).NotEmpty()
|
||||
.WithMessage("Phải chọn hạng mục công việc.");
|
||||
// [S83 bug fix] BE enforce quy trình duyệt V2 — đóng lỗ hổng validate
|
||||
// FE-only (FE canSubmit bắt buộc nhưng BE chỉ validate-nếu-có-truyền →
|
||||
// phiếu null-workflow lọt vào ChoDuyet = kẹt V1-legacy "quy trình cũ").
|
||||
// NotEmpty chặn cả null lẫn Guid.Empty.
|
||||
RuleFor(x => x.ApprovalWorkflowId).NotEmpty()
|
||||
.WithMessage("Phải chọn quy trình duyệt.");
|
||||
RuleFor(x => x.DiaDiem).MaximumLength(500);
|
||||
RuleFor(x => x.MoTa).MaximumLength(2000);
|
||||
// [HoSoLink] MaxLength MATCH EF config HasMaxLength(1000) (S35 lesson).
|
||||
|
||||
@ -215,6 +215,18 @@ public class PurchaseEvaluationWorkflowService(
|
||||
+ string.Join(" · ", missing) + ".");
|
||||
}
|
||||
|
||||
// [S83 bug fix] Guard require-workflow: KHÔNG cho gửi duyệt phiếu chưa
|
||||
// pin quy trình duyệt V2 (ApprovalWorkflowId null → kẹt nhánh V1-legacy:
|
||||
// không Bước/Cấp, banner "quy trình cũ", không route duyệt được). FE bắt
|
||||
// buộc lúc create (canSubmit) nhưng BE phải enforce defense-in-depth
|
||||
// (validate FE-only = lỗ hổng, họ gotcha #44). Đặt SAU Section-3
|
||||
// (orthogonal — ưu tiên báo thiếu data) NHƯNG TRƯỚC mutate phase. Data
|
||||
// V1 cũ đã wipe S59 → chặn V1-submit an toàn (mọi phiếu mới = V2).
|
||||
if (evaluation.ApprovalWorkflowId is null)
|
||||
throw new ConflictException(
|
||||
"Phiếu chưa chọn quy trình duyệt — không thể gửi duyệt. "
|
||||
+ "Vui lòng mở Sửa, chọn \"Quy trình duyệt\" rồi gửi lại.");
|
||||
|
||||
evaluation.Phase = PurchaseEvaluationPhase.ChoDuyet;
|
||||
|
||||
// Mig 31 (S23 t1 Plan K) — F2 Drafter-skip-from-Nháp semantic deprecated.
|
||||
|
||||
Reference in New Issue
Block a user