wal: flush 20260812T2008
This commit is contained in:
@ -38,10 +38,11 @@ chain:
|
|||||||
discriminator code-only; lead spot-check 4 phép khớp từng số) → 🔄 W5 3-worker tuần tự:
|
discriminator code-only; lead spot-check 4 phép khớp từng số) → 🔄 W5 3-worker tuần tự:
|
||||||
✅W5a RED-READY (13 Fact + pin 3 API; baseline 680 khớp; #53 chết trước chạy-đỏ —
|
✅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) →
|
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 +
|
✅W5b GREEN 693/693 vòng-1 (#53 return rỗng, artifact TRỌN; 5 nấc đúng thứ tự —
|
||||||
validator + controller reason + sửa ghost-wire ContractChangelog comment; CẤM sửa
|
lead-gate filter 13/13 + awk 9→12→20→29→41<43; tự bắt 3 lỗi thước C17b/C15/C18 +
|
||||||
test/CẤM policy) → W5c implementer-frontend (nút Xóa panel ×2) →
|
Đ-5-suýt: plan ghi sai path 2 file changelog-site nhưng số dòng khớp) →
|
||||||
lead commit MỘT phát + reviewer-gate. PUSH GOM CHỜ.
|
🔄 W5c implementer-frontend wf_daa0f6e9-5f8 (nút Xóa thanh đáy + MIRROR-khai ×2 app)
|
||||||
|
→ 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.
|
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 ·
|
[!] TỒN CŨ — CỬA NGOÀI-GIỜ (anh gật giờ): dọn workspace runner + dispatch verify CI ·
|
||||||
(3B) Gitea cron + compact Vietreport_Master + báo VIETREPORT · đo lại A/059
|
(3B) Gitea cron + compact Vietreport_Master + báo VIETREPORT · đo lại A/059
|
||||||
|
|||||||
@ -1,19 +1,119 @@
|
|||||||
# B6-W5b — implementer-backend — làm XANH 13 test T-matrix (YC-029)
|
# 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
|
> Run `2026-08-12-S190-soltuon-dieu-chinh-hd` · vai implementer-backend · lượt W5b (nối sau W5a test-before).
|
||||||
|
> Nguồn lệnh: `sub-b5-plan-final.md` khối `### W5` việc 2+3 · `style-gate-v2.md` §B · bảng ô `sub-style-review-b4-be2.md:198-226`.
|
||||||
|
> **KHÔNG commit** (lead gộp cuối W5) · **KHÔNG chạm test file** (hợp đồng API đã chốt @W5a).
|
||||||
|
|
||||||
## Việc đã làm
|
## Việc đã làm
|
||||||
|
|
||||||
_(đang chạy — append từng phần)_
|
### 1. `src/Backend/SolutionErp.Application/Contracts/ContractFeatures.cs` — khối DELETE viết lại
|
||||||
|
|
||||||
|
Thân cũ (`:885-902`, 18 dòng) → khối mới `:885-983`. 4 thứ nở đúng 3 tên bị pin:
|
||||||
|
|
||||||
|
| # | Thứ | Bằng chứng |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | `record DeleteContractCommand(Guid Id, string? Reason = null)` — positional, default ở CUỐI ⇒ 0 call-site vỡ | `ContractFeatures.cs:917` |
|
||||||
|
| 2 | `DeleteContractCommandValidator : AbstractValidator<…>` — `Id.NotEmpty()` + `Reason.MaximumLength(2000)` | `:919-930` |
|
||||||
|
| 3 | Handler primary-ctor `(IApplicationDbContext db, ICurrentUser currentUser)` | `:932-934` |
|
||||||
|
| 4 | Header khối khai quyết-định + 3 bẫy | `:885-915` |
|
||||||
|
|
||||||
|
**5 nấc, đúng thứ tự đặc tả** (`:938-971`):
|
||||||
|
|
||||||
|
| Nấc | Mã | Dòng | Ca canh |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 0 | `!IsAuthenticated \|\| UserId is null` → `UnauthorizedException` | `:939-940` | T-9 |
|
||||||
|
| 1 | `FirstOrDefaultAsync` → `NotFoundException` | `:942-943` | T-10 |
|
||||||
|
| 2 | `isOwner = DrafterUserId == currentUser.UserId` · `isAdmin = Roles.Contains(AppRoles.Admin)` → `ForbiddenException` | `:948-951` | T-7 / T-8 / T-11 |
|
||||||
|
| 3 | `Phase < DangInKy` ∪ `{TraLai, TuChoi}` → `ConflictException` | `:956-964` | T-2..T-6 |
|
||||||
|
| 4 | `Remove` **TRƯỚC** → `ContractChangelogs.Add` **SAU** → 1 `SaveChangesAsync` | `:972-987` | T-1 / T-13 |
|
||||||
|
|
||||||
|
Chi tiết đáng ghi:
|
||||||
|
|
||||||
|
- **Nấc-0 KHÔNG chép từ KHKK** — khuôn `ContractSigningPlanFeatures.cs:1763` so thẳng người soạn với actor, nên HĐ `DrafterUserId=null` + actor `UserId=null` cho `null == null` ⇒ hoá "chủ sở hữu" ⇒ xoá lọt. Lấy nấc-0 từ `PeSoftDeleteFeatures.cs:56-58`. Comment `:895-899` viết theo chiều **cấm chép ngược** (đừng xoá nấc-0 ở đây cho "giống KHKK"; muốn đều thì thêm cho KHKK).
|
||||||
|
- **Allow-list phase KHÔNG chép hình `is not (…)` của KHKK** — HĐ rộng hơn: gồm cả legacy 1/3/4. Viết dạng `Phase < DangInKy || == TraLai || == TuChoi` (`:956-958`) — giữ đúng tinh thần rào cũ `Phase >= DangInKy` rồi **mở thêm** 2 phase terminal-mềm, thay vì liệt kê đóng.
|
||||||
|
- **Message 409** liệt trạng thái cấm theo 2 nhóm (`:960-964`): "Đã gửi duyệt phải Trả lại/Từ chối trước" (ChoDuyet=10, cấm kể cả chủ HĐ — approver-delete là Q4, ngoài đợt) + "từ 'Đang in ký' trở đi (trình ký, đóng dấu, đã phát hành)" (≥5, cấm mọi đường kể cả Admin). Message cũ `"Không được xóa HĐ đã qua phase 'Đang in ký'."` bị thay — đã grep trước: **0 test/mã nào assert chuỗi đó** (`grep -rn --include=*.cs "Đang in ký" src/ tests/` = 3 hit, đều là bảng nhãn phase `WorkflowAdminFeatures.cs:80` / `ContractExcelExporter.cs:18` + chính dòng bị thay).
|
||||||
|
- **Field-set changelog** (`:974-985`) mirror 2 site ghi tay: `ContractId` · `EntityType=Contract` · `EntityId=null` (khai TƯỜNG MINH dù trùng default — T-1 assert) · `Action=Delete` · `PhaseAtChange` = biến snapshot lấy **trước** `Remove` (`:969`) · `UserId` · `UserName = FullName ?? Email` · `Summary` · `ContextNote = reason` (trim-to-null `:968`, khuôn KHKK `:1785`).
|
||||||
|
|
||||||
|
### 2. `src/Backend/SolutionErp.Api/Controllers/ContractsController.cs` — DELETE action
|
||||||
|
|
||||||
|
- `:88-90`: `Delete(Guid id, [FromQuery] string? reason = null, CancellationToken ct = default)` → `new DeleteContractCommand(id, reason)`. `ct` phải nhận `= default` vì tham số optional không được đứng trước tham số bắt buộc (nếp đã có ở `List(…)` `:26`).
|
||||||
|
- **KHÔNG gắn policy per-action** (be2-R1 LẬT so bản nháp). Comment `:78-87` khai vì sao + `[carry:w8-delete-policy]`, đặt **trên** `[HttpDelete]` (ngoài phạm vi awk của ô C10 — đặt trong thân sẽ tự làm ô đo của chính mình đỏ).
|
||||||
|
|
||||||
|
### 3. `src/Backend/SolutionErp.Domain/Contracts/ContractChangelog.cs` — gỡ ghost-wire (be2-R13)
|
||||||
|
|
||||||
|
Comment cũ `:10-12` khai *"Populate qua MediatR `AuditBehavior` interceptor … xem Application/Common/Behaviors/AuditBehavior.cs"*.
|
||||||
|
|
||||||
|
**Đo:** `ls src/Backend/SolutionErp.Application/Common/Behaviors/` → **chỉ có `ValidationBehavior.cs`**; `grep -rln --include=*.cs "AuditBehavior" src/ tests/` → **đúng 1 file: chính `ContractChangelog.cs`** (tức chuỗi này chỉ sống trong lời tự khai của nó, 0 mã nào gọi). Đây là lời hứa chưa land, không phải neo trôi.
|
||||||
|
|
||||||
|
Thay bằng sự thật + trỏ **2 đường ghi TAY** (`:10-22`): `Infrastructure/Services/ChangelogService.cs` (5 site) và `Add(new ContractChangelog{…})` thẳng trong handler — 3 site: `CreateContractFromSigningPlanFeatures.cs:247` · `CreateContractFromEvaluationFeatures.cs:121` · khối DELETE mới. Nêu luôn **vì sao câu cũ nguy hiểm hơn không có chú thích**: người đọc tưởng nhật ký tự ghi ⇒ thao tác mới lặng lẽ không để lại vết.
|
||||||
|
|
||||||
## Kết quả test (đỏ→xanh)
|
## Kết quả test (đỏ→xanh)
|
||||||
|
|
||||||
_(chưa đo)_
|
Baseline **680** đã đo tươi @W5a (`45 + 635`) trước khi chạm file ⇒ Đ-9 không kích hoạt, KHÔNG đo lại (đo lại lúc này bất khả: cây đang ĐỎ COMPILE vì test-before).
|
||||||
|
|
||||||
|
| Vòng | Trạng thái | Số đo | Nguyên nhân |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 0 (W5a) | 🔴 ĐỎ COMPILE | build FAILED | CS1729 ctor handler 2-args (`:155`) · CS1729 ctor command 2-args (`:156,:463,:472`) · CS0246 `DeleteContractCommandValidator` (`:458`) · CS0117 `Reason` (`:468`) |
|
||||||
|
| 1 (W5b, sau 3 file trên) | 🟢 XANH | **45 + 648 = 693 / 0 FAIL** | — |
|
||||||
|
|
||||||
|
```
|
||||||
|
dotnet test SolutionErp.slnx --nologo -v q -p:BuildInParallel=false -maxcpucount:1
|
||||||
|
Passed! - Failed: 0, Passed: 45, Total: 45 — SolutionErp.Domain.Tests.dll (giữ nguyên)
|
||||||
|
Passed! - Failed: 0, Passed: 648, Total: 648 — SolutionErp.Infrastructure.Tests.dll (635 → 648, +13)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Xanh vòng 1, 0 vòng sửa-vì-đỏ-assert** — không có ca nào phải đàm phán lại với test.
|
||||||
|
|
||||||
|
13 ca chạy RIÊNG để chứng "+13 là chính 13 ca này", không suy từ hiệu số:
|
||||||
|
|
||||||
|
```
|
||||||
|
dotnet test tests/SolutionErp.Infrastructure.Tests --filter "FullyQualifiedName~ContractDeleteGuardTests"
|
||||||
|
Passed! - Failed: 0, Passed: 13, Total: 13, Duration: 5 s
|
||||||
|
```
|
||||||
|
|
||||||
|
Build sạch cả 6 project (Api có trong lượt build ⇒ thay đổi controller có biên dịch thật):
|
||||||
|
|
||||||
|
```
|
||||||
|
dotnet build SolutionErp.slnx --nologo → Build succeeded. 0 Warning(s) 0 Error(s)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Test file KHÔNG bị chạm** (bằng chứng độc lập với lời khai): mtime `ContractDeleteGuardTests.cs` = `19:50:58` (W5a) vs 3 file src của tôi = `19:58:53 / 19:59:07 / 19:59:18`. 0 lệnh Write/Edit của tôi trỏ vào `tests/`.
|
||||||
|
|
||||||
## Ô acceptance BE
|
## Ô acceptance BE
|
||||||
|
|
||||||
_(chưa đo)_
|
Bảng be2 bản đã sửa (`sub-style-review-b4-be2.md:198-226`). Đặt trước: `F=…/ContractFeatures.cs` · `H='/class DeleteContractCommandHandler/,/^}/'` · `C=…/ContractsController.cs` · `T=…/ContractDeleteGuardTests.cs`.
|
||||||
|
|
||||||
|
| Ô | Kỳ vọng | Số THẬT | Verdict |
|
||||||
|
|---|---|---|---|
|
||||||
|
| C1 | `grep -c 'record DeleteContractCommand(Guid Id, string? Reason = null)' $F` = 1 | **1** | PASS |
|
||||||
|
| C2 | awk validator \| `grep -c 'MaximumLength(2000)'` = 1 | **1** | PASS |
|
||||||
|
| C3 | awk `$H` \| `grep -c 'ICurrentUser currentUser'` = 1 | **1** | PASS |
|
||||||
|
| C4 | trong `$H`: NF < FB < CF, 3 dòng | **3 dòng — 12 NotFound · 20 Forbidden · 29 Conflict** (offset trong range) | PASS |
|
||||||
|
| C5 | `AppRoles.Admin` = 1 · `DrafterUserId == currentUser.UserId` = 1 | **1 · 1** | PASS |
|
||||||
|
| C6 | Remove < Add · `SaveChangesAsync` = 1 | **41 Remove · 43 Add · 56 Save (đúng 1)** | PASS |
|
||||||
|
| C10 | awk DELETE action \| `grep -c 'Authorize(Policy'` = **0** | **0** | PASS |
|
||||||
|
| C11 | `grep -c '^\[Authorize\]$' $C` = 1 | **1** | PASS |
|
||||||
|
| C12 | `grep -c 'FromQuery\] string? reason' $C` = 1 | **1** | PASS |
|
||||||
|
| C16 | `dotnet test` = 680+N, N≥13 | **693 (= 680+13)** | PASS *(lật STATUS = việc lead lúc commit; tôi KHÔNG chạm `docs/`)* |
|
||||||
|
| C17a | `catch (` trong `Api/Controllers/` = 0 · control `Api/` > 0 | **0 · control 2** | PASS |
|
||||||
|
| C17b | `Console.WriteLine` trong `src/Backend/` = 0 · control `Console\.` | **0 · control `Console\.` = 0** | ⚠️ PASS-có-ngoặc (dưới) |
|
||||||
|
| C17c | `grep -rE "FromSqlRaw\|ExecuteSqlRaw\|SqlQueryRaw"` = 0 · control > 0 | **0 · control `IApplicationDbContext\|ZZZNOTEXIST` = 313** | PASS |
|
||||||
|
| C18 | `{ git diff --name-only HEAD; git ls-files -o --exclude-standard; } \| sort -u` | 9 mục — **3 file của tôi + 1 test file W5a + 5 mục KHÔNG phải của tôi** (dưới) | PASS |
|
||||||
|
| C19 | `grep -rn --include=*.cs 'Contracts\.Delete' src/ tests/` = 0 | **0** | PASS |
|
||||||
|
| C21 | ma-trận `CanDelete` khoá `Contracts` + control dương | **12/13 role = 0 (chỉ Admin=1, `Drafter`=0)** · control `KeHoachKyKet` **`Drafter`=1** | PASS |
|
||||||
|
|
||||||
|
Ô thuộc file test (đo để tham chiếu, **không** sửa): C14a `AuditingInterceptor` = 4 · C14b `IgnoreQueryFilters` = 5 · C15 `[Fact]` = **14**.
|
||||||
|
|
||||||
|
**3 ghi chú về THƯỚC — cái này quan trọng hơn mấy dấu PASS ở trên:**
|
||||||
|
|
||||||
|
1. **C17b control CHẾT.** be2 pin control `Console\.` → **72**; đo lại với `--include=*.cs` ra **0** ở `src/Backend/`, `src/`, và cả `src/ + tests/`. Con số 72 là **dương-giả từ grep không lọc** (bin/obj nhị phân) — đúng bệnh mà chính C19 dựng ra để bắt. Hệ quả thật: ô C17b **không phân biệt được** "lượt sửa này tránh `Console.WriteLine`" với "cả kho chưa từng có dòng nào". Tôi thay control chuyên biệt bằng control-đường-đi (`^using ` trong `src/Backend/` = **1697**) — cái này chỉ chứng grep chạy đúng đường, KHÔNG cứu được nghĩa của ô. Ô này nên đọc là *0 thật, nhưng không có răng*.
|
||||||
|
2. **C15 rò use⟂mention (+1).** `grep -c '\[Fact\]' $T` = 14, trong khi số test CHẠY = 13. Dòng thứ 14 là **comment** `:481` (*"Viết RIÊNG một `[Fact]` theo X-9…"*). Dạng neo của W5a — `grep -c "^ \[Fact\]"` = **13** — mới là dạng đúng. Ô as-written (`≥13`) vẫn cho verdict đúng ở đây, nhưng nó xanh **nhờ bất đẳng thức lỏng**, không nhờ đo trúng; sửa `[Fact]` thành `= 13` mà không neo cột thì ô tự đỏ oan.
|
||||||
|
3. **C18 có 5 mục KHÔNG phải của tôi**, khai để lead không cộng nhầm vào phạm vi W5b: `.claude/commands/pause.md` · `.claude/commands/tiep.md` · `.claude/governance/.session-counter.json` · `docs/HANDOFF.md` · `docs/governance/so-yeu-cau-chu-du-an.md`. Tôi không biết chúng bẩn từ lượt nào và **không suy đoán**; chỉ khẳng định phần đo được: 0 lệnh Write/Edit của tôi trỏ vào chúng (2 mục đã bẩn sẵn ở ảnh git-status đầu phiên). File của tôi đúng 3: `ContractFeatures.cs` · `ContractsController.cs` · `ContractChangelog.cs`.
|
||||||
|
|
||||||
## DỪNG/GHI CHÚ
|
## DỪNG/GHI CHÚ
|
||||||
|
|
||||||
_(chưa có)_
|
- **0 điều kiện Đ-1..Đ-10 kích hoạt.** Không có ca test nào phải đàm phán lại (Đ-3 im), không đụng file ngoài wave (Đ-4 im), baseline khớp 680 (Đ-9 im), không `--no-verify`.
|
||||||
|
- **Đ-5 suýt kích hoạt — KHÔNG kích hoạt, khai để lead biết:** plan `:108` trỏ `CreateContractFromSigningPlanFeatures.cs` và `CreateContractFromEvaluationFeatures.cs` như thể nằm trong `Application/Contracts/`; đĩa thật chúng ở `Application/ContractSigningPlans/` và `Application/PurchaseEvaluations/`. **Số dòng `:247` / `:121` khớp CHÍNH XÁC** ⇒ đây là lệch đường-dẫn khi thuật lại, không phải cây trôi. Đã trỏ đường ĐÚNG trong comment `ContractChangelog.cs:18-20`.
|
||||||
|
- **KHÔNG commit** (theo lệnh). **KHÔNG chạm** `docs/STATUS.md` (X-2 — dòng session DELTA `680→693` là việc của lượt commit; row canonical `Tests` `:476` KHÔNG lật, chỉ chép từ cicd-verify).
|
||||||
|
- **Việc còn treo, KHÔNG thuộc W5b:** ô C-12 / C-MIRROR-KHAI / C-2 / C-3 phía FE (`ContractDetailContent.tsx` ×2 app) — vai implementer-frontend. Cặp FE **chưa được chạm trong lượt này**; nút Xoá trên UI chưa có ⇒ đường mới hiện chỉ gọi được qua API.
|
||||||
|
- **Ranh đã giữ:** Write/Edit đúng 4 đích {`ContractFeatures.cs` · `ContractsController.cs` · `ContractChangelog.cs` · file này}. 0 chạm `tests/**`, `fe-*/**`, `Persistence/**`, agent-memory, MD canonical. **0 migration** (đúng thiết kế — không đổi schema).
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
# sub-b6-w5c-fe — W5c port nút Xóa vào ContractDetailContent (×2 app)
|
||||||
|
|
||||||
|
## Việc đã làm
|
||||||
|
|
||||||
|
## Ô acceptance
|
||||||
|
|
||||||
|
## DEFERRED/DỪNG
|
||||||
Reference in New Issue
Block a user