Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-implbe-k3.md
2026-07-31 17:38:48 +07:00

7.8 KiB
Raw Blame History

K3-BE: IN-PROGRESS — bước-0 XONG (lead), §1-8 p2 đang chạy

sub-implbe-k3 — K3 BACKEND (S165, wave 3/8: 8 workflow nhóm + finalize + sweep)

🔴 KHAI VẾT: p1 wf_a04124a7-0fe = class engine-process-exit (35 tool-use/458s nhưng **0 delta đĩa

  • 0 artifact + return rỗng** — lượt chạy coi như chưa từng tồn tại; #53 tally cả wave). Bước-0 dưới đây = LEAD tự chạy (ssh + sqlcmd trực tiếp), p2 seed từ bảng ĐÃ VERIFY này, không cần ssh lại.

§0 [LEAD] FAIL-CLOSED verify đội-hình QT-DN-V2-001 LIVE — PASS

  • Instance prod = localhost\SQLEXPRESS (named instance — -S localhost/tcp:1433 đều fail; ghi lại cho mọi lane sau đỡ dò). Windows-auth -E qua ssh vietreport-vps chạy được.
  • ApprovalWorkflows WHERE Code='QT-DN-V2-001' = 3 row: 2 archived (IsActive=0) + 1 LIVE (IsActive=1), ApplicableType=1 (Duyệt NCC/PE — nguồn đội-hình, đúng OG-2 + note owner slot-54 "lấy đúng bộ người duyệt đang cấu hình ở workflow Duyệt NCC prod"). TotalWf active toàn hệ = 7.
  • ROSTER bản LIVE (nguyên văn sqlcmd, mojibake console đã chuẩn hoá dấu theo email đã biết):
Bước Dept Cấp Email Tên
1 «Phòng 1» Phòng Cung Ứng (PRO) 1 (OR-4) phuong.nguyen@solutions.com.vn Nguyễn Thị Bích Phượng
1 Phòng Cung Ứng 1 long.chau@solutions.com.vn Châu Tạ Kim Long
1 Phòng Cung Ứng 1 duy.nguyen@solutions.com.vn Nguyễn Văn Duy
1 Phòng Cung Ứng 1 binh.lethanh@solutions.com.vn Bình Lê Thanh
1 Phòng Cung Ứng 2 tra.bui@solutions.com.vn Bùi Lê Thủy Trà
2 «Phòng 2» P. Kiểm soát Chi phí (CCM) 1 (OR-4) luu.tran@solutions.com.vn Trần Xuân Lưu
2 P. Kiểm soát Chi phí 1 truong.letrandang@solutions.com.vn Lê Trần Đăng Trường
2 P. Kiểm soát Chi phí 1 binh.le@solutions.com.vn Lê Văn Bình
2 P. Kiểm soát Chi phí 1 nguyen.ho@solutions.com.vn Hồ Thị Nữ Nguyên
2 P. Kiểm soát Chi phí 2 chuong.phan@solutions.com.vn Phan Văn Chương (TP.CCM — giữ cờ finalize OG-3/OG-9)
3 «Phòng 3» Ban Giám đốc (CEO) 1 truong.nguyen@solutions.com.vn Nguyễn Văn Trường
  • Vá-11 danh-tính (phân giải bằng dept trên bản LIVE): truong.letrandang (CCM C1) ⟂ truong.nguyen (BGĐ C1 = CEO) — 2 người khác dept, không nhầm; binh.lethanh (PRO C1) ⟂ binh.le (CCM C1) — khác dept, không nhầm. Cặp "tring.le"/"thanh.lethanh" trong câu-đố spec KHÔNG xuất hiện trên roster LIVE ⇒ là bẫy chính-tả từ ảnh, roster email là chân lý.
  • Mô-hình 3 trạm PRO → CCM → CEO với OR-of-N cấp 1 mỗi trạm + cấp 2 = trưởng phòng. Seed 8 workflow KHKK-N1..N8 mirror ĐÚNG cấu trúc này (3 Steps × Levels như bảng), resolve user theo EMAIL.

(§1-8 p2 ghi tiếp bên dưới)


§1 [p2] KẾ HOẠCH (ghi TRƯỚC khi code — 3 dòng)

  1. ADbInitializer.cs: thêm SeedKhkkGroupWorkflowsAsync(db, userManager, logger) (UNGATED, đặt sau cụm 4 seeder WorkflowApps V2 ở InitializeAsync), mirror khuôn SeedSampleContractWorkflowV2Async; resolve 11 email → dict 1 lượt, rồi loop N=1..8 tạo KHKK-N{n} (type-10) 3 Steps × Levels theo roster §0.
  2. BMenuKeys.cs: +8 const AwV2_KhkkN1..N8 + vào All (ràng buộc T6: key ∈ All BẮT BUỘC có menu-row) ⇒ DbInitializer.SeedMenuTreeAsync: +8 row con dưới ApprovalWorkflowsV2 (order 3..10), idempotent per-Key.
  3. Cdotnet build SolutionErp.slnx (0W/0E) + dotnet test SolutionErp.slnx full (baseline 609/0) + đếm MenuKeys.All bằng lệnh máy → ghi DELTA.

Đo TRƯỚC khi sửa (baseline, lệnh máy chạy ở §4): MenuKeys.All hiện = ? (đo ở §4, không đoán).

🔴 2 lệch phát hiện lúc khảo sát (khai ngay, KHÔNG tự quyết):

  • L1 — "vùng seed workflow type-10 hiện có (W3 S161)" KHÔNG TỒN TẠI. grep ContractSigningPlan DbInitializer.cs = 0 hit (chỉ có SeedKeHoachKyKetAccessAsync = seed quyền, không phải workflow). ⇒ Không có khuôn type-10 để mirror; tôi mirror khuôn gần nhất cùng lớp = SeedSampleContractWorkflowV2Async (:226) / SeedSampleProposalWorkflowV2Async (:276) — cùng cách dựng ApprovalWorkflow + Steps + Levels.
  • L2 — AllowApproverFinalize bị ÉP false server-side cho type-10 ở đường Designer. ApprovalWorkflowV2AdminFeatures.cs:380-381: AllowApproverFinalize = typeEnum != ...ContractSigningPlan && l.… (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.csproj0 Warning / 0 Error.