Files
solution-erp/docs/changelog/sessions/2026-06-11-S59-wipe-tree-pmh-uat-batch.md
pqhuy1987 6bf28bfdb4 [CLAUDE] Docs: S59 session-end closeout - 10 dot ship prod-verified #273->#282 + gotcha #61/#62 + harvest gate PASS 5/5
- Session log MOI 2026-06-11-S59-wipe-tree-pmh-uat-batch.md (wipe testing data +
  tree 4 tang + 71 ma PMH + 6 vong UAT realtime, bundle FINAL B1DtNT9C/D6uF3Mln Run #282).
- STATUS/HANDOFF flush S59 (header + table + In Progress + Recently Done + bundle line).
- gotchas.md +2: #61 sqlcmd -f 65001 (console mojibake vs data-hong-that) + #62 rename
  natural-key DB-truoc-code-sau (seed per-code idempotent). CLAUDE.md root cite 62.
- Agent-memory 5 file: cicd x9 run entries + UTC-annotate #275 + bundle status-line final,
  inv-codebase recon S59 + curate S51->archive, H1 x2 + H2 x2 closeout entries.
- H2 GATE PASS 5/5 (0 miss, 0 on-behalf can append) + H1 ALL-4-FRESH (cross-count
  verified: gotcha 62 x3 nguon, bundle 4-source). RAG: 2 chunk S59 stored, rerank 0.875.
- Chore monthly 07-01: curate cicd L1 ~56KB + inv 32.9KB + STATUS/HANDOFF re-tier (uu tien).
2026-06-11 18:49:21 +07:00

61 lines
11 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.

# Session 59 — 2026-06-11 (chiều→tối) — Wipe testing data + PE tree 4 tầng + 71 mã PMH + 6 vòng UAT feedback (10 đợt ship prod-verified)
> **10 commit code → 8 Gitea Run PASS + 2 cancelled-supersede-benign (#273→#282), tất cả prod-verified.** Anh: `/session-start` → forward Zalo anh Kiệt FDC (2 việc) → chốt tree follow-up → forward chị Trà Sol (dọn mã tự chế) → anh Kiệt chốt format mã → 6 vòng screenshot UAT feedback realtime (4 vòng cuối chen giữa session-end) → "Chốt làm đi nhé" (session-end).
> Bundle FINAL: admin **`B1DtNT9C`** / user **`D6uF3Mln`** (Run #282 `792c030`). Test **240/240** (verify local ×2 + CI gate ×8). HMW-mode ON nguyên session nhưng mọi việc chạy Agent-tool spawn lẻ (không Workflow fan-out — task vừa, em main solo + recon/cicd spawn).
## Đợt 1 — Wipe transactional testing data prod (anh Kiệt: "xoá các cái testing trước đi em") — `56882ac` → Run #273
- 🟦 investigator-codebase recon prod: chỉ 3 cụm test data — **10 PE** (A/031-040, cả 10 WorkItemId NULL) + child 252 rows · **7 Contracts `[DEMO]`** + 30 child · **64 Notifications**; mọi module khác 0. Workflows: 7 ghim active + 1 V2 cũ inactive. Uploads: 19 folder PE vs 10 PE (~10 orphan từ Plan R S23). Generator PE/Contract đều INSERT-if-missing → DELETE sequence = reset mã an toàn.
- Anh chốt (AskUserQuestion): **wipe cả 3 cụm + reset mã về 0**.
- `scripts/s59-wipe-testing-data.sql` (pattern Plan R S23, QUOTED_IDENTIFIER ON): DELETE PE (cascade, Quotes NO_ACTION pass nhờ cascade Details→Quotes) → Contracts → Notifications → 1 AwV2 inactive (`IsActive=0 AND IsUserSelectable=0`) → PeSeq+CtSeq. AFTER exact: PE/child/Ct/Notif = 0 · AwV2 7/7 active · KEEP Projects 70 / WorkItems 86 / Suppliers 22 / Users 55 / Templates 9 / WfDefV1 10. Uploads orphan rd+md lại (ssh từng lệnh — quoting 3 lớp vỡ tại `&`, tách lệnh đơn).
- **Run #273 PASS** ~3m34s: bundle ×2 rotate (`R9uGRxvw`/`DikfX1RD`) + **app-recycle KHÔNG resurrect** (DemoSeed:Disabled gate held — verify THẬT qua recycle, không trên giấy). Team vào testing chiều: phiếu thật đầu tiên ra đúng **PE/2026/A/001** (sequence reset đúng thiết kế).
## Đợt 2+3 — PE Panel 1 tree regroup (2 vòng theo chỉ đạo) — `56882ac` (v1) + `0eafcd3` → Run #274
- Anh Kiệt v1: "Tên dự án (2026) → Hạng mục công việc → Phiếu cần duyệt" (thứ tự label "Dự án - Năm" — mirror folder Outlook FDC). Ship trong `56882ac`: node gộp `(Dự án, Năm-tạo-phiếu)` label "Tên (Năm)" → Hạng mục (`workItemId` Mig 49 — list DTO đã có sẵn `workItemName` S57bis nên FE-only) → phiếu. Bỏ tầng NCC (vẫn ở card/detail).
- Anh hỏi lại "Dự án→Năm hay Năm→Dự án?" → chốt follow-up: **"Năm chứa Dự án, Dự án chứa Hạng mục"** → `0eafcd3`: tree 4 tầng 📅 **Năm (DESC, bg-slate-50) → 📁 Dự án (A-Z vi) → 🧱 Hạng mục (A-Z vi) → phiếu (createdAt DESC)**. `yearGroups` useMemo thay `projectGroups`, expand-state localStorage key bump v3.
- **Run #274 PASS** ~4m51s: bundle ×2 rotate (`DuU7OTym`/`DWyeTzf3`), PE wipe held.
## Đợt 4 — Dọn 15 mã hạng mục tự chế (chị Trà Sol: "xóa cái đám phần thô phần hoàn thiện… MÀ ANH TỰ ĐẺ RA") — `bbd1554` → Run #275
- Prod 86 = 71 real PMH + **15 demo seed cũ** (Phần thô 5 + Hoàn thiện 6 + Cơ điện 3 + Khác 1 — DAO-MONG, SON-NUOC, TRAT-TUONG…). Đối chiếu **71/71 real khớp từng dòng bảng PMH** anh paste (4 nhóm 16/30/9/16 — S55 nạp từ chính Excel này).
- Fix kép: (a) **GỠ HẲN block seed demo** khỏi `DbInitializer` (guard `!AnyAsync()` vốn chống resurrect khi bảng còn data, nhưng DB mới tinh sẽ đẻ lại — diệt gốc theo "không đẻ thêm mã của công ty khác vô"); (b) `scripts/s59-wipe-demo-workitems.sql` DELETE 15 codes prod + LocalDB Dev → 71.
- **Run #275 PASS** ~3m44s: bundle ×2 FROZEN (BE-only đúng) + **app-recycle giữ 71** (demo codes = 0, seed real idempotent add 0). INFO: PE = 1 (phiếu UAT thật A/001 — không phải resurrect).
## Đợt 5 — Rename 71 mã theo format PMH anh Kiệt chốt ("MÃ CV gồm chữ MEP-SUB-1 rồi tên 1 MEP Sub MEP (Full) — đúng kiểu vậy") — `c869d26` → Run #276
- Mapping: `VT-nn→MAT-n` · `TP-nn→SUB-n` · `MEP-0n→MEP-SUB-n` · `TB-nn→MEP-EQU-n`; Name = `"STT nhóm tên"` (`1 Mat Bê tông`, `1 MEP Sub MEP (Full)`…). Category 4 nhóm giữ.
- **Thứ tự sống còn (gotcha #62 NEW):** SQL UPDATE rename (GIỮ Id) chạy prod + Dev **TRƯỚC** push — seed per-code idempotent mà deploy trước sẽ INSERT 71 mã mới cạnh 71 cũ = 142. Run #276 verify **đúng 71**.
- **Encoding (gotcha #61 NEW):** sqlcmd đọc file UTF-8 tiếng Việt PHẢI `-f 65001`; console VPS mojibake = display-only — verify data thật qua LocalDB console (đúng dấu) + **API JSON prod** (login admin → GET /catalogs/work-items → `"2 MEP Sub Hệ thống trung thế"` nguyên vẹn).
- FE sort numeric-aware 3 chỗ ×2 app (mã không pad → string-sort xếp "MAT-10" trước "MAT-2"): 2 dropdown (`select:` sort `localeCompare(…, {numeric:true})`) + tree workItemName. Spec provenance `master-import-data.generated.md` sync 71 dòng + note mapping.
- **Run #276 PASS** ~4m33s: bundle ×2 rotate (`BBA0KSWu`/`DzdTI18G`), spot MEP-SUB-1 đúng.
## Đợt 6 — UAT feedback vòng 1 (4 điểm form tạo phiếu, screenshot 16:40) — `faed59f` → Run #277
- **NEW `ui/SearchableSelect.tsx`** (~140 LOC, không lib ngoài): combobox gõ-để-lọc, **fold bỏ dấu tiếng Việt** (NFD strip U+0300-036F + đ→d — gõ "be tong" trúng "Bê tông"), keyboard ↑↓/Enter/Esc, clear ✕, listbox absolute z-50, style mirror ui/Input density S55.
- Áp: **Hạng mục + Dự án** ở PeWorkspaceCreateView + PeHeaderForm (HeaderForm giữ placeholder "Giữ nguyên: …" cho phiếu cũ). **Auto Địa điểm**: chọn dự án tự điền từ `Project.Location` (S55), chỉ ghi đè khi user chưa gõ tay (track `lastAutoLoc` ref). **Điều khoản thanh toán nhập tay**: Input 1 dòng → Textarea 3 dòng (CreateView + PeDetailTabs inline-edit; render detail đã `whitespace-pre-wrap` sẵn từ trước).
- **Run #277 PASS** ~4m09s: bundle ×2 rotate (`ex7Tc92G`/`DzUeSk96`).
## Đợt 7 — UAT feedback vòng 2 (3 điểm, screenshot 16:52) — `9c330d2` → Run #278
- Anh chốt 2 quyết định (AskUserQuestion): **(1) ẨN CẢ Trả lại + Từ chối** khi người duyệt = người soạn (`drafterUserId === currentUser.id` — PeWorkflowPanel skip 2 nút trong map; hủy phiếu = nhờ cấp khác Từ chối / Xóa phiếu Nháp); **(2) CHO PHÉP quick-add NCC**: `SuppliersController` POST hạ `Roles=Admin,CatalogManager``[Authorize]` any-auth (PUT/DELETE giữ khóa S57) + AddSupplierDialog nút "+ NCC mới" form nhanh (Mã/Tên/Loại/SĐT/Email) → POST → invalidate + auto-select vào phiếu.
- NCC dropdown → SearchableSelect sort A-Z theo mã. **Upload nhiều file 1 lần**: input `multiple` + `onPick` async upload tuần tự `mutateAsync` từng file (×2 chỗ: báo giá per-NCC + bảng so sánh — replace_all 2 occurrences identical).
- Test 240/240 local TRƯỚC push (BE authz + seed đổi trong session). **Run #278 PASS** ~3m45s: bundle ×2 rotate (`BSh2fG2X`/`D22KfpPc`) + **authz probe live 4/4**: unauth POST **401** (mở quyền ≠ anonymous) · nv.test POST **201** (id tạo thật) · nv.test DELETE **403** (khóa giữ) · admin cleanup 204→404 (tombstone soft-delete by-design). Suppliers active 22 giữ.
## Đợt 8-10 — UAT vòng 3-6 realtime (chen giữa session-end, anh forward liên tục) — `f21c55d`/`69997da`/`80b64dd`/`792c030` → Run #279-cancelled/#280/#281-cancelled/#282 FINAL
- **Vòng 3 — "thêm file giao diện bị thay đổi không cân xứng" (`f21c55d`):** bảng NCC tham gia auto-layout → cell File (chip tên dài 8.2MB) phình, bóp dọc cột NCC. Fix `table-fixed` + width % từng cột (NCC 24/SĐT 9/Email 14/ĐKTT 14/File 22/Tiền 12/action w-10) + `min-w-[860px]` (hẹp → scroll ngang wrapper) + email span block truncate. Chip file truncate sẵn — kích hoạt khi cell khóa width.
- **Vòng 4 — "chỗ tên ngân sách bỏ đi nhé" (`69997da` #280):** bỏ ô "Tên (không bắt buộc)" ngân sách nhập tay (user không hiểu "ý nghĩa dự phòng là gì") — chỉ còn Số tiền. Payload `budgetManualName: null`; PeHeaderForm `hasManual` detect thêm theo amount (phiếu mới name-null vẫn nhận đúng manual mode). Tên cũ hiện read-only, về null khi lưu lần tới.
- **Vòng 5 — "điều khoản thanh toán bỏ nốt ra luôn tất cả các form" (`80b64dd`):** GỠ field phiếu-level khỏi CẢ 3 form (CreateView: Select preset + Textarea custom + PAYMENT_PRESETS/PAYMENT_CUSTOM/paymentMode drop, 142 LOC · HeaderForm + DetailTabs inline-edit: bỏ Textarea, state giữ → save giữ nguyên data cũ). GIỮ: cột "Điều khoản TT" per-NCC bảng so sánh (data từng NCC, khác field) + display read-only phiếu cũ.
- **Vòng 6 — "bỏ luôn cái nút thêm hạng mục" (`792c030` #282):** gỡ nút "+ Thêm hạng mục" ItemsTab — 1 phiếu = 1 hạng mục chọn từ header (S57bis/S58), hạng mục đầu auto-seed khi tạo. AddItemDialog giữ dead-code flip lại dễ.
- **2 run cancelled (#279, #281) = supersede-BENIGN** (Gitea concurrency-cancel khi push đè lúc UAT góp ý realtime ~1s gap): cicd ancestor-verify `git merge-base --is-ancestor` TRUE cả 2 — mọi fix preserved trong HEAD, ships qua run kế (#280, #282). Pattern lặp #385 S58 — cicd-monitor giờ xử lý chuỗi này thành thạo (con final-v2 tự phát hiện supersede + verify run MỚI thay vì báo fail).
## Closeout & lessons
- **0/14 spawn truncated** (H1×2 + H2×2 bootstrap/closeout + investigator recon + cicd ×9) — lần đầu sau nhiều session; verdict-FIRST + entry gọn + prompt scoped works.
- **gotcha #61** (sqlcmd -f 65001 + verify-qua-API-JSON) + **#62** (rename natural-key: DB-trước-code-sau) NEW → 62 total.
- Quy trình "destructive prod" giữ chuẩn: recon → AskUserQuestion chốt scope → script committed vào repo → chạy → verify exact-count → cicd re-verify sau app-recycle.
- cicd-monitor MEMORY ~56KB > cap 30KB (9 cicd-spawn/ngày, H2 đo 54KB giữa session + 2 entry cuối) → chore-flag curate L2 monthly 2026-07-01 (FIFO top vẫn inject OK). H2 GATE PASS 5/5 + H1 ALL-4-FRESH (cross-count verified); 2 fix theo H2 flag: UTC-annotate entry #275 + bundle status-line tự cập bởi cicd final-v2.
- Ops note benign: `GET /api/suppliers` trả page đầu (20) — đếm thật qua DB (22); không UI nào dùng sai.
- Pending (carry): test-after guard cho `LockDemoSampleUsersAsync` (S58) + asymmetric authz suppliers POST/PUT-DELETE (S59) → test-specialist khi UAT ổn; 4 ops của anh (tzutil / email anh Chương / báo password 5 staff / lock nv.cao-truong khi gán thật); PermissionGuard per-route khi golive HRM/Office; Phase 9 Ops; monthly audit 2026-07-01.