Files
solution-erp/.claude/workflows/runs/2026-07-29-S161-khkk-w6-duongong/sub-test-specialist-0.md
2026-07-29 23:15:44 +07:00

5.6 KiB
Raw Blame History

sub-test-specialist-0 — W6 ĐỢT-2: 5 test PIN đường ống HĐ V2 (+2 bonus)

Run: 2026-07-29-S161-khkk-w6-duongong · Spec: .claude/workflows/runs/2026-07-29-S160-khkk-dryrun-plan/spec-wave-w6-duong-ong-hd-v2-29-07-2026.md §③-B Luật lượt này: CHỈ tests/** · KHÔNG sửa production · KHÔNG commit/push · ghi TỪNG MỤC trong lúc làm (chống #53).


§0 — ĐO TRƯỚC KHI VIẾT (baseline tươi, KHÔNG tin số đề bài)

Lệnh: dotnet test SolutionErp.slnx --nologo --verbosity minimal -p:BuildInParallel=false -maxcpucount:1

Project Passed Failed Skipped
SolutionErp.Domain.Tests 45 0 0
SolutionErp.Infrastructure.Tests 535 0 0
TỔNG 580 0 0

⇒ Đề bài ghi 580 (45D+535I) — KHỚP 3/3 con số. Đích ≥ 585.


§1 — ĐỌC CODE THẬT (test theo CODE, không theo prompt)

Diff production của đợt-1 (git diff HEAD, 2 file, +161/-10):

Điểm sửa Vị trí đo tươi Nội dung
List — vế V2 + bản-cứng ContractFeatures.cs:305-314 myWorkflowIds.Contains(x.c.ApprovalWorkflowId) + Phase != DangSoanThao · isHardCopyActor && Phase == DaPhatHanh
Helper per-HĐ :375-395 HardCopyActorRoles = [Director, AuthorizedSigner, HrAdmin, CostControl] · ResolveUserApprovalWorkflowIdsAsync trả List<Guid?>
ListDeleted — CỐ Ý KHÔNG ghép :426-431 chú thích tường minh: giữ Drafter eligible-phase
Inbox — admin phase tường minh :487-497 AdminInboxPhases = 7 legacy + ChoDuyet
Inbox — v2InboxIds + early-exit :514-527 eligiblePhases.Count == 0 && v2InboxIds.Count == 0 (2 nguồn) · `where …
Inbox — resolve con-trỏ :543-577 in-memory join, steps[idx] theo INDEX (không phải Order), Levels.Any(l => l.Order == cur && l.ApproverUserId == uid)
Detail — vế V2 per-HĐ :605-621 isV2Approver hỏi theo c.ApprovalWorkflowId · isDraftPhase (S89) · isHardCopyActor && Phase == DaPhatHanh
Guard trình ContractWorkflowService.cs:73-92 +Procurement · isCreator = actorUserId is Guid actorId && (CreatedBy == actorId DrafterUserId == actorId)

3 bẫy rút từ CODE — quyết định thiết kế test:

  1. CurrentWorkflowStepIndexINDEX vào list sort theo Order, KHÔNG phải Order (:569-571 steps[idx]). ⇒ mọi seed workflow đa-Bước dùng Step.Order = 5/15 để index 0/1 không thể trùng Order do may mắn.
  2. CostControl VỪA là hard-copy actor (:376) VỪA có eligible-phase legacy {DangGopY, DangKiemTraCCM} (:359) ⇒ dùng CostControl làm ca ÂM ở phase ChoDuyet là ca mạnh nhất: nó chứng vế bản-cứng bị chặn theo phase (&& Phase == DaPhatHanh), không phải role-blanket.
  3. Trap CreatedBy: actorUserId is Guid là thứ duy nhất chặn null == null khi actor null + CreatedBy null + decision=Approve (KHÔNG phải AutoApprove, nên isSystem=false). TestApplicationDbContext không wire AuditingInterceptor ⇒ HĐ seed có CreatedBy == null tự nhiên — đúng cấu hình để đo trap này.

§2 — 7 test đã viết + lượt chạy lọc ĐẦU TIÊN

File MỚI (duy nhất tao ghi trong tests/): tests/SolutionErp.Infrastructure.Tests/Application/ContractV2PipelineTests.cs

# Tên Loại
T1 Inbox_PendingLevelApprover_SeesChoDuyetContract PIN spec
T2 Inbox_OtherLevel_DoesNotSeeContract PIN spec (ÂM)
T3 View_V2Approver_NotDrafter_CanSeeChoDuyetContract PIN spec
T4 List_HardCopyActor_NotAdmin_SeesDaPhatHanhContract PIN spec (+ khối XÓA MỀM §③-B :31)
T5 View_UserOutsideWorkflow_WithUnrelatedRole_Gets403 PIN spec (ÂM, role pin CostControl+Procurement)
T6 Inbox_Admin_SeesChoDuyetContract BONUS (DR-4 / F-B13)
T7 Submit_ProcurementAndCreator_Allowed_UnrelatedRoleAndNullActor_Forbidden BONUS (guard trình + bẫy actor-null)

Lỗi biên dịch duy nhất: thiếu using SolutionErp.Application.Contracts.Dtos; (DTO nằm namespace .Dtos, không phải .Contracts) → vá 1 dòng.

Chạy lọc --filter FullyQualifiedName~ContractV2PipelineTests: Failed: 0, Passed: 7, Total: 7 (4 s).


§3 — CHỨNG LƯỚI CÓ RĂNG (fault-inject: hoàn nguyên production tạm thời)

⚠️ Test-after xanh ngay lượt đầu KHÔNG chứng được gì. Phải đo: 7 lưới này có ĐỎ dưới mã TRƯỚC W6 không (khuôn RED-proven-via-git-stash, S86).

🔴 AN TOÀN / KHÔI PHỤC — đọc mục này TRƯỚC nếu tao chết giữa chừng (#53): bản W6 của 2 file production được sao lưu 2 LỚP trước khi hoàn nguyên:

  • Lớp 1 — scratchpad: C:\Users\pqhuy\AppData\Local\Temp\claude\D--Dropbox-CONG-VIEC-SOLUTION-SOLUTION-ERP\24be4c29-c54d-4ed0-ba2a-8240f62de712\scratchpad\w6-backup\ (ContractFeatures.cs + ContractWorkflowService.cs)
  • Lớp 2 — git stash (git tự giữ, xem git stash list).

MD5 bản W6 ĐÚNG (đích của phép khôi phục):

c11e3820267019995bd9ed815eac483f  src/Backend/SolutionErp.Application/Contracts/ContractFeatures.cs
d564219fc9c5cb0857298ee97f6037b5  src/Backend/SolutionErp.Infrastructure/Services/ContractWorkflowService.cs

Khôi phục = git stash pop (hoặc chép đè từ scratchpad) rồi đối chiếu lại 2 MD5 trêngit diff --stat phải ra lại 142 + / 15 + = 161 insertions(+), 10 deletions(-).