From 9a69dae859d6d1efdedc67f87987ca15c74a3a69 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Fri, 31 Jul 2026 17:38:48 +0700 Subject: [PATCH] wal: flush 20260731T1738 --- .../sub-implbe-k3.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-implbe-k3.md b/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-implbe-k3.md index fee0772..42f4b1b 100644 --- a/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-implbe-k3.md +++ b/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-implbe-k3.md @@ -62,3 +62,39 @@ K3-BE: IN-PROGRESS — bước-0 XONG (lead), §1-8 p2 đang chạy (W1 S161 F-8 containment). Seeder ghi entity TRỰC TIẾP nên **không bị chặn**, nhưng nếu admin bấm "tạo version mới" qua Designer thì cờ rơi về false. Tôi vẫn set `true` theo lệnh (OG-3/OG-9) + ghi comment đúng câu lead giao; **nhịp sau cùng wave** port nhánh service + (nếu owner chốt) gỡ ép-false ở `:381`. + +--- + +# §2 VIỆC A — `SeedKhkkGroupWorkflowsAsync` — DONE + +**File:** `src/Backend/SolutionErp.Infrastructure/Persistence/DbInitializer.cs` (2 chỗ) +- `:160-171` — gọi trong `InitializeAsync`, **UNGATED** (ngoài `if (!demoSeedDisabled)`), đặt ngay sau cụm + 4 seeder WorkflowApps V2 và trước `WarnDefaultAdminPasswordAsync`. Comment nêu gotcha #51. +- `:520-…` — thân method, ngay sau `SeedSampleVehicleBookingWorkflowV2Async`. + +**Đã làm đúng lệnh:** +- 8 workflow `KHKK-N1..KHKK-N8`, `ApplicableType = ContractSigningPlan` (=10), `Version=1`, + `IsActive=true`, `IsUserSelectable=true`, `Name = $"Duyệt KHKK — Nhóm {n}"` (em-dash + khoảng trắng + y như lệnh), `ActivatedAt=UtcNow`. +- Idempotent per-Code literal theo lệnh: `if (await db.ApprovalWorkflows.AnyAsync(w => w.Code == code)) continue;` +- 3 Steps Order 1/2/3, Name `"Phòng Cung Ứng"` / `"P. Kiểm soát Chi phí"` / `"Ban Giám đốc"`, + `DepartmentId` = hint theo mã phòng `PRO` / `CCM` / `BOD` (`SeedDepartmentsAsync:2744`; nullable ⇒ phòng + vắng cũng không chặn). +- Levels đúng roster §0: Step1 C1 OR-4 + C2 `tra.bui`; Step2 C1 OR-4 + C2 `chuong.phan`; Step3 C1 `truong.nguyen`. +- `AllowApproverFinalize = true` **CHỈ** ở Step2/Cấp2 (`chuong.phan`) — ghi comment nguyên câu lead giao + (OG-3/OG-9 + "nhánh service port ở nhịp sau CÙNG WAVE trước push nên không phải config-lie #78"). + Đặt PER-ROW (khuôn F5/F6) nên chỉ 1 người mang cờ, không phát cho cả Cấp. +- Resolve email→user 1 lượt (11 email `Distinct` OrdinalIgnoreCase) qua `userManager.FindByEmailAsync`; + thiếu ⇒ log warning gộp + **bỏ slot**, KHÔNG throw. Cấp 0 người ⇒ bỏ Cấp; Bước 0 Cấp ⇒ bỏ Bước + warn; + workflow 0 Bước ⇒ VẪN tạo + warn (đúng lệnh). +- Log: `logger.LogInformation("Seeded {Count} KHKK group workflows (K3 SP-002)", seeded)` — chỉ khi `seeded > 0`. + +**2 quyết định nhỏ tôi tự chốt (khai để lead soi):** +- ⚠️ **KHÔNG dùng khuôn `AnyAsync(w.ApplicableType == …)`** của 6 seeder mẫu: 8 workflow DÙNG CHUNG type-10 + ⇒ check-theo-type sẽ chặn 7 nhóm còn lại ngay sau khi N1 vừa tạo. Đây là chỗ khuôn cũ **không** copy được. +- **Order của Cấp đánh LẠI liên tục** (`levelOrder++` chỉ khi cấp có người) thay vì cứng 1/2 — nếu dev-DB thiếu + đúng người Cấp 1 thì workflow còn mỗi Cấp Order=2, vi phạm ràng buộc sequential của Designer + (`ApprovalWorkflowV2AdminFeatures.cs` `HaveSequentialOrders`). Trên prod (đủ 11 người) kết quả **y hệt** 1/2. + +**Build chunk A:** `dotnet build src/Backend/SolutionErp.Infrastructure/SolutionErp.Infrastructure.csproj` +→ **0 Warning / 0 Error**.