[CLAUDE] PurchaseEvaluation: go han hanh dong "Tu choi" - chi con Duyet hoac Tra lai (UAT anh Kiet S60 14:14)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m30s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m30s
- Domain policy: xoa MOI transition -> TuChoi o ca 4 policy (NccOnly + NccWithPlan + ForV2Schema + FromDefinition) -> NextPhases het tra TuChoi, nut FE tu bien mat - Service guard S60: chan targetPhase=TuChoi moi caller ke ca Admin (dung truoc moi branch — spec bo han, khong escape hatch); message huong dan dung Tra lai / Xoa nhap - FE x2 app: filter phong thu next.filter(p != TuChoi) PeWorkflowPanel (SHA256 identical); dialog/isCancel giu dead-safe de flip lai de - Enum TuChoi + phieu TuChoi cu + tab filter "Tu choi" GIU display (data cu render binh thuong) - SlaExpiryJob chi dung Contract — PE khong auto-TuChoi, khong anh huong - Tests spec-change cung commit: Domain flip BothPolicies_TuChoi_RemovedFromAllTransitions_S60 + NEW V2SchemaPolicy fact; Infra NEW TargetTuChoi_WithRejectDecision_Throws_TuChoiRemoved_S60 (guard #45 test cu giu nguyen PASS — van dung truoc) - Test 254 -> 256 PASS (59 Domain + 197 Infra) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@ -121,6 +121,37 @@ public class PurchaseEvaluationWorkflowServiceGuardTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TransitionAsync_TargetTuChoi_WithRejectDecision_Throws_TuChoiRemoved_S60()
|
||||
{
|
||||
// UAT S60 (anh Kiệt 14:14): "bỏ luôn nút Từ chối — Duyệt hoặc Trả về
|
||||
// thôi". Payload TuChoi + decision=Reject (hợp lệ THEO SPEC CŨ) giờ bị
|
||||
// guard S60 chặn hẳn — TuChoi hết đường vào từ transition API (guard
|
||||
// #45 decision-mismatch vẫn đứng trước cover nhánh TuChoi+Approve).
|
||||
var (svc, fix, db) = CreateService();
|
||||
using (fix)
|
||||
{
|
||||
var pe = BuildPeInChoDuyet("PE-GUARD-004");
|
||||
db.PurchaseEvaluations.Add(pe);
|
||||
await db.SaveChangesAsync(CancellationToken.None);
|
||||
|
||||
var act = async () => await svc.TransitionAsync(
|
||||
evaluation: pe,
|
||||
targetPhase: PurchaseEvaluationPhase.TuChoi,
|
||||
actorUserId: Guid.NewGuid(),
|
||||
actorRoles: new[] { AppRoles.CostControl },
|
||||
decision: ApprovalDecision.Reject,
|
||||
comment: "test tu choi removed S60",
|
||||
ct: CancellationToken.None);
|
||||
|
||||
await act.Should().ThrowAsync<ConflictException>()
|
||||
.WithMessage("*Từ chối*đã được gỡ*");
|
||||
|
||||
pe.Phase.Should().Be(PurchaseEvaluationPhase.ChoDuyet,
|
||||
"Guard chặn trước khi mutate — phiếu giữ nguyên ChoDuyet");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TransitionAsync_TargetTraLai_WithRejectDecision_SetsPhaseTraLai()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user