wal: flush 20260731T1441

This commit is contained in:
pqhuy1987
2026-07-31 14:41:04 +07:00
parent c72ffc2de3
commit 735f9687f8
4 changed files with 104 additions and 5 deletions

View File

@ -16,8 +16,13 @@ chain:
[x] wf: B4 K1-BE p1 wf_2569b79b-12f — chết-giữa ~40% NHƯNG disk-truth: SCHEMA-LAYER XONG ĐÚNG SPEC
(entity 10-cột ✓ unique-filtered ✓ Mig70 3-file ✓ 0-RenameColumn ✓ DbContext ✓ — lead sanity 3/3).
Thiếu: seeder+MenuKeys+CQRS+build. Files uncommitted trên cây (git status 4 mới + 3 sửa)
[!] wf: B4 K1-BE p2 wf_2e08ba77-f53 ĐANG CHẠY (relaunch-cắt-gọt): seeder 86-row + MenuKeys/All + CQRS +
controller mirror-Catalogs + build slnx + test-590. 🔴 KHÔNG commit/push — OG-6 gate
[x] wf: B4 K1-BE p2 wf_2e08ba77-f53 — K1-BE TRỌN (return rỗng, disk-truth ĐỦ): seeder 86/86 (lead đếm máy)
+ MenuKeys/All + CQRS ContractCatalogFeatures + controller (path api/catalogs/contract-catalog, authz
mirror) + build 0W/0E + TEST 590/590 (lead chạy ×2 — lần-1 flaky 2-fail isolation, lần-2 SẠCH; chạy
riêng class 11/11). Lane khai 2 quyết hợp lý (TenVi sạch · controller file-riêng path-spec). UNCOMMITTED
[!] wf: B4 K1-FE+K1-test wf_d894f6e6-018 ĐANG CHẠY (2 lane song song: impl-fe KIND_CONFIG contract-catalog
×2 app + 4-chỗ-mirror · test-specialist 6 test T1-T6 [seed-idempotent-86 · phân-bố-8-nhóm · unique-
filtered · validator · soft-delete · key-∈-All]). 🔴 KHÔNG commit/push — OG-6 gate
[ ] B4 tiếp: K1-FE (×2 app KIND_CONFIG) + K1-test → K2 → K3 → K4a... theo build-order; mỗi wave lead verify
+ reviewer-gate trước commit; PUSH K1 chờ anh soát OG-6 (bảng transcribe + 8 nhãn)
[ ] K8 dry-run: gói test SOLUTION-PE-{n} + B0-form 14 người thật (fail-closed) + đo freeze 2-nhánh

View File

