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

11 KiB
Raw Blame History

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.