diff --git a/.claude/WAL.md b/.claude/WAL.md index b7a9f219..d708ba32 100644 --- a/.claude/WAL.md +++ b/.claude/WAL.md @@ -39,8 +39,11 @@ chain: [x] G2 XONG. wf_5aa55a4e-065: data ×2 app (002.02 36 slot/2 bảng/5 điều · 002.03 46/6/6 · PHẦN 2 5 điều read-only) + ContractBodyView.tsx 42.640B ĐÃ render thật trong form (chú thích tại chỗ: đặt giữa Header và Chi tiết, +nút Lưu thứ 2 ở chân vì bản 7 trang). Ô LẶP chung key ĐÚNG: ben_b_ten×3 · so_hd/hang_muc/dia_diem/ben_b_dia_chi ×2 [x] lead vá sau G2: lane chỉ tạo ContractBodyView ở fe-user ⇒ LỆCH cặp; đã mirror + đồng bộ ContractCreatePage ⇒ 3/3 cặp TRÙNG sha256 · tsc --noEmit exit 0 ×2 (build 470ms là incremental, KHÔNG tin — ép tsc riêng) [x] control-dương nội dung PHẦN 2: 5/5 cụm khớp file gốc ⇒ chữ THẬT không bịa (33 khoan + 5 dieu) -[!] wf: wf_b04efcd7-366 G3+G4 — pre-fill (đổ ô từ Supplier/Project/PE, dùng pe.DiaDiem vì Project.Location 93% rỗng, ô nguồn rỗng thì BỎ QUA không ghi '') · khoá bất-khả-đảo (Mig AddContractSealedAt + guard 2 cửa + TEST-BEFORE 2 ca) · print CSS (ô in ra thành đường kẻ, không phải khung input) -[ ] G5 cuối: reviewer + style FE/BE + cicd + DEPLOY prod cho anh test +[x] G3+G4 XONG (wf_b04efcd7-366): pre-fill 194 dòng vào bridge · Contract.SealedAt+SealedByUserId + Mig 20260813204332_AddContractSealedAt (3-file ĐỦ, ModelSnapshot có SealedAt, has-pending=No changes) · print CSS 5 hit ×2 app +[x] ĐO SAU G4: BE build 0 error · test **697→699 PASS** (+2 test seal) · tsc --noEmit exit 0 ×2 · cặp ContractBodyView TRÙNG sha256 · diff tổng 38 file +984/−85 + 10 path mới +[!] wf: wf_24bed124-eed G5 chấm cuối 4 lane — reviewer adversarial 6 trục (tìm nhánh câm THỨ 5 · menu mất im lặng · paymentTerms có bị xoá khi lưu body · khoá có răng thật · key trùng ngoài ô-lặp · key pre-fill khớp key data) + 3 vai style FE/BE/DB +[ ] sau G5: vá finding CHẶN-DEPLOY (nếu có) → commit → push → cicd → DEPLOY prod cho anh test +[ ] 🔴 KHI BÁO ANH: PHẢI khai 4 nợ đã-biết (VAT · con-trỏ ĐIỀU 8/12 chết · authz upload · 12 điều PHẦN 2) — owner hoãn CỐ Ý, cấm im cho tròn [ ] sau G1: G2 document-view (PHẦN 1 riêng ×2 + PHẦN 2 chung cuối) → G3 pre-fill → G4 in+khoá → G5 verify/deploy [ ] sau review: lead tổng hợp → fan-out Opus 5 MAX thi công theo wave [!] 7 câu (90)-(96) CHỜ CHỦ DỰ ÁN — 0 đáp; nhà CANONICAL = docs/HANDOFF.md khối (90)-(96) diff --git a/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-database-reviewer-style-3.md b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-database-reviewer-style-3.md new file mode 100644 index 00000000..49b28cc8 --- /dev/null +++ b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-database-reviewer-style-3.md @@ -0,0 +1,30 @@ +# sub-database-reviewer-style-3 — G5 DB-STYLE (S194 / YC-032) + +> Vai: `database-reviewer-style` — chấm ĐỒNG-NHẤT QUY-ƯỚC ĐẶT TÊN + HÌNH-DẠNG MIGRATION. +> KHÔNG chấm thiết-kế schema (FK strategy / index perf / concurrency = `database-agent`). +> Địa-phận: `src/Backend/SolutionErp.Infrastructure/Persistence/**`. + +## 0. Thước phạm-vi (untracked-aware) + +``` +{ git diff --name-only origin/main...HEAD + git diff --name-only HEAD + git ls-files -o --exclude-standard +} | sort -u | grep -i 'Persistence/' +``` + +(kết quả + đo đạc append phía dưới) + +## 1. 3-file rule + +## 2. Tên migration + +## 3. Cột SealedAt / SealedByUserId + +## 4. Down() reversible + +## 5. DbInitializer seed + +## 6. has-pending-model-changes + +## 7. VERDICT diff --git a/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-front-end-reviewer-style-1.md b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-front-end-reviewer-style-1.md new file mode 100644 index 00000000..75bdd65b --- /dev/null +++ b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-front-end-reviewer-style-1.md @@ -0,0 +1,23 @@ +# sub-front-end-reviewer-style-1 — G5 STYLE-GATE YC-032 (S194) + +> Vai: `front-end-reviewer-style` — soi ĐỒNG-NHẤT STYLE, KHÔNG soi logic. +> Địa phận: `fe-admin/src/**` + `fe-user/src/**`. +> Alias tên file mà TASK gọi: `sub-fe-style-1.md` (file này = bản canonical theo RUN-TRACE). + +## VERDICT +_(điền cuối)_ + +## 0. Cửa-sổ đo (phần MỚI = chưa-production) +_(đang đo)_ + +## 1. Máy trước (ESLint) +_(đang đo)_ + +## 2. MIRROR 2 app +_(đang đo)_ + +## 3. Đối chiếu khuôn PRODUCTION +_(đang đo)_ + +## 4. Finding +_(đang đo)_ diff --git a/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-implementer-backend-3.md b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-implementer-backend-3.md index 2f54d99d..51829e2d 100644 --- a/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-implementer-backend-3.md +++ b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-implementer-backend-3.md @@ -8,6 +8,76 @@ --- -## LƯỢT 1-2 — scaffold + đọc nguồn +## LƯỢT 1-2 — đọc nguồn + ĐO DỮ LIỆU TRƯỚC KHI VIẾT MÃ -(đang đọc key ô + file sở hữu) +### A. Key ô — đọc THẲNG từ đĩa, KHÔNG chế + +Nguồn: `fe-user/src/lib/contractBody/body002_02.ts` (36 slot) + `body002_03.ts` (46 slot). +`types.ts:17-18` nói rõ: *"`slot.key` ĐI THẲNG vào `ContractDraftData.body` và SỐNG TRONG DB"* ⇒ chỉ +dùng key đã tồn tại. +`ContractBodyView.tsx:225` chốt kiểu: **`body` là `Record` PHẲNG** ⇒ mọi giá trị đổ +xuống phải là **CHUỖI JSON**, không phải số. + +### B. ĐO DỮ LIỆU (LocalDB `SolutionErp_Dev`, `WHERE IsDeleted = 0`) + +Lệnh: `sqlcmd -S "(localdb)\MSSQLLocalDB" -d SolutionErp_Dev -i …\measure.sql` +Vị từ rỗng = `NULLIF(LTRIM(RTRIM(col)),'') IS NULL` (bắt cả NULL lẫn chuỗi trắng). + +| Bảng | n | Cột | rỗng | % rỗng | +|---|---|---|---|---| +| Suppliers | 24 | `Name` | 0 | **0%** | +| Suppliers | 24 | `Address` | 2 | 8,3% | +| Suppliers | 24 | `Phone` | 2 | 8,3% | +| Suppliers | 24 | `ContactPhone` | 20 | 83,3% | +| Suppliers | 24 | `BankAccount` | 20 | **83,3%** 🔴 | +| Suppliers | 24 | `TaxCode` | 6 | 25,0% | +| Suppliers | 24 | `LegalRepresentative` | 20 | **83,3%** 🔴 | +| Suppliers | 24 | `LegalRepTitle` | 20 | **83,3%** 🔴 | +| Suppliers | 24 | `Fax` | 23 | **95,8%** 🔴 | +| Suppliers | 24 | `ContactPerson` | 7 | 29,2% | +| Suppliers | 24 | `ContactTitle` | 20 | 83,3% | +| Projects | 69 | `Name` | 0 | **0%** | +| Projects | 69 | `Investor` | 64 | **92,8%** 🔴 | +| Projects | 69 | `Location` | 64 | **92,8%** 🔴 | +| PurchaseEvaluations | 4 | `DiaDiem` | 0 | **0%** ✅ | +| PurchaseEvaluations | 4 | `TenGoiThau` | 0 | **0%** ✅ | +| ContractSigningPlanLines | 2 | `TenHangMuc` | 0 | **0%** | + +🔴 = nguồn rỗng > 50% ⇒ **nối đúng nhưng thực tế sẽ TRẮNG**. + +Số đo TRÙNG KHỚP MEMORY-PACK (BankAccount 83% · người đại diện 83% · Investor 93% · Location 93% · +MST 25% · `pe.DiaDiem` 0%) ⇒ xác nhận lệnh *"địa điểm lấy `pe.DiaDiem`, KHÔNG lấy `Project.Location`"* +là đúng bằng số, không phải theo cảm tính. + +⚠️ **CAVEAT MẪU SỐ (tự khai, đừng đọc quá số):** `PurchaseEvaluations` **n = 4** và +`ContractSigningPlanLines` **n = 2** trên Dev. "0% rỗng" trên n=4 là **tín hiệu yếu** — nó nói +"chưa thấy ca rỗng", KHÔNG nói "không thể rỗng". Cả hai cột đều `nullable` ở Domain +(`PurchaseEvaluation.cs:19` `string? DiaDiem`) ⇒ mã vẫn phải null-safe, và đã null-safe. + +### C. Chọn cột nguồn khi có ≥2 ứng viên (khai để người sau khỏi đoán) + +- **`ben_b_dien_thoai`** → `Supplier.Phone` (8,3% rỗng), **KHÔNG** `ContactPhone` (83,3% rỗng). + Lý do NGỮ NGHĨA trước, số sau: ô nằm trong khối "BÊN NHẬN THẦU (Bên B)" cùng Tên/Địa chỉ/MST ⇒ đó + là điện thoại **công ty**; `ContactPhone` là "SĐT người liên hệ" (`Supplier.cs:31`). Số đo chỉ xác + nhận thêm là chọn đúng cột cũng là chọn cột đầy hơn. +- **`ben_b_nguoi_dai_dien` / `ben_b_chuc_vu`** → `LegalRepresentative` / `LegalRepTitle` + (`Supplier.cs:24-25`), **KHÔNG** `ContactPerson`/`ContactTitle`. Ô này đứng ngay trên khối ký + "ĐẠI DIỆN BÊN B" ⇒ phải là **đại diện pháp luật**, không phải người liên hệ. + 🔴 Đây là ca **chọn cột ĐÚNG NGHĨA dù RỖNG HƠN**: `ContactPerson` chỉ rỗng 29,2% còn + `LegalRepresentative` rỗng 83,3%. Lấy `ContactPerson` cho "đầy bảng thành tích" = điền **sai người + ký** vào hợp đồng — tức là đổ một giá trị SAI trông như đã điền xong, tệ hơn hẳn ô trống. + +### D. Ô CÓ trong mẫu nhưng CỐ Ý KHÔNG đổ + +| key | vì sao bỏ | +|---|---| +| `gia_tri_bang_chu` | phải sinh chữ-số-tiếng-Việt (thuật toán mới) — ngoài phạm vi lane, và đọc-số-thành-chữ sai thì sai trong văn bản pháp lý | +| `ben_a_so_tai_khoan` · `ben_a_ngan_hang` · `ben_a_nguoi_dai_dien` · `ben_a_chuc_vu` | Bên A = Solutions, **0 nguồn trong DB** (không có bảng thông tin công ty mình) | +| `bia_thang` · `bia_nam` · `ngay_ky_*` · `ngay_hoan_thanh` | ngày do người soạn chốt; lấy `DateTime.UtcNow` = **bịa** một ngày ký | +| `hd_chinh_so` · `hd_chinh_ngay` | HĐ giao thầu chính giữa Solutions ⟂ Chủ đầu tư — hệ chưa có ô này | +| `bhld_*` (9 ô, chỉ 002.03) | đơn giá bảo hộ lao động — không có danh mục nguồn | +| bảng (`bang_gia_tri`, `bang_tom_tat`, `pl0*`) | ô bảng, không phải slot phẳng; lược đồ `body` là map phẳng | + +--- + +## LƯỢT 3 — MÃ (đang viết) diff --git a/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-reviewer-5.md b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-reviewer-5.md new file mode 100644 index 00000000..1ecf47b8 --- /dev/null +++ b/.claude/workflows/runs/2026-08-13-S194-yc032-hd-thauphu-2form/sub-reviewer-5.md @@ -0,0 +1,37 @@ +# sub-reviewer-5 — G5 vòng chấm cuối YC-032 (HĐ Thầu phụ tách 2 form) + +> Vai: reviewer adversarial (read-only). Ngày 2026-08-13/14. Trần lượt ~40. +> Diện: 38 file sửa (+984/−85) + 11 file/thư-mục mới (chưa `git add`). +> Nhiệm vụ: soi 6 trục, mỗi trục tự đo bằng lệnh, 0-hit kèm control-dương. + +## 0. Trạng thái cây (đo) + +(đang đo) + +## 1. Trục 1 — nhánh câm còn sót (switch trên ContractType) + +(đang đo) + +## 2. Trục 2 — menu biến mất im lặng (gotcha #50) + +(đang đo) + +## 3. Trục 3 — lược đồ DraftData, 3 đường ghi + +(đang đo) + +## 4. Trục 4 — khoá bản cứng có răng thật không + +(đang đo) + +## 5. Trục 5 — key ô trùng trong body002_0*.ts + +(đang đo) + +## 6. Trục 6 — pre-fill từ KHKK khớp key + N+1 + +(đang đo) + +## 7. Bảng finding tổng hợp + +(đang đo)