@ -11,9 +11,89 @@
- [ ] B8 build + test
## Lệch spec (nếu có)
_(chưa có)_
1. **MenuKeys VÀO `All`** (lead) vs **NGOÀI `All`** (invest-spec K1.d:57) → theo lead, khai drift bên dưới.
2. **Controller riêng** `ContractCatalogController` (lead) vs **extend `CatalogsController`** (invest-spec K1.c:51) → theo lead về FILE, giữ PATH `api/catalogs/contract-catalog` của spec để FE khỏi đổi.
3. **TenVi B2-07..B2-14 bỏ chú-thích `(ảnh: …)`** — chú-thích của người chép, không phải tên hạng mục; chuyển thành comment cuối dòng. Row vẫn đủ 14.
4. **Test K1 k=5 (invest-spec K1.e) KHÔNG viết** — lead chỉ định "KHÔNG viết test mới, chỉ KHÔNG VỠ"; test là việc `test-specialist`.
## Kết quả build/test
_(chưa chạy)_
- `dotnet build SolutionErp.slnx --nologo -v minimal`**Build succeeded · 0 Warning(s) · 0 Error(s)** · Time Elapsed 00:00:15.33
- `dotnet test SolutionErp.slnx --nologo -v minimal`
- `Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45` (Domain, 332 ms)
- `Passed! - Failed: 0, Passed: 545, Skipped: 0, Total: 545` (Infrastructure, 1 m 25 s)
- **Tổng 590 PASS / 0 FAIL** = ĐÚNG baseline 590 (`STATUS.md:472`) → 0 test vỡ, 0 test mới (đúng lệnh).
## FILE tạo/sửa (PHẦN 2 — lượt này)
**MỚI (2):**
- `src/Backend/SolutionErp.Application/Master/Catalogs/ContractCatalogFeatures.cs` — 5 handler + 2 validator + DTO
- `src/Backend/SolutionErp.Api/Controllers/ContractCatalogController.cs` — 5 endpoint, `[Authorize]` + 3× `[Authorize(Roles="Admin")]`
**SỬA (2):**
- `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs` **+186 dòng** — `SeedContractCatalogAsync` (86 row) + call-site `InitializeAsync` + 1 menu row leaf
- `src/Backend/SolutionErp.Domain/Identity/MenuKeys.cs` **+5 dòng** — const `ContractCatalog` + vào `All`
**CÓ SẴN từ lượt 1 (KHÔNG đụng, liệt để lead commit đủ):** `Domain/Master/Catalogs/ContractCatalogEntry.cs` · `Persistence/Configurations/ContractCatalogEntryConfiguration.cs` · Mig 3-file `20260731072441_AddContractCatalogEntries.cs` + `.Designer.cs` + `ApplicationDbContextModelSnapshot.cs` · `IApplicationDbContext.cs` (+2) · `ApplicationDbContext.cs` (+2).
**Tổng scope K1-BE = 10 file** (4 lượt-này + 6 lượt-1). `git status -- src/Backend` xác nhận **0 file FE, 0 file tests/** bị chạm.
## Drift DELTA (số canonical `docs/STATUS.md` — em main vá doc, tôi KHÔNG đụng)
| Row | Trước | Sau | Cách đo |
|---|---|---|---|
| Menu keys | 55 | **56** | đếm TỪ MÃ `MenuKeys.All` (sed vùng array → tách `,` → đếm identifier) = **56** |
| Policies | 220 | **224** | DERIVED `\|All\| × \|Actions\| = 56 × 4` |
| Mig | 69 | **70** | `20260731072441_AddContractCatalogEntries` (lượt 1) |
| Bảng | 96 | **97** | +1 `ContractCatalogEntries` (lượt 1) |
| Tests | 590 | **590** | không đổi (0 test mới, 0 vỡ) |
## 🔴 Bàn giao / còn hở (lead quyết)
1. **Mig 70 CHƯA áp Dev-DB**`sqlcmd (localdb)\MSSQLLocalDB -d SolutionErp_Dev` → top `__EFMigrationsHistory` = `20260729122015_AddContractSigningPlans` (Mig 69). Tôi KHÔNG tự áp (ngoài 7 bước lệnh + lệnh cấm sửa schema). Tự lành khi chạy API: `DbInitializer:64 MigrateAsync()` áp Mig 70 rồi seed 86 row ngay cùng lần boot. Hoặc tay: `dotnet ef database update --project src/Backend/SolutionErp.Infrastructure --startup-project src/Backend/SolutionErp.Api` (+ `--connection "…Database=SolutionErp_Dev…"` cho Dev).
2. **Chưa chạy verify RUNTIME** (restart API ×2 → COUNT=86 idempotent, K1.f:70-71) vì chưa áp DB — checklist đó còn TRỐNG, đừng tick.
3. **Leaf menu hiện chỉ Admin thấy** — 3 seeder grant khác dùng list-key-cứng (chi tiết P2-B2).
4. **[OG-6] chưa gật** — data 86 row đã land trong code; nếu owner soát ra sai ô nào thì sửa tuple + restart (per-Code idempotent nên row đã seed KHÔNG tự cập nhật, cần UPDATE tay hoặc thêm nhánh upgrade-if-exists).
5. Test K1 k=5 để `test-specialist`.
END impl-be-k1 — 4 file lượt này (10 file scope K1-BE) · build PASS 0W/0E · test 590 (45D+545I) 0 fail
## PHẦN 2 (relaunch)
Lượt 1 chết sau schema-layer. Schema ĐÃ TRÊN ĐĨA (verify @relaunch):
- `src/Backend/SolutionErp.Domain/Master/Catalogs/ContractCatalogEntry.cs` (10 cột, AuditableEntity)
- Mig `20260731072441_AddContractCatalogEntries` (3-file) — KHÔNG tạo lại, KHÔNG sửa.
Việc PHẦN 2: seeder 86-row · MenuKeys + MenuItem · CQRS/controller · build · test.
### P2-B0 Đọc nguồn (xong)
- [x] `sub-invest-fable-b2-cum1.md` §K1.b/.c (:33-51) — seed UNGATED + IgnoreQueryFilters + mapping field; CQRS mega-file + extend CatalogsController
- [x] `danh-muc-sp002-transcribe.md` TRỌN — 86 row (A1 5 · A2 1 · A3 9 · A4 5 · B1 23 · B2 14 · B3 15 · C1 6 · C2 3 · C3 4 · CEO 1 = 86); bảng 8 nhóm (SignerRole + InitialsChain)
- [x] `DbInitializer.cs:2889-2986` khuôn tuple-array + per-Code idempotent
- [x] `MenuKeys.cs:164-186` vùng `All` (5 leaf catalog :168)
### ⚠️ LỆCH SPEC đã khai (lead override, làm theo lead)
- invest-spec §K1.d (:57) ghi `MenuKeys.ContractCatalog` **NGOÀI `All`** (0 policy mới).
- LỆNH lead PHẦN 2 mục 2 ghi **VÀO `All`** + drift DELTA **(+1 key / +4 policy)**.
→ Làm theo LỆNH lead (mới hơn + có khai drift). Hệ quả: `docs/STATUS.md` row `Menu keys` +1 và row `Policies` +4 (DERIVED |All|×|Actions|) — em main cập nhật STATUS, tôi KHÔNG đụng doc.
### P2-B1 Seeder 86 row — XONG
- `DbInitializer.cs` +`SeedContractCatalogAsync` (đặt ngay TRƯỚC `SeedContractTemplatesAsync`) + call-site trong `InitializeAsync` ngay SAU `SeedRealMasterDataAsync` (khớp K1.b "cạnh SeedRealMasterDataAsync, trước sample workflows").
- **UNGATED** (ngoài `if (!demoSeedDisabled)`) — gotcha #51.
- Idempotent per-Code + **`IgnoreQueryFilters()`** khi dò existing → né #75/#76 resurrect (làm ĐÚNG HƠN khuôn `:2970`, ghi comment lý do trong code).
- `NduqNote = null` [OG-3] · `IsActive = true` · `SortOrder` = STT trong section.
- SignerRole/InitialsChain: lookup `signByGroup` 8 nhóm → **ghi denorm vào TỪNG row** (đủ 8 field/row như lệnh; không chép tay chuỗi 86 lần để khỏi lệch ký tự). Ô "N/A" đã bỏ đúng spec (N3 còn 3 ô, N4/N8 còn 2 ô, N7 còn 3 ô).
- **ĐO tại chỗ (grep count trên file vừa ghi):** tổng **86** row; theo section `A1=5 A2=1 A3=9 A4=5 B1=23 B2=14 B3=15 C1=6 C2=3 C3=4 CEO=1`; theo `ApprovalGroup` = **5/10/5/23/14/15/13/1** → khớp ĐÚNG K1.b:41.
### P2-B2 MenuKeys + MenuItem — XONG
- `MenuKeys.cs` +const `ContractCatalog = "ContractCatalog"` (cạnh 4 const catalog, `:28-32`) + **VÀO `All`** ngay sau dòng 5 leaf catalog.
- `DbInitializer.cs` `SeedMenuTreeAsync` +row `(MenuKeys.ContractCatalog, "Danh mục Hợp đồng", MenuKeys.Catalogs, 5, "FileSpreadsheet")` — leaf thứ 5 dưới "Danh mục chi tiết"; icon `FileSpreadsheet` đã dùng sẵn (`MenuKeys.Forms` :1788) nên FE có map.
- Grant Admin: TỰ ĐỘNG qua loop `SeedAdminPermissionsAsync` `MenuKeys.All` (`:2058`) — 0 code thêm.
- ⚠️ **Flag cho lead (KHÔNG tự làm — ngoài lệnh):** 3 seeder grant khác dùng DANH SÁCH KEY CỨNG chứ không prefix-match → key mới KHÔNG tự vào: `SeedCatalogManagerPermissionsAsync` (`:2626-2629`), `SeedAllRolesReviewReadPermissionsAsync` (`:2181-2182`), `SeedProcurementMasterAccessAsync` (`:2360-2363`). ⇒ **hiện chỉ Admin thấy leaf "Danh mục Hợp đồng"**; muốn PRO/CatalogManager thấy thì thêm key vào 3 list đó (mỗi chỗ 1 dòng).
### P2-B3+B4 CQRS + Controller — XONG
- MỚI `SolutionErp.Application/Master/Catalogs/ContractCatalogFeatures.cs`: `ListContractCatalogQuery(GroupCode?, ApprovalGroup?, IsActive?, Q?)` (sort GroupCode→SortOrder→Code, KHÔNG paging) · `GetContractCatalogEntryQuery` · `Create/Update/Delete` + 2 validator.
- Validator MaxLength **lấy từ EF config** `ContractCatalogEntryConfiguration.cs:18-24` (Code 20 · TenVi/TenEn/NduqNote 500 · GroupCode 10 · SignerRole 100 · InitialsChain 300) — không trust spec; `ApprovalGroup` `InclusiveBetween(1,8)`.
- Dup-Code: `AnyAsync(x => x.Code == req.Code)` chạy trên ACTIVE-set (query filter `!IsDeleted`) → khớp UNIQUE filtered `[IsDeleted]=0`, Code của row xoá-mềm tái dùng được. Delete = `Remove` → soft qua AuditingInterceptor.
- MỚI `SolutionErp.Api/Controllers/ContractCatalogController.cs``[Route("api/catalogs/contract-catalog")]` + class `[Authorize]`, 3 verb ghi `[Authorize(Roles = "Admin")]`. **0 policy key mới**.
- Ghi chú hòa 2 lệnh: lead nói "controller ContractCatalogController", invest-spec K1.c:51 nói "extend CatalogsController" với path `api/catalogs/contract-catalog` → tôi lấy **file controller riêng (theo lead)** + **giữ nguyên path (theo spec)** ⇒ FE KIND_CONFIG `contract-catalog` chạy được không cần đổi.
### P2-B5 Build — PASS
`dotnet build SolutionErp.slnx --nologo -v minimal`**Build succeeded · 0 Warning · 0 Error** (15.3s, 6 project) — PASS ngay lần đầu, 0 vòng sửa compile.
- ⚠️ **1 quyết-định data khai rõ:** transcribe B2-07..B2-14 có chú-thích truy-vết `(ảnh: số 7 thứ nhất)`, `(ảnh: 9)`… — đó là **ghi-chú của người chép, KHÔNG phải tên hạng mục**. Tôi seed TenVi **sạch** ("Công tác kim loại", "Cảnh quan"…) và chuyển chú-thích thành comment cuối dòng code. Số dòng giữ nguyên 14 (AS-IS về row). Nếu owner muốn giữ nguyên văn trong tên → sửa 8 chuỗi, 1 phút.
(ĐANG LÀM)

View File

@ -0,0 +1,7 @@
# impl-fe K1
## Tiến độ
- (ĐANG LÀM) Call-1: khung sub-file. Bước kế: đọc §K1 (d) FE + BE contract trên đĩa + khuôn KIND_CONFIG catalogs fe-user.
## Kết quả build
- (ĐANG LÀM)

View File

@ -0,0 +1,7 @@
# test K1
## Tiến độ
- (ĐANG LÀM) call-1: khung sub-file đã ghi. Bước kế: đọc spec §K1 + code thật (entity/config/seeder/features).
## Kết quả
- (CHƯA ĐO)