Files
solution-erp/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/sub-test-specialist-2.md
2026-07-29 22:05:53 +07:00

4.9 KiB
Raw Blame History

sub-test-specialist-2 — S161 W3 ĐỢT-2 TEST-BEFORE (6 test sàn, kỳ vọng ĐỎ)

Ghi TỪNG MỤC trong lúc làm (bài #53: chỉ thứ trên đĩa mới sống). Scope MINE: tests/SolutionErp.Infrastructure.Tests/Application/ContractSigningPlanApprovalTests.cs (file MỚI). KHÔNG chạm: src/Backend/** · fe-*/** · slnx · commit/push · MEMORY.md.

⚠️ Tên file sub-md: lệnh lead (khối LUẬT) ghi sub-test-specialist-2.md; khối RUN-TRACE boilerplate ghi sub-test-specialist-0.md. Chọn -2 vì khớp đánh số của chính run-folder này (implementer-backend-0, implementer-frontend-1) và tránh đè file (bài S133: 2 invocation cùng role + cùng index ghi đè nhau, mất trọn nội dung). Khai ở đây để lead không phải đoán.


§0 — ĐO TRƯỚC KHI GÕ (baseline TƯƠI, không tin số đề bài)

Mục đo Lệnh Kết quả
Baseline dotnet test SolutionErp.slnx --nologo -v minimal -p:BuildInParallel=false -maxcpucount:1 Domain 45/45 · Infra 529/529 · Failed 0574 — KHỚP số bàn giao
Chữ ký service IContractSigningPlanWorkflowService.cs:25-29 + ContractSigningPlanWorkflowService.cs:78-82 new ContractSigningPlanWorkflowService(db, currentUser, dateTime, notifications) · TransitionAsync(planId, action, comment, ct)
Record trả về IContractSigningPlanWorkflowService.cs:38-41 ContractSigningPlanTransitionResult(int Phase, int? CurrentWorkflowStepIndex, int? CurrentApprovalLevelOrder)Phaseint (QUYẾT-1 lane BE)
Skeleton ném gì ContractSigningPlanWorkflowService.cs:108/113/117/121 NotImplementedException("W3 đợt-3: " + action) cho cả 4 nhánh ⇒ ĐỎ THẬT
Inbox W2 (không chạm service) ContractSigningPlanFeatures.cs:725-752 + :229-264 GetMyContractSigningPlanInboxQueryHandler(db, currentUser); non-admin qua ResolveV2InboxIdsAsyncCHẠY ĐƯỢC HÔM NAY
Con-trỏ là INDEX hay Order? ContractSigningPlanFeatures.cs:256-260 steps[idx] sau OrderBy(s => s.Order)CurrentWorkflowStepIndex = INDEX 0-based, KHÔNG phải Step.Order. Mã W2 đã chốt ⇒ test được phép ép Step.Order ≠ index (xem §2 T2)
FK bắt buộc row thật ApprovalWorkflowConfiguration.cs:72-75 (Level.ApproverUserId → Users Restrict) · ContractSigningPlanConfiguration.cs:36-39 (Plan.ApprovalWorkflowId → ApprovalWorkflows Restrict) ⇒ seed PHẢI có User thật + ApprovalWorkflow thật
loose-Guid (khỏi seed) ContractSigningPlanConfiguration.cs:10-12 + ContractSigningPlan.cs:24-29 PurchaseEvaluationId / ProjectId / DepartmentId / DrafterUserId KHÔNG FK ⇒ không cần seed PE/Project/Department (khác hẳn W2)
MaKeHoach UNIQUE ContractSigningPlanConfiguration.cs:28 filtered unique ⇒ mỗi phiếu trong 1 fixture phải mã KHÁC nhau
Nguồn copy đợt-3 (để biết đo cái gì) ContractWorkflowService.cs:246 GroupBy · :255-266 OR-of-N + admin bypass · :289-316 UPSERT · :355-393 advance/terminal terminal set CẢ HAI con-trỏ = null (:380-381) ⇒ test pin null tại terminal
Stub notify có sẵn CreateContractCommandApplicableTypeTests.cs:95 NoOpNotificationServiceAppcùng namespace ...Tests.Application dùng thẳng, KHÔNG đẻ stub thứ 2

Kết luận §0: seed W3 NHẸ hơn W2 nhiều (không PE, không Supplier, không quote) — chỉ Users + ApprovalWorkflow(+Steps+Levels) + ContractSigningPlan(+Lines).


§1 — 2 quyết định hạ tầng của file test

(1) Fixture RIÊNG KhkkWorkflowFixtureAuditingInterceptor (mirror ContractSigningPlanCrudTests.cs:49-82 W2). Lý do KHÔNG dùng IdentityFixture: guard trình đợt-3 = CreatedBy == actor DeptManager AdminCreatedBy của phiếu phải là NGƯỜI THẬT. TestApplicationDbContext trần KHÔNG wire interceptor ⇒ CreatedBy sẽ là null cho mọi phiếu ⇒ nhánh CreatedBy == actor KHÔNG BAO GIỜ đúng, test submit sẽ đỏ vì lý do sai. Seed phiếu bằng context của chính người soạn ⇒ CreatedBy khớp DrafterUserId (2 đường đọc, cùng 1 giá trị — đợt-3 chọn đường nào cũng đúng).

(2) User seed THẲNG db.Users.Add(...), KHÔNG qua UserManager. Service đợt-3 lấy role từ ICurrentUser.Roles (lane BE khai QUYẾT-2: cố ý KHÔNG inject UserManager) ⇒ kéo cả Identity stack vào chỉ để có row FK là phí. Repo chưa có tiền lệ db.Users.Add trong tests (grep 0 hit) ⇒ mục này là cái mới, và nó chỉ hợp lệ vì Level.ApproverUserId cần row tồn tại, không cần đăng nhập được.


§2 — 6 test: đo gì, bẫy cài ở đâu

(điền tiếp bên dưới trong lúc viết)