wal: flush 20260731T1452
This commit is contained in:
@ -20,9 +20,12 @@ chain:
|
||||
+ 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
|
||||
[x] wf: B4 K1-FE ✅ (6 file/3-per-app đối xứng · KIND_CONFIG kind-5 · 4-chỗ-16-bis · SHA-pair d71a9e3b ×2 ·
|
||||
build ×2 PASS — lead RE-BUILD trọng-tài #68 lần-3: diagnostics IDE = stale, build thật XANH; lane khai
|
||||
2 khoảng-hở UX [3 filter BE chưa UI · tab hiện cả fe-user] chờ lead/anh, KHÔNG tự quyết — đúng luật).
|
||||
Bonus finding: `columns` KIND_CONFIG = config CHẾT từ S29, kind-5 là lần đầu được nối render
|
||||
[!] wf: B4 K1-test p2 wf_1fb9f309-a27 (relaunch — p1 chết sau đọc-contract): viết ContractCatalogTests 6-test
|
||||
+ chạy suite kỳ vọng 596. 🔴 KHÔNG commit — sau đó: reviewer-gate K1 → chờ OG-6 → commit-push K1
|
||||
[ ] 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
|
||||
|
||||
@ -1,7 +1,58 @@
|
||||
# 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.
|
||||
- Call-1: khung sub-file. OK.
|
||||
- Đọc xong nguồn:
|
||||
- `sub-invest-fable-b2-cum1.md:53-57` §K1.d — kind mới `contract-catalog` vào KIND_CONFIG ×2 app, endpoint `api/catalogs/contract-catalog`, route `:kind` sẵn ⇒ 0 route mới.
|
||||
- BE THẬT: `src/Backend/SolutionErp.Api/Controllers/ContractCatalogController.cs:21` `[Route("api/catalogs/contract-catalog")]`, `[Authorize]` class + `[Authorize(Roles="Admin")]` 3 verb ghi (`:39,:47,:56`). List query `groupCode/approvalGroup/isActive/q` (`:27-30`).
|
||||
- DTO `ContractCatalogFeatures.cs:27-38` = 11 field {Id, Code, TenVi, TenEn?, GroupCode, ApprovalGroup int, SignerRole, InitialsChain?, NduqNote?, IsActive, SortOrder}. Create/Update command = 10 field (không Id) `:96-106` / `:155-166`. `ApprovalGroup` InclusiveBetween(1,8) `:118`. PUT check `id != body.Id` → 400 ⇒ FE phải gửi kèm `id`.
|
||||
- Khuôn FE: `fe-user/src/pages/master/CatalogsPage.tsx` 321 dòng — SHA **IDENTICAL** với fe-admin (`6f482614…`) ⇒ viết 1 lần rồi `cp`.
|
||||
- Menu: BE `MenuKeys.cs:28` const `ContractCatalog` (VÀO `All` :173) + `DbInitializer` seed row `(ContractCatalog, "Danh mục Hợp đồng", parent Catalogs, order 5, icon "FileSpreadsheet")`.
|
||||
- `Layout.tsx` + `menuKeys.ts` DIVERGE 2 app (SHA khác) ⇒ mirror TAY, không cp.
|
||||
- Sửa `CatalogsPage.tsx` fe-user (kind thứ 5) → `cp` fe-admin → menuKeys ×2 → Layout staticMap ×2 → build ×2. XONG.
|
||||
|
||||
## File tạo/sửa (6 file, 0 file mới — 3 file/app, đối xứng)
|
||||
|
||||
| File | Δ | Nội dung |
|
||||
|---|---|---|
|
||||
| `fe-user/src/pages/master/CatalogsPage.tsx` | +201/−68 (321→454 dòng) | kind thứ 5 |
|
||||
| `fe-admin/src/pages/master/CatalogsPage.tsx` | +201/−68 | `cp` y nguyên — SHA-pair |
|
||||
| `fe-user/src/lib/menuKeys.ts` | +4 | `ContractCatalog: 'ContractCatalog'` |
|
||||
| `fe-admin/src/lib/menuKeys.ts` | +4 | idem (2 file DIVERGE sẵn ⇒ edit tay, không cp) |
|
||||
| `fe-user/src/components/Layout.tsx` | +4 | staticMap `ContractCatalog: '/master/catalogs/contract-catalog'` |
|
||||
| `fe-admin/src/components/Layout.tsx` | +4 | idem |
|
||||
|
||||
### Chi tiết `CatalogsPage.tsx` (khuôn KIND_CONFIG, ADD-KIND playbook)
|
||||
1. `type Kind` += `'contract-catalog'` · `KINDS` += (sub-tab thứ 5 tự hiện).
|
||||
2. `FieldDef` nới 3 thứ: `type` += `'number' | 'select'`, `options?: {value:number;label:string}[]`, `numeric?: boolean`.
|
||||
3. `KIND_CONFIG['contract-catalog']` — icon `FileSpreadsheet` (KHỚP icon BE seed), 10 field ĐÚNG 10 field của `CreateContractCatalogEntryCommand`: code · groupCode · tenVi · tenEn · approvalGroup(select N1–N8, numeric) · sortOrder(number, numeric) · signerRole · initialsChain · nduqNote(textarea) · isActive(checkbox). 4 field `*` = 4 `NotEmpty` của validator BE (`ContractCatalogFeatures.cs:114-120`).
|
||||
4. `columns` (trước giờ là config CHẾT, không ai đọc) → thành nguồn `<thead>` cho nhánh contract-catalog: 8 cột {Mã · Tên VN · Tên EN · Nhóm · Nhóm duyệt · Vai ký chính · Ký nháy · Trạng thái}.
|
||||
5. `<tbody>` nhánh riêng (4 kind cũ giữ NGUYÊN byte cell cũ) · `colSpan` hardcode 6 → `colCount` tính theo kind.
|
||||
6. `CatalogRow.name` `string` → `string?` (contract-catalog dùng `tenVi`) + helper `rowLabel()` cho confirm xóa (trước là `row.name` → sẽ in "undefined").
|
||||
7. `ApprovalGroupBadge` — Pattern 14: 8 chuỗi class ĐẦY ĐỦ trong `APPROVAL_GROUP_BADGE`, cycle `(value-1) % 8`, KHÔNG interpolate.
|
||||
8. `buildBody` — field `numeric` ép `Number()`, rỗng → **0 chứ không null** (BE `int` non-nullable, `null → int` là System.Text.Json ném). Nhánh cũ (`'' | undefined → null`) giữ nguyên cho field còn lại.
|
||||
9. `openCreate` — select mặc định option đầu (N1) để không POST rỗng dính `InclusiveBetween(1,8)`.
|
||||
10. `PageHeader description` đổi theo kind (giữ signature title/description, không thêm prop).
|
||||
|
||||
### Pattern 16-bis — 4 chỗ
|
||||
| # | Chỗ | Trạng thái |
|
||||
|---|---|---|
|
||||
| 1 | Page/types | ✅ `CatalogsPage.tsx` ×2 (0 file types mới — row là `Record<string, unknown>`) |
|
||||
| 2 | `App.tsx` Route | ✅ **KHÔNG cần** — `/master/catalogs/:kind` có sẵn (`fe-user/src/App.tsx:63`, `fe-admin/src/App.tsx:69`), kind mới đi chung |
|
||||
| 3 | `lib/menuKeys.ts` | ✅ ×2 |
|
||||
| 4 | `Layout.tsx` staticMap | ✅ ×2 — chỗ DỄ MISS (gotcha #50) |
|
||||
|
||||
## Kết quả build
|
||||
- (ĐANG LÀM)
|
||||
- `fe-user`: **PASS** — `tsc -b && vite build`, 1950 modules, `dist/assets/index-C5SIaqt5.js` 1,634.97 kB, ✓ built in 21.57s, **0 TS error**.
|
||||
- `fe-admin`: **PASS** — `dist/assets/index-DLUxeB3d.js` 1,718.77 kB, ✓ built in 9.52s, **0 TS error**.
|
||||
- Warning: `@import` phải đứng trước rule + chunk >500 kB + INEFFECTIVE_DYNAMIC_IMPORT `realtime.ts` — **pre-existing cả 3**, không phải do K1.
|
||||
- SHA-pair `CatalogsPage.tsx`: `d71a9e3bb17b835b85b4f3467905af2ab414f52e3ec0c58e79d55ef57673985a` ×2 IDENTICAL (trước sửa: `6f482614…` ×2).
|
||||
- Chứng Pattern 14 có răng (class KHÔNG bị purge) — grep CSS đã build: `bg-sky-50` `bg-violet-50` `bg-teal-50` `bg-orange-50` `border-indigo-200` `text-rose-700` có mặt ở CẢ `fe-user/dist/assets/index-BjUevXzu.css` LẪN `fe-admin/dist/assets/index-B62-9mVN.css`.
|
||||
- `git diff --stat` đối xứng: 201/201 · 4/4 · 4/4 → 350 insert / 68 delete / 6 file.
|
||||
|
||||
## Ngoài phạm vi (KHÔNG đụng — đúng lệnh)
|
||||
- 0 file `src/Backend/**` (chỉ Read `ContractCatalogController.cs` + `ContractCatalogFeatures.cs` để lấy shape).
|
||||
- 0 file pipeline/khkk (K4/K5). 0 commit, 0 push.
|
||||
- KHÔNG sửa `agent-memory/*` (spawn-record trả về qua `memoryDelta`, em main harvest).
|
||||
|
||||
END impl-fe-k1 — 6 file · build ×2 PASS
|
||||
|
||||
@ -1,7 +1,32 @@
|
||||
# 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)
|
||||
### §0 Baseline ĐO TƯƠI trước khi viết (không tin số đề bài) — XONG
|
||||
Lệnh: `dotnet test SolutionErp.slnx --nologo --verbosity minimal -p:BuildInParallel=false -maxcpucount:1`
|
||||
```
|
||||
Domain: Failed 0, Passed 45, Total 45
|
||||
Infra : Failed 1, Passed 544, Total 545
|
||||
```
|
||||
⇒ **baseline 590 test = 589 PASS / 1 FAIL**. Đề bài ghi "590/590" — LỆCH 1.
|
||||
🔴 **FAIL KHÔNG liên quan K1:** `Forms.DocxRendererTests.RenderAsync_UnknownPlaceholder_KeepsLiteralToken_NoCrash`
|
||||
→ `System.OutOfMemoryException` tại `WordprocessingDocument.AddMainDocumentPart()` (DocxRendererTests.cs:26).
|
||||
Nghi flake do áp lực RAM (fan-out nhiều agent chạy song song), KHÔNG phải regression code.
|
||||
Sẽ đo lại RIÊNG test đó ở §3 để phân biệt flake ⟂ vỡ thật.
|
||||
|
||||
### §1 Đọc nguồn — XONG
|
||||
- `sub-invest-fable-b2-cum1.md:59-75` §K1.e (5 case) + §K1.f (checklist acceptance)
|
||||
- Code THẬT (test theo CODE, không theo spec):
|
||||
· `Domain/Master/Catalogs/ContractCatalogEntry.cs:13-25` — 10 cột
|
||||
· `Persistence/Configurations/ContractCatalogEntryConfiguration.cs:27-29` — UNIQUE filtered `[IsDeleted] = 0` + index ApprovalGroup + query filter
|
||||
· `DbInitializer.cs:3163-3324` `SeedContractCatalogAsync(ApplicationDbContext, ILogger)` **private static** → gọi qua REFLECTION (khuôn S67)
|
||||
· `DbInitializer.cs:3293-3296` — `IgnoreQueryFilters()` khi dò existing (né #75/#76)
|
||||
· `Application/Master/Catalogs/ContractCatalogFeatures.cs` — List/Get/Create/Update/Delete + 2 validator `InclusiveBetween(1,8)`
|
||||
· `Api/Controllers/ContractCatalogController.cs:20-23` — `[Authorize]` class + `Roles="Admin"` cho 3 verb ghi (**0 policy key**)
|
||||
· `MenuKeys.cs:28-32 + :173` — const `ContractCatalog` **VÀO `All`**; `DbInitializer.cs:1776` menu row parent `Catalogs`
|
||||
|
||||
## PHẦN 2 (relaunch)
|
||||
|
||||
### §2 Viết file test — ĐANG LÀM
|
||||
Relaunch 14:5x. Lượt 1 chết sau §1 (contract đã note đủ → KHÔNG đọc lại code trừ khuôn fixture).
|
||||
Kế hoạch: `tests/SolutionErp.Infrastructure.Tests/Services/ContractCatalogTests.cs` — 6 test T1..T6.
|
||||
|
||||
Reference in New Issue
Block a user