Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-k8-dryrun.md

123 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

K8-DRYRUN: ĐANG CHẠY — B0 PASS (backup 26,6MB + roster LIVE + login admin OK); B1.. đổ ruột liên tục bên dưới
# sub-k8-dryrun — K8 dry-run E2E toàn trình (S168, 2026-08-01)
> Mandate owner @S168 (verbatim): *"Chạy dry-run hết luôn đi rồi tao giao tiếp plan khác"*.
> Kịch bản = spec-cụm3 §③ K8 + bảng B0-B16 (`sub-invest-fable-b2-cum3.md` K8.1) + **vá-9..15 spec-final THẮNG nền**.
> 🔴 Vá-12 owner-ratified @S164 *"tạo PE Test SOLUTION-PE-1,2,3… không test trên phiếu thật"* ⇒ **bộ test RIÊNG** (Project+NCC+gói ZZTEST/SOLUTION-PE-{n}), **KHÔNG đụng `PE/2026/A/049`** — câu giờ-G K8.2 của bản nền coi như ĐÃ trả.
> Người bấm mọi bước hôm nay = **admin (duyệt thay — SignedByUserId track, banner "Admin duyệt thay" by-design)**; cột "Ai (thật)" trong form = roster LIVE để buổi chạy với người thật dùng lại.
## B0 — PRE-FLIGHT (fail-closed) — ✅ PASS 16:2x-16:3x +07
- (i) **Backup prod:** `C:\Backups\SolutionErp\SolutionErp_preK8_S168.bak` — 27.877.888 B @ 2026-08-01 16:28 (BACKUP DATABASE 3393 pages OK). *(Script `scripts/backup-sql.ps1` default `D:\` — VPS KHÔNG có ổ D ⇒ dùng `C:\Backups`; default ĐÃ VÁ `C:\` @S168 cùng lượt.)*
- (ii) **Workflow LIVE (sqlcmd -E; ⚠️ `$env:PROD_DB_PASSWORD` KHÔNG tồn tại cả 3 scope trên VPS — persona-note stale cùng lớp F-9):**
- type-1 PE: `QT-DN-V2-001` active+selectable · 3 trạm (P1: 4NV L1 + tra.bui L2[SkipToFinal,Delete] · P2: 4NV L1 + **chuong.phan L2 [Finalize=1,SkipToFinal,Delete]** · P3: truong.nguyen [SkipToFinal]).
- type-10 KHKK: **đủ 8 nhóm N1-N8 active**; `KHKK-N4` 3 trạm 11 người (Cung ứng: 4NV+tra.bui · Kiểm soát CP: 4NV+**chuong.phan [Finalize=1]** · BGĐ: truong.nguyen) — khớp anchor OG-3/OG-9.
- type-3 HĐ: `QT-HD-V2-001` active — **1 trạm 1 người: binh.le (Bước 1 - Phòng CCM)**.
- (ii-b) Catalog: `ContractCatalogEntries` = **86** dòng; nhóm-4 mẫu B1-01 Đá · B1-02 Cát · B1-03 Cọc tràm · B1-04 Bê tông · **B1-05 Xi măng (chọn cho line test)** · B1-06 Thép.
- (iii) Dữ liệu test sẵn có: Projects ZZTEST = **0** · Suppliers TEST = **0** ⇒ TẠO MỚI qua API (GĐ0 dưới). Contracts prod = **0** (HĐ dry-run sẽ là HĐ ĐẦU TIÊN trên prod — seq cháy thuộc cặp prefix TEST, vô hại data thật).
- (iv) **Dặn team:** em KHÔNG có kênh Zalo/email — thay bằng ZZTEST-prefix mọi bản ghi + mục này để anh nhắn team *"notification phiếu ZZTEST trong hôm nay — bỏ qua"*. KHAI trade-off, không im.
- (v) Login API prod: `POST /api/auth/login` admin OK (accessToken 468c — field `accessToken` đúng bài S160).
## B0-FORM 14 dòng {bước · người THẬT (roster LIVE) · tài khoản · ai bấm hôm nay} — vá-9 fail-closed
| B | Ai (thật, theo roster LIVE) | Tài khoản | Hôm nay |
|---|---|---|---|
| B1-B3 | BCH drafter (đại diện Cung ứng: Nguyễn Văn Duy) | duy.nguyen@solutions.com.vn | admin (tạo thay) |
| B4 | Trạm-1 PE/KHKK — 1 trong {duy.nguyen · binh.lethanh · long.chau · phuong.nguyen} + L2 tra.bui | (4+1 tài khoản trên) | admin duyệt thay |
| B5 | Trạm-2 — 1 trong {luu.tran · nguyen.ho · binh.le · truong.letrandang} | (4 tài khoản) | admin duyệt thay |
| B6 | **TP.CCM Phan Văn Chương (Finalize)** | chuong.phan@solutions.com.vn | admin duyệt thay (tick finalize) |
| B7 | CEO Nguyễn Văn Trường (nhánh B) | truong.nguyen@solutions.com.vn | admin duyệt thay |
| B8 | BCH/Admin kiểm khóa | — | admin |
| B9 | Người có `Contracts.Create` (câu III default: Drafter/Procurement/Admin — seeder K7 CanCreate=3) | — | admin |
| B10 | Người bấm B9 | — | admin |
| B11 | Approver HĐ: **Lê Văn Bình** (QT-HD-V2-001 trạm duy nhất) | binh.le@solutions.com.vn | admin duyệt thay |
| B12 | HRA/CCM (HardCopyActorRoles) | — | admin |
| B13 | Bất kỳ + Admin (mở cây) | — | admin |
| B14 | Lead chốt sổ | — | lead |
⇒ 14/14 dòng CÓ CHỦ — fail-closed ĐẠT (không dòng nào trống).
## Nhật ký bước (đổ ruột liên tục — ID ghi TẠI CHỖ cho rollback vá-11/13)
### 🔴 PHÁT HIỆN TRƯỚC GIỜ CHẠY — BLOCKER toàn trình: Lines-editor KHÔNG TỒN TẠI (vá tại chỗ @S168)
Truy vết trước khi bấm B1 (đúng tinh thần "K8 lộ wave thiếu"):
- `ContractSigningPlanFeatures.cs` auto-gen line mồi `CatalogEntryId = null` + comment HẸN *"Người soạn gán sau qua `UpdateContractSigningPlanLineCommand`"***command đó chỉ tồn tại TRONG COMMENT** (grep toàn src + FE = 0 impl, 0 route, 0 call).
- `ContractSigningPlanWorkflowService.SubmitAsync` (vá-5) **CHẶN THẬT** line null: `"Còn dòng chưa gán hạng mục…"` + đếm-so-khớp nhóm.
- FE `KhkkDetailPage` cột Hạng mục tự khai *"Đường GÁN (Lines-editor) = K4b"* — nhưng K4b THẬT ship việc khác (`88e7ecf` = nối `?group=` sidebar, đo `git show --name-only`). ⇒ mảnh rơi giữa build-order.
- Hệ quả nếu không vá: **MỌI phiếu KHKK tạo sau K2 kẹt Nháp vĩnh viễn** — dry-run chết ở B3. Đây chính là chỗ cicd-K2 khai *"mục-4 chân-lý-rỗng — đo lại khi K8 đẻ phiếu thật"*.
**Vá @S168 (BE + FE ×2 app + 3 test):** `UpdateContractSigningPlanLineCommand(PlanId, LineId, CatalogEntryId)` handler (EnsureDraftEditable + fail-fast entry sống/đúng-nhóm 409 + denorm `TenHangMuc` + changelog Line) · route `PUT /contract-signing-plans/{id}/lines/{lineId}` policy `KeHoachKyKet.Update` · FE select gán tại bảng (Nháp/TraLai, khoá dòng đã bắc cầu HĐ, options lọc `?approvalGroup=`) mirror SHA-pair `21e0ca0507d4` ×2 app · 3 Fact (dương gán→submit-QUA · âm khác-nhóm 409 · âm phase). Gate + commit riêng trước khi chạy chuỗi.
### GĐ0 — dựng bộ test — ✅ PASS (script `k8run.py gd0`, state `k8-state.json` scratchpad)
| Vật | ID |
|---|---|
| Project `ZZTEST-K8` "ZZTEST Du an dry-run K8 (SOLUTION-PE)" | `9c6caa7a-22b9-4482-bc74-2ef36fbebc54` |
| Supplier `ZZTEST-NCC-K8` | `10b60f58-1bb0-4164-b191-3cb9af3896fe` |
| WorkItem `ZZTEST-WI-K8` | `a29c7932-411c-4763-9ca6-5546798c3d5c` |
| Catalog line-test | B1-05 Xi măng `69a6db3a-30b1-4289-878b-a364a1fd1eab` |
| Workflow ids | PE `8a0aa922…` · KHKK-N4 `bf90b962…` · HĐ `12aee3bf…` |
### GĐ1 — PE 2 nhánh — ✅ TRỌN (B1-B7 phần PE)
- **PE-1 nhánh A = `PE/2026/A/052`** (`4e4ad413-30cb-4eda-b5cf-31f2936e8ec2`; supplier-row `512f6b41` · detail `55285053` · quote 110tr-VAT isSelected · Bảng-so-sánh att `50bbcf46`): submit → 3 lượt trạm → lượt 4 **giá-chốt NCC 110tr + finalize tại CCM (chuong.phan)****DaDuyet KHÔNG qua CEO** (OG-9 nhánh A chứng ✓) → winner ZZTEST-NCC ✓.
- **PE-2 nhánh B = `PE/2026/A/053`** (`a53db8b9-df60-42d0-92c0-e2ca4c80f2e5`; row `9e3d8060` · detail `1f98f925` · att `4a79abfd`): submit → **5 lượt ĐỦ đường** với `applyLevelFinalize=false` ở mọi lượt (checkbox opt-out F-1 `7a903cf` chứng chạy thật) ⇒ qua **CEO Trường** → DaDuyet → winner ✓.
- Sự-cố script tự bắt + sửa dọc đường (đều là THUỐC THỬ tốt cho form B0 buổi người-thật): ① PE detail đòi `GroupCode/GroupName` required · ② `QuoteBody.BgVat/ChuaVat` = decimal non-null · ③ submit-guard đòi đính kèm **Bảng so sánh** (purpose=4) · ④ cấp cuối đòi **chọn giá chốt** (Ncc/ProMin/ProMax/Ccm/ProMinMax — Mig 66) · ⑤ auth rate-limit **429** khi login mỗi-stage ⇒ cache token (JWT 1h) vào state · ⑥ 1 phiếu nháp orphan (script fail giữa) ⇒ **DELETE 204 dọn liền** — allow-list Nháp xoá được, đúng thiết kế.
### GĐ2+ (KHKK → bridge → HĐ → bản-cứng → QĐ9) — CHỜ deploy line-editor (commit + push + cicd) rồi chạy stages `khkk1…qd9-2`
### GĐ2→GĐ4 + QĐ9 — ✅ TRỌN CẢ 2 NHÁNH (sau deploy #444 line-editor live)
| Bước | Nhánh A | Nhánh B |
|---|---|---|
| KHKK tạo + **gán hạng mục qua endpoint MỚI** | `KHKK/2026/001` (`9cc64a5e`), line `776faa92` ← B1-05 ✓ | `KHKK/2026/002` (`3b11f7d3`), line `0a9e67a0` ✓ |
| Duyệt | **4 lượt — finalize tại Chương (KHÔNG qua BGĐ)** ✓ OG-9 | **5 lượt — QUA ĐỦ BGĐ/CEO** (`applyLevelFinalize=false` mọi lượt — checkbox opt-out F-1 sống) ✓ |
| DaDuyet | phase=3, approvedTổng **110.000.000** chốt tại choke-point | phase=3, approvedTổng 110.000.000 |
| Bridge K7 → HĐ | HĐ `47b453d3` — mã RG-001 tự sinh **`ZZTEST-K8/NCC/SOL&ZZTEST-NCC-K8/01`**, `giaTri == ApprovedAmount` = 110tr ✓ | (không bridge — spec chỉ cần 1 nhánh) |
| Duyệt HĐ | submit → 1 lượt (binh.le trạm duy nhất) → **DaPhatHanh (9)** — HĐ ĐẦU TIÊN trên prod, là ZZTEST đúng chủ đích | — |
| GĐ4 bản cứng | upload SealedCopy purpose=3 `78be7327`**LIST `hasSealedCopy=True`** ✓ (field là EXISTS tầng LIST — detail đọc `attachments[]`) | — |
| B13 mối nối cây | `khkk.line.contractId → 47b453d3` ✓ · `pe.contractId → 47b453d3` (forward-provision K5) ✓ · `hasSealedCopy` ✓ — đúng 3 nguồn `usePipelineStages:293-299` đọc | line.contractId = null (đúng — chưa bridge) |
| **QĐ9 freeze (đo 2 vế/nhánh)** | (a) sửa quote nguồn PE DaDuyet → **409 "không thể chỉnh sửa Section 2"** = nguồn khoá từ tầng dưới · (b) catalog-rename `Xi măng→Xi măng (ZZTEST QD9)` 204 → **line GIỮ 'Xi măng'** (denorm thắng join-ngược — bit TRƯỢT-ĐƯỢC thật) → restore 204 nguyên trạng | (a) 409 y hệt · (b) rename→GIỮ→restore ✓ |
🔸 Khai đo: **B13 đo ở tầng API-mối-nối** (3 con trỏ cây đọc), KHÔNG chụp UI — dry-run kỹ thuật admin-duyệt-thay; buổi người-thật theo form B0 sẽ chụp `ss-k8-*` + bấm trên UI thật. QĐ9 nguyên bản ("đổi nguồn → số không đổi") nâng thành bằng chứng MẠNH HƠN ở vế (a): cửa đổi nguồn bị khoá hẳn 409.
### B15 — SỔ BẢN-GHI-VĨNH-VIỄN + seq cháy (rollback theo ID, vá-11/13)
- **BẤT TỬ by-design (sống chung, nhận diện ZZTEST/SOLUTION-PE):** PE `PE/2026/A/052` + `PE/2026/A/053` (DaDuyet) · KHKK `KHKK/2026/001` + `/002` (DaDuyet — HỐ-1-KHKK: chiếm slot (PE,N4); PE là test nên vô hại) · HĐ `ZZTEST-K8/NCC/SOL&ZZTEST-NCC-K8/01` DaPhatHanh (HỐ-1 numeric-guard chặn xóa; muốn dọn = sqlcmd soft-delete CHỜ ANH GẬT — lệnh: `UPDATE Contracts SET IsDeleted=1 WHERE Id='47b453d3-…'` + NULL lại `Line.ContractId`/`pe.ContractId` nếu gỡ).
- 🔴 **Seq cháy KHÔNG thu hồi:** `KHKK/2026` seq ăn **001+002** (global-per-year — phiếu THẬT đầu tiên sẽ là 003, anh biết trước kẻo thắc mắc) · PE `2026/A` seq ăn 052+053 · mã HĐ seq 01 thuộc CẶP PREFIX TEST (vô hại prefix thật).
- Master test GIỮ làm bộ tái dùng (đúng tinh thần SOLUTION-PE-{n} owner ratify): Project `ZZTEST-K8` · Supplier `ZZTEST-NCC-K8` · WorkItem `ZZTEST-WI-K8`.
- Đã dọn trong-phiên: phiếu nháp orphan `0430d99f` DELETE 204 · catalog B1-05 restore nguyên trạng ×2 lần đo.
- Notification đã bắn tới roster thật trong lúc duyệt-thay — mọi tên mang ZZTEST; **anh nhắn team "phiếu ZZTEST hôm nay bỏ qua"** (B0.iv khai: em không có kênh Zalo/email).
- B16 rollback: KHÔNG kích hoạt (0 lần hỏng-phải-dừng).
END sub-k8-dryrun — VERDICT=**K8 DRY-RUN PASS TOÀN TRÌNH 2 NHÁNH** (GĐ1 PE 2 phiếu · GĐ2 KHKK 2 phiếu qua endpoint line MỚI · K7-bridge → GĐ3 HĐ DaPhatHanh · GĐ4 bản-cứng · QĐ9 4/4 vế · B15 sổ-ID đủ) — 1 blocker THẬT phát hiện + vá + ship trong phiên (Lines-editor) · 8 thuốc-thử guard ghi lại cho buổi người-thật
---
## BỘ FIXTURE TEST (owner lệnh @S168 sau dry-run: "để là ADMIN_TEST… tạo luôn master data test… 1 bộ User test… chữ test trước… mỗi bộ 2-3 thôi")
🔴 **LUẬT chốt từ lệnh này: mọi test từ nay chạy trên FIXTURE TEST — CẤM đụng master data / user thật.** (Dry-run K8 đã theo đúng — bộ ZZTEST.)
**Users (password chung `Test@12345678` — policy prod đòi ≥12 ký tự; đổi sau buổi test nếu anh muốn):**
| FullName | Email | Roles | Id |
|---|---|---|---|
| **ADMIN_TEST** | admin_test@solutions.com.vn | Admin | `f0151cc7-32ad-4ec0-5da7-08deefbe0ee9` |
| TEST Nhân viên Soạn thảo | test.drafter@solutions.com.vn | Drafter + Procurement | `79de0ef1-4658-41cd-5da8-08deefbe0ee9` |
| TEST Người duyệt | test.approver@solutions.com.vn | CostControl + DeptManager | `f4d02ccb-7466-4d7e-5da9-08deefbe0ee9` |
Verify: login ADMIN_TEST OK (token 471c) · 3/3 hiện `GET /users?search=TEST`. ⚠️ 2 user TEST muốn **DUYỆT thật** thì phải được gắn vào workflow qua **Designer — ANH TỰ TAY** ((54)-FINAL, em không đụng workflow); role hiện tại đủ THẤY màn.
**Master data test (cộng bộ ZZTEST sẵn có từ GĐ0):**
| Bộ | Thành viên (2-3/bộ) |
|---|---|
| Department (1) | TEST Phòng thử nghiệm `ZZTEST-PB``53044453…` (3 user TEST gắn vào đây) |
| Projects (2) | `ZZTEST-K8` (GĐ0) · `ZZTEST-K8-2` "TEST Dự án thử nghiệm 2" — `b1a77d48…` |
| Suppliers (3) | `ZZTEST-NCC-K8` (NCC, GĐ0) · `ZZTEST-NTP-K8` (Thầu phụ) — `3c41bd4c…` · `ZZTEST-TD-K8` (Tổ đội) — `517f62c9…` |
| WorkItems (2) | `ZZTEST-WI-K8` (GĐ0) · `ZZTEST-WI-K8-2``54ced5c2…` |
Không bơm test vào `ContractCatalogEntries` (danh mục SP-002 chuẩn 86 dòng dùng chung — QĐ9 đã đo bằng rename+restore, không để vết).
END-FIXTURE — 1 dept + 3 users + 3 suppliers + 2 projects + 2 workitems, tất cả prefix TEST/ZZTEST, verify sống 2 phép