diff --git a/.claude/WAL.md b/.claude/WAL.md index bf5b928b..9e4b2083 100644 --- a/.claude/WAL.md +++ b/.claude/WAL.md @@ -36,8 +36,11 @@ chain: refactor derived-state né set-state-in-effect) → ✅W3 ed3b39ff on-behalf (#53 chết đúng bước commit — artifact GHI TRỌN 10/10 ô + tự bắt ô-2a-không-răng thay bằng discriminator code-only; lead spot-check 4 phép khớp từng số) → 🔄 W5 3-worker tuần tự: - W5a test-specialist wf_2914dd19-e86 (13 Fact T-matrix chứng ĐỎ, không commit) → - W5b implementer-backend (làm xanh) → W5c implementer-frontend (nút Xóa panel ×2) → + ✅W5a RED-READY (13 Fact + pin 3 API; baseline 680 khớp; #53 chết trước chạy-đỏ — + lead xác nhận ĐỎ compile on-behalf: CS1729×2 + CS0246 + CS0117 đúng hợp-đồng) → + 🔄 W5b implementer-backend wf_a96421d7-edf (làm xanh 693 kỳ vọng; 5 nấc handler + + validator + controller reason + sửa ghost-wire ContractChangelog comment; CẤM sửa + test/CẤM policy) → W5c implementer-frontend (nút Xóa panel ×2) → lead commit MỘT phát + reviewer-gate. PUSH GOM CHỜ. DEFERRED-TO-LOCAL-VERIFY dồn: W4+W1+W2+W3 ô hành-vi — đo ④ một thể sau W5. [!] TỒN CŨ — CỬA NGOÀI-GIỜ (anh gật giờ): dọn workspace runner + dispatch verify CI · diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-b6-w5a-tests.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-b6-w5a-tests.md index c8d59f2a..ab797fea 100644 --- a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-b6-w5a-tests.md +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-b6-w5a-tests.md @@ -4,16 +4,64 @@ ## Baseline -CHƯA ĐO. +Đo TƯƠI 2026-08-12, TRƯỚC khi chạm bất kỳ file nào (Đ-9): + +``` +dotnet test SolutionErp.slnx --nologo -v q -p:BuildInParallel=false -maxcpucount:1 +Passed! - Failed: 0, Passed: 45, Total: 45 — SolutionErp.Domain.Tests.dll +Passed! - Failed: 0, Passed: 635, Total: 635 — SolutionErp.Infrastructure.Tests.dll +``` + +**45 + 635 = 680 PASS / 0 FAIL** ⇒ KHỚP mốc B4 (680). Đ-9 KHÔNG kích hoạt, đi tiếp. +(Cờ `-p:BuildInParallel=false -maxcpucount:1` là nếp chống MSBuild OOM của repo, không đổi tập test.) ## 13 ca đã viết (map T-n → tên Fact) -CHƯA VIẾT. +File: `tests/SolutionErp.Infrastructure.Tests/Application/ContractDeleteGuardTests.cs` (MỚI, untracked). +Đếm đo tươi: `grep -c "^ \[Fact\]"` = **13** · 13 dòng comment `// T-n:` khớp 1-1. + +| T-n | Tên `[Fact]` | Kỳ vọng đã mã hoá | +|---|---|---| +| T-1 | `DeleteContract_DraftByOwner_SoftDeletes_AndWritesOneChangelogRow` :170 | 3-trong-1: `Count==0` (khuất) · `IgnoreQueryFilters` IsDeleted=true + DeletedBy=owner · changelog **2 dòng** (Insert seed + Delete) với EntityType=Contract, EntityId=null, PhaseAtChange=2, UserId, UserName, ContextNote | +| T-2 | `DeleteContract_TraLai_ByOwner_Succeeds` :210 | OK + `PhaseAtChange == TraLai(98)` | +| T-3 | `DeleteContract_TuChoi_ByOwner_Succeeds` :232 | OK + `PhaseAtChange == TuChoi(99)` | +| T-4 | `DeleteContract_LegacyPhaseBelowDangInKy_ByOwner_Succeeds` :255 | OK cho **1, 3, 4** (`DangChon`/`DangGopY`/`DangDamPhan`) | +| T-5 | `DeleteContract_ChoDuyet_ByOwner_ThrowsConflict` :281 | `ConflictException` + HĐ còn nguyên + **0 vết xoá ma** | +| T-6 | `DeleteContract_DaPhatHanh_ByAdmin_ThrowsConflict` :308 | `ConflictException` (9, Admin) + **biên `DangInKy(5)` cũng chặn** + cả 2 còn nguyên | +| T-7 | `DeleteContract_DraftOfAnotherUser_ByStranger_ThrowsForbidden` :336 | `ForbiddenException` + HĐ còn nguyên | +| T-8 | `DeleteContract_DraftOfAnotherUser_ByAdmin_Succeeds` :357 | OK + `DeletedBy == admin` + changelog `UserId == admin` | +| T-9 | `DeleteContract_NullDrafter_ByAnonymousActor_ThrowsUnauthorized` :385 | `UnauthorizedException` + HĐ còn nguyên | +| T-10 | `DeleteContract_UnknownId_ByStranger_ThrowsNotFoundBeforeForbidden` :408 | `NotFoundException` (KHÔNG Forbidden) | +| T-11 | `DeleteContract_ChoDuyetOfAnotherUser_ByStranger_ThrowsForbiddenBeforeConflict` :427 | `ForbiddenException` (KHÔNG Conflict) | +| T-12 | `DeleteContract_ReasonOver2000Chars_FailsValidation` :451 | `ValidationException` (app, không phải FluentValidation) + `Errors` có key `Reason` + `next` KHÔNG chạy + **control dương đúng 2000 ký tự thì chạy** | +| T-13 | `DeleteContract_WhitespaceReason_Succeeds_AndStoresNullContextNote` :481 | OK + `ContextNote == null` | +| T-14 | — **KHÔNG VIẾT** (phản-ca tôn trọng) | 0 test reflection-authz cho DELETE; lý do ghi trong header file | + +### 🔴 3 TÊN BỊ PIN — hợp đồng API mà BE (W5 việc 2) phải nở ĐÚNG +1. `DeleteContractCommand(Guid Id, string? Reason = null)` +2. `DeleteContractCommandHandler(IApplicationDbContext db, ICurrentUser currentUser)` +3. `DeleteContractCommandValidator : AbstractValidator` (khuôn `ContractSigningPlanFeatures.cs:1743`) + +Sai tên/sai arity ⇒ vẫn đỏ compile. Đây là chủ đích của test-before (chốt hợp đồng trước khi gõ prod). + +### Quyết định hạ tầng (điều kiện để phép đo CÓ NGHĨA) +- Fixture private-per-file `ContractDeleteFixture` (cái thứ 6 cùng nếp họ Contract — be2-R14) **wire `AuditingInterceptor`**. Không có nó thì `Remove()` = xoá CỨNG ⇒ mọi `IgnoreQueryFilters().Single(...)` nổ, còn `Count()==0` thì xanh cả khi soft-delete chưa từng tồn tại (bài S155). +- Mỗi lệnh = 1 `DbContext` mới, dùng chung 1 connection (mô phỏng scoped-per-request) — đúng điều kiện đẻ ra bug T26; nếu tái dùng context thì changelog Added bị cascade client-side ngay tại `Remove()` mà test lại không thấy. +- Seed kèm **1 dòng changelog `Insert` có sẵn** ⇒ assert "đúng 1 dòng Delete" thành phép đo PHÂN BIỆT (đọc theo `Action`, không đếm bừa) + canh vết cũ không bị lượt xoá cuốn theo. +- `Contract.SupplierId/ProjectId` là Guid LOOSE (`ContractConfiguration.cs:29-31` chỉ có index, không FK) ⇒ KHÔNG cần seed master, không rủi ro SQLite lỗi 19. +- T-12 đo qua `ValidationBehavior` THẬT (đường request đi trong prod) + alias `using ValidationException = SolutionErp.Application.Common.Exceptions.ValidationException` giống chính `ValidationBehavior.cs` ⇒ bắt đúng exception map ra HTTP 400, không nhầm bản FluentValidation. ## Kết quả chạy ĐỎ -CHƯA CHẠY. +*(worker #53 chết trước bước này — LEAD chạy on-behalf @S190)* + +`dotnet build tests/SolutionErp.Infrastructure.Tests` → **Build FAILED, ĐỎ COMPILE đúng kỳ vọng +test-before**, lỗi khớp ĐÚNG 3 tên bị pin: CS1729 `DeleteContractCommandHandler` ctor 2-args +(:155) · CS1729 `DeleteContractCommand` ctor 2-args (:156, :463, :472) · CS0246 +`DeleteContractCommandValidator` chưa tồn tại (:458) · CS0117 `Reason` chưa có (:468). +⇒ RED-READY — hợp đồng API đã chốt, W5b (implementer-backend) làm xanh. ## DỪNG/GHI CHÚ -CHƯA CÓ. +- Worker chết #53 SAU khi viết trọn file test + bảng map, TRƯỚC bước chạy-đỏ + return. + Lead xác nhận đỏ on-behalf. 0 điều kiện Đ kích hoạt. diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-b6-w5b-be.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-b6-w5b-be.md new file mode 100644 index 00000000..62eef184 --- /dev/null +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-b6-w5b-be.md @@ -0,0 +1,19 @@ +# B6-W5b — implementer-backend — làm XANH 13 test T-matrix (YC-029) + +Run: `2026-08-12-S190-soltuon-dieu-chinh-hd` · vai: implementer-backend · lượt: W5b + +## Việc đã làm + +_(đang chạy — append từng phần)_ + +## Kết quả test (đỏ→xanh) + +_(chưa đo)_ + +## Ô acceptance BE + +_(chưa đo)_ + +## DỪNG/GHI CHÚ + +_(chưa có)_