From db9cf99fdf3c0b07c838cacfebbf324410dddb72 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Wed, 12 Aug 2026 17:27:21 +0700 Subject: [PATCH] wal: flush 20260812T1727 --- .claude/WAL.md | 12 +- .../run.md | 18 +++ .../spec-soltuon-dieu-chinh-hd-12-08-2026.md | 103 ++++++++++++++++++ .../sub-invest-b1-fable.md | 47 +++++++- .../sub-review-b2-lens1.md | 13 +++ .../sub-review-b2-lens2.md | 15 +++ .../sub-review-b2-lens3.md | 15 +++ 7 files changed, 215 insertions(+), 8 deletions(-) create mode 100644 .claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/spec-soltuon-dieu-chinh-hd-12-08-2026.md create mode 100644 .claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens1.md create mode 100644 .claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens2.md create mode 100644 .claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens3.md diff --git a/.claude/WAL.md b/.claude/WAL.md index 7bc3c60d..cc96b9bd 100644 --- a/.claude/WAL.md +++ b/.claude/WAL.md @@ -8,11 +8,13 @@ goal: YC-029 "SOLTUON-12-08-2026" — 5 điều chỉnh GĐ3 sau review prod c chain: [x] /tiep S190 trọn (sàn-3 ⑤ cân sổ · verify site+marker+A/059 Phase=10 · tick 64 · se=0/all=0 · ctx-verifier 13 cờ → vá run.md S189 + di-trú 2 carry vào HANDOFF + WAL số mục) -[!] B1 /fable-real investigator-codebase — invest 5 điều chỉnh + đối chiếu khuôn KHKK/NCC - → propose wave+checklist. #53 ×2 (return rỗng) nhưng artifact cứu: lượt-1 Thứ-1+Thứ-3 - (root-cause A+B) · B1b Thứ-2+Thứ-4 (máy per-loại OK, lẫn = 3 lỗ UI; thiếu nút Xóa màn - duyệt). wf: B1c wf_09951efa-970 chốt Thứ-5+Đọc-ý+PROPOSE · sub-invest-b1-fable.md -[ ] B2 /fable-clone reviewer — review spec/wave B1 (≥3 lane opus, đóng-gói C2) +[x] B1 invest TRỌN 7/7 mục qua 3 chặng (#53 ×2, artifact cứu 100%): root-cause bug menu + A+B · máy per-loại OK (lẫn = 3 lỗ UI) · Thứ-5 đã có ~95% (thiếu 1 nhánh resolvePath + fe-admin #50) · 5 wave. LEAD VERIFY 4/4 claim + SPEC GHI: + runs/2026-08-12-S190-soltuon-dieu-chinh-hd/spec-soltuon-dieu-chinh-hd-12-08-2026.md +[!] B2 /fable-clone reviewer — 3 lane opus (lens correctness · khuôn+scope · acceptance). + wf: wf_d9a14945-190 · artifact sub-review-b2-lens{1,2,3}.md · xong thì lead synthesize + → sửa spec → B3 [ ] B3 /fable-real ×2 style: front-end-reviewer-style + back-end-reviewer-style → spec-list style đồng nhất khuôn KHKK/DuyetNCC [ ] B4 /fable-clone ×2 style FE/BE — review lại 2 spec style diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/run.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/run.md index e91d90f7..b35d8893 100644 --- a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/run.md +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/run.md @@ -50,3 +50,21 @@ HEAD lúc mở run: ae1dcf4a · HMW-mode ON · lead Opus 5 MAX (default) - **B1c chặng chót** `wf_09951efa-970`: 3 mục cuối (Thứ-5 admin Designer · Đọc-ý · PROPOSE spec/wave/checklist — gợi ý W1 bug-menu → W2 cây-trái → W3 slice-WfView → W4 admin-7-leaf → W5 nút-Xóa-BE-nhỏ, lane được quyền chỉnh). +- **B1c KẾT QUẢ** (19 tool-use · 157K · ~11' · return SẠCH): VERDICT READY 3/3. Phát hiện + đắt: **Thứ-5 ĐÃ CÓ ~95% @S188** (7 menu-row `AwV2_Hd*` seed by-construction Order 11..17 + + Designer family-slice + route đủ) — thiếu ĐÚNG 1 nhánh `Hd*` trong resolvePath fe-admin + `Layout.tsx:175-189` ⇒ 7 leaf DROP IM LẶNG #50 (mà comment ngay đó tự cảnh báo #50 — ca + "vá tệp A quên tệp B" tái diễn). Đọc-ý 4 ĐÚNG / Đ3 CẦN-CHỈNH (không phải #34/#50/#85 mà + 2 lỗ trên-thuốc-#34). Wave chốt: W1 GỘP danh-tính + slice (2 nửa 1 thay đổi) → W2 cây-trái + → W3 pendingMe → W4 admin-5-dòng (song song) → W5 Xóa V2-aware (khuôn BE = PE + PeSoftDeleteFeatures.cs:110-114, KHÔNG phải KHKK). +- **LEAD VERIFY B1** (@S190): 4/4 claim load-bearing grep độc lập KHỚP (seed 2296/2306 · + awV2Match 0-Hd + control KhkkN · Layout:151-152 nguyên văn · delete-guard so số — đính + chính path `Application/Contracts/ContractFeatures.cs`; + lead phát hiện thêm: đường xóa + = `db.Contracts.Remove` ⇒ W5 phải xác minh soft-vs-hard trước khi nới guard). **SPEC ghi:** + `spec-soltuon-dieu-chinh-hd-12-08-2026.md` (3-mục H21). +- **B2 phóng** `wf_d9a14945-190` — /fable-clone reviewer ensemble 3 lane opus: + label `WF reviewer b2-lens1-correct s190` (correctness W1/W2 + regression) · + `WF reviewer b2-lens2-khuon s190` (fidelity khuôn + scope + đọc-ý cần hỏi lại anh) · + `WF reviewer b2-lens3-accept s190` (acceptance chạy-được + Goodhart + W5 khuôn PE). + Artifact: sub-review-b2-lens{1,2,3}.md. diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/spec-soltuon-dieu-chinh-hd-12-08-2026.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/spec-soltuon-dieu-chinh-hd-12-08-2026.md new file mode 100644 index 00000000..2d3e9921 --- /dev/null +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/spec-soltuon-dieu-chinh-hd-12-08-2026.md @@ -0,0 +1,103 @@ +# SPEC — SOLTUON-12-08-2026 (YC-029: 5 điều chỉnh GĐ3 đồng-khuôn KHKK/Duyệt NCC) + +> H21 spec-file 3-mục. Engine propose = `sub-invest-b1-fable.md` (Fable-5, 3 chặng B1/B1b/B1c). +> Lead verify @S190: 4/4 claim load-bearing spot-check KHỚP (seed `AwV2_Hd*` by-construction · +> fe-admin `Layout.tsx:175-189` 0 nhánh `Hd` + control `KhkkN:188` · fe-user `Layout.tsx:151-152` +> đúng nguyên văn · delete-guard so số tại `src/Backend/SolutionErp.Application/Contracts/ContractFeatures.cs:896-897` +> — lane ghi thiếu segment path `Contracts/`, đã đính chính). Trạng thái: CHỜ B2 review (fable-clone). + +## ① Tính-năng / đề-bài + +Đồng-khuôn GĐ3 "Duyệt Hợp đồng" với KHKK + Duyệt NCC prod (luật owner S176: đã-deploy = CHUẨN), +theo 5 điều chỉnh anh chốt @S190 sau khi review prod (YC-029, ảnh kết tinh `anh-mo-ta.md`): +- **Đ1** cây toàn trình DỜI sang cột TRÁI trang `my-contracts` làm trục điều hướng (khuôn KHKK: + cây trái 400px, flat-list = fallback trong CÙNG panel, panel-3 dashed/WorkflowHistory). +- **Đ2+Đ3** menu 7 loại HĐ mang đúng danh-tính trục ContractType — hết click-nhảy-lẫn (bug A: + `?type=3` ApplicableType đá accordion; bug B: `phase=9` transient 2-leaf-cùng-sáng), leaf + "Luồng duyệt" slice đúng họ `HD-*` của loại. Máy per-loại ĐÃ XONG @S188 — toàn bộ là UI. +- **Đ4** bộ thao-tác theo hành-vi KHKK: Đang-duyệt ở lại cùng trang (`pendingMe=1`), Đã-duyệt + danh-tính chuẩn (`view=approved`), nút XÓA ở màn duyệt theo cờ per-Cấp `AllowApproverDelete`. +- **Đ5** admin Designer hiện 7 leaf per-loại (menu-row + policy + Designer + route ĐÃ seed @S188 + — thiếu đúng 1 nhánh `resolvePath` fe-admin ⇒ drop im lặng #50). + +Tổng: **FE-only 4 wave + 1 wave BE nhỏ (0 migration)**. Đợt này PROPOSE + IMPLEMENT + gate +per-wave; **DEPLOY CHỜ** (CI runner workspace còn hỏng P0 — vá-gốc = CỬA NGOÀI-GIỜ; push gom). + +## ② Cách implement (per điều chỉnh — file:line đã verify) + +- **Đ1 (W2):** `fe-user/src/pages/contracts/MyContractsPage.tsx:153` grid `[320px_1fr_360px]` → + `[400px_1fr_360px]`; panel-1 = `PipelineTreePanel currentStage={3} hideHeader hideSearch` + + flat-list fallback server-side trong CÙNG panel (khuôn `KhkkListPage.tsx:171` + + `KhkkListPanel.tsx:21-24,366-371`); panel-3 = dashed khi chưa chọn / `WorkflowHistoryPanel` + khi chọn (QĐ-2 `KhkkListPage.tsx:252-256` — CẤM cây ở panel-3). Bịt gap: + `usePipelineStages.ts:377` leaf GĐ3 `navigate('/contracts/…')` → thêm opt-in + `stage3Options.onOpenContract` (analog `onOpenKhkk` `:185,:244`) + wire `PipelineTreePanel.tsx:111` + → chọn vào panel-2 qua `?id=`. Host CHỈ fe-user (fe-admin không có MyContractsPage) nhưng + `usePipelineStages` + `PipelineTreePanel` = cặp MIRROR ×2 app → sửa cả 2 bản SHA-identical. +- **Đ2+Đ3 (W1):** `fe-user/src/components/Layout.tsx:151` WfView → `/contracts/workflow-matrix?ct=N` + (BỎ `type=3` khỏi URL — trang tự suy applicableType=3 theo path, khuôn alias-path khkk sẵn) · + `:152` thêm `&view=approved` (khuôn PE `:180-185`, giữ `phase=9` làm lọc thật) · sửa comment + stale `:141-142` · accordion `:470-485` ưu tiên `ct` + loại trừ pathname `/contracts/workflow-matrix` + khỏi nhánh else (phòng thủ 2 lớp) · `fe-user/src/pages/pe/WorkflowMatrixViewPage.tsx` thêm + nhánh đọc `ct` → lọc `code === 'HD-'` y khuôn nhánh `group` `:84-98` (map ContractType→mã: + const cục bộ 7-entry — fe-user KHÔNG mirror lib fe-admin, `contractWorkflowFamily.ts:16-18` + tự khai fe-admin-ONLY). fe-admin KHÔNG đụng (Ct_* bị ẩn `:248` + cố ý không có trang matrix). +- **Đ4-Đang-duyệt (W3):** `fe-user/Layout.tsx:150` `Ct_*_Pending` → `/my-contracts?type=N&pendingMe=1` + (khuôn PE `:176`; BE param `pendingMe` sẵn) + `MyContractsPage` đọc `pendingMe` gửi server; + GIỮ `/inbox` làm hộp thư tổng. (`[carry:w7b-inbox-param]` liên quan — KHÔNG gộp vào đợt này.) +- **Đ5 (W4):** `fe-admin/src/components/Layout.tsx` import `findContractWfByTypeCode` từ + `@/lib/contractWorkflowFamily` + thêm sau `:188`: + `if (findContractWfByTypeCode(code)) return '/system/approval-workflows-v2/' + code`. + KHÔNG dùng `?ct=`/`?family=` — khuôn họ này là path-param `:typeCode` y hệt `KhkkN{n}`. + KHÔNG sửa DbInitializer (label đã khớp khuôn). +- **Đ4-nút-Xóa (W5, BE nhỏ 0-mig):** mirror khuôn PE prod `PeSoftDeleteFeatures.cs:110-114` + (3 điều-kiện: ChoDuyet · ĐÚNG-LƯỢT actor · `matchingLevel.AllowApproverDelete`). Việc: nới + delete-guard `Application/Contracts/ContractFeatures.cs:896-897` (đang so SỐ + `Phase >= DangInKy` — chặn nhầm V2 ChoDuyet=10/TraLai=98/TuChoi=99, finding S160) thành + V2-aware + nhánh xóa-bởi-approver đọc cờ (cột `ApprovalWorkflowLevels.AllowApproverDelete` + Mig 68 DÙNG CHUNG V2 — Designer round-trip sẵn cho `HD-*`: + `ApprovalWorkflowV2AdminFeatures.cs:475,883,1288`) + DTO expose cờ (khuôn + `PurchaseEvaluationDtos.cs:138`) + FE `ContractWorkflowPanel.tsx` thêm mục Xóa mirror + `KhkkWorkflowPanel.tsx:12-14,118,233` (panel SHA-mirror ×2 app). + 🔴 Lead thêm khi verify: đường xóa hiện tại là `db.Contracts.Remove(entity)` — wave PHẢI + XÁC MINH interceptor soft-delete (AuditableEntity `IsDeleted`) đứng sau Remove hay không + TRƯỚC khi nới guard; màn "Đã xóa" (`/contracts/deleted`) đang đọc soft-delete ⇒ nếu Remove + là hard-delete thật thì nhánh xóa-bởi-approver phải đi đường soft-delete như PE, KHÔNG + tái dùng Remove. + +## ③ Checklist — 5 wave + acceptance ĐO ĐƯỢC + +Thứ tự: **W1 → W2 → W3** (W3 sau W1 vì cùng vùng `Layout.tsx:148-152`); **W4 song song** bất kỳ +lúc; **W5 cuối** (BE + test-before guard). Mỗi wave: implement → build → reviewer-gate → tick. + +- **W1 — Danh-tính menu + slice per-loại (fe-user):** + ✅(i) tái-hiện A: mở nhóm 01 → click "Luồng duyệt" → accordion GIỮ nhóm 01, leaf sáng đúng; + ✅(ii) tái-hiện B: `?type=1&phase=9&view=approved` → CHỈ leaf "Đã duyệt" sáng; + ✅(iii) WfView `ct=1` chỉ hiện họ `HD-TP` (0 dòng QT-HD-V2-001/loại khác); + ✅(iv) `grep -rn "workflow-matrix?type=3" fe-user/src` = 0-hit + control dương + `grep "workflow-matrix?ct=" fe-user/src` ≥1; + ✅(v) `npm run build` fe-user PASS. +- **W2 — Cây toàn trình sang trái (fe-user + cặp mirror ×2 app):** + ✅(i) grep `grid-cols-\[400px` MyContractsPage ≥1; + ✅(ii) click leaf HĐ trên cây → panel-2 mở detail, URL Ở LẠI `/my-contracts`; + ✅(iii) gõ search → flatMode; + ✅(iv) cặp `usePipelineStages.ts`/`PipelineTreePanel.tsx` 2 app SHA256 khớp từng cặp; + ✅(v) build 2 app PASS. +- **W3 — Đang-duyệt về cùng trang (fe-user):** + ✅(i) grep `pendingMe=1` nhánh Ct_ Layout ≥1; ✅(ii) leaf "Đang duyệt" ở lại `/my-contracts`, + list khớp inbox cũ cùng user; ✅(iii) build PASS. +- **W4 — Admin Designer 7 leaf (fe-admin ≈5 dòng):** + ✅(i) sidebar "Quy trình duyệt (Mới)" đủ 17 leaf (2 NCC + 8 KHKK + 7 HĐ Order 11..17); + ✅(ii) click "QT Duyệt HĐ — Thầu phụ" → panel khoá mã `HD-TP`, history CHỈ HD-TP; + ✅(iii) build fe-admin PASS. +- **W5 — Nút Xóa màn duyệt V2-aware (BE nhỏ + FE, 0-mig, TEST-BEFORE guard):** + ✅(i) `dotnet test SolutionErp.slnx` PASS + test mới: TraLai/TuChoi Drafter xóa được · + ChoDuyet CHỈ approver-đúng-lượt-có-cờ · cờ tắt → 403/409 · V1 `Phase>=DangInKy` VẪN chặn + (regression S160) · xác minh soft-vs-hard-delete (lead-note ②); + ✅(ii) grep `AllowApproverDelete` Contract-delete-path ≥1 (trước: 0-hit); + ✅(iii) panel 2 app SHA-identical + nút Xóa chỉ render khi DTO cờ bật; ✅(iv) build 2 app PASS. + +**Ngoài wave — CHỜ ANH (không tự làm):** ① gỡ-ghim/thay `QT-HD-V2-001` bằng 7 bản `HD-*` nếu +muốn "tuyệt-đối mỗi loại 1 quy trình" (van xả `ContractWorkflowGuards.cs:141-143` là CỐ Ý — +việc Designer/DATA 0 code); ② port 3 món KHKK cố-ý-không-port (skipToFinal · duyệt-thay-CEO · +banner-kết-thúc-sớm) = cần nở `ContractDetail` DTO. diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-invest-b1-fable.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-invest-b1-fable.md index d384a5a4..a2574a73 100644 --- a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-invest-b1-fable.md +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-invest-b1-fable.md @@ -4,7 +4,13 @@ ## Đọc-ý 5 điều chỉnh (xác nhận/bác từng cái) -(pending) +| # | Điều chỉnh | Đọc-ý lead (anh-mo-ta.md) | Verdict | Căn cứ (từ ground-truth 4 mục) | Tin | +|---|---|---|---|---|---| +| 1 | Dời cây toàn trình | DỜI panel cây PHẢI→TRÁI, bố cục giống KHKK; "danh-sách đi đâu" = invest đề xuất | **ĐÚNG** | Khuôn KHKK: cây = panel TRÁI 400px làm trục điều hướng, danh-sách KHÔNG cần cột riêng — flat-list là chế-độ FALLBACK trong CÙNG panel khi search/lọc (`KhkkListPage.tsx:171` + `KhkkListPanel.tsx:21-24,366-371`), panel-3 = dashed/WorkflowHistory (QĐ-2 `:252-256`) | CAO | +| 2 | Mỗi loại HĐ 1 quy trình riêng | "đúng 7 workflow HD-* đã seed @S188 — UI/menu/trang từng loại lọc ĐÚNG, không lẫn" | **ĐÚNG** (kèm đính-chính phạm-vi) | Máy ĐÃ per-loại TRỌN: 7 mã `HD-*` (`ContractApprovalWorkflowFamily.cs:33-42`) + 4 cửa guard 409 + PA-A tự pin — dữ-liệu KHÔNG lẫn; việc còn lại CHỈ là 3 lỗ UI: WfView không đọc `ct` (`WorkflowMatrixViewPage.tsx:57,67`) + 2 bug menu A/B + comment stale `Layout.tsx:141-142` | CAO | +| 3 | Menu lẫn lộn, click nhảy | BUG điều hướng — "nghi lớp gotcha #34 / #50 / #85, lane truy bằng code" | **CẦN-CHỈNH** (đúng bệnh, sai lớp nghi) | KHÔNG phải #34/#50/#85 — 2 lỗ TRÊN thuốc-của-#34: (A) leaf WfView cả 7 loại mang `?type=3` (ApplicableType) mà accordion auto-expand đọc `type` như ContractType → mutex đóng nhóm đang mở (`Layout.tsx:151` ⟂ `:470-485`, chuỗi tái-hiện được); (B) `phase=9` transient làm danh-tính → 2 leaf cùng sáng (`:152` ⟂ `:350` — đúng ca PE đã chữa `view=approved` `:180-185`) | CAO | +| 4 | Thao tác/duyệt/xóa y khuôn KHKK | Bộ hành-vi submenu + nút trong màn duyệt theo Y KHUÔN KHKK prod (owner S176) | **ĐÚNG** (1 ranh chờ anh) | Bảng lệch 6-leaf đã đo: 3 🔴 (Luồng-duyệt slice · Danh-sách = Thứ-1 · Đã-duyệt `view=approved`) + 1 ⚠️ (Đang-duyệt → `pendingMe=1` thay trang Inbox rời) + 2 ✅; màn duyệt THIẾU nút Xóa (cột `AllowApproverDelete` Mig 68 DÙNG CHUNG V2, sẵn cho `HD-*`) — delta BE nhỏ 0-mig; **ranh:** 3 món cố-ý-không-port (skipToFinal/duyệt-thay-CEO/banner-kết-thúc-sớm, chặn bởi `ContractDetail` DTO 0 field) — mặc-định GIỮ khai-lệch, port = quyết của anh | CAO (ranh 3-món: VỪA) | +| 5 | Admin Designer per-loại HĐ | Sidebar admin cần mục RIÊNG từng loại y khuôn KHKK N1-8; "lane xác nhận đã có chưa hay đang gộp" | **ĐÚNG — và ĐÃ CÓ ~95%** | Menu-row + 28 policy + Designer family-slice + route ĐÃ land S188 (`DbInitializer.cs:2303-2310` · `ApprovalWorkflowsV2Page.tsx:314-396` · `App.tsx:80`); thiếu ĐÚNG nhánh `Hd*` trong `resolvePath` fe-admin (`Layout.tsx:175-189`, 0-hit `Hd` + control dương `KhkkN:188`) ⇒ leaf drop im lặng #50 — fix ≈ 5 dòng | CAO | ## Thứ-1 layout cây toàn trình @@ -87,8 +93,43 @@ ## Thứ-5 admin Designer per-loại -(pending) +**VERDICT: ~95% ĐÃ CÓ từ S188 — BE seed 7 menu-row + policy + Designer slice + route đều ĐỦ; thiếu ĐÚNG 1 nhánh `resolvePath` fe-admin ⇒ 7 leaf DROP IM LẶNG khỏi sidebar (đúng gotcha #50). Fix ≈ 5 dòng fe-admin, 0 BE, 0 mig, 0 seed mới.** + +1. **Sidebar fe-admin = DB-menu-driven, KHÔNG phải menu tĩnh** (bác giả-thuyết cũ): render từ `AuthContext.menu` → `filterForAdmin` lọc ĐỆ QUY theo `ADMIN_HIDDEN_KEYS` (`Layout.tsx:227-240` — ẩn Contracts/PE/KeHoachKyKet/HopDongCung/Workflows/PeWorkflows…; **`ApprovalWorkflowsV2` KHÔNG nằm trong tập ẩn**) + prefix `Ct_` (`:248`). Leaf sống PHẢI qua `resolvePath` — trả `null` = drop im lặng (`:251-260`). +2. **Menu-row GĐ3 ĐÃ SEED:** `DbInitializer.cs:2303-2310` sinh 7 leaf key `AwV2_Hd{TP,GK,NCC,DV,MB,NTNCC,NTDV}`, label `"QT Duyệt HĐ — {shortName}"`, parent `ApprovalWorkflowsV2`, Order 11..17 (tiếp ngay sau KHKK 3..10) — key sinh by-construction từ `MenuKeys.ApprovalWorkflowContractLeaf` (`MenuKeys.cs:151`) trên `ContractApprovalWorkflowFamily.Members` (invariant T6 `:2296-2300`: key vào `All` ⇒ 28 policy `AwV2_Hd*.{R,C,U,D}` + admin auto-grant). ⇒ leaf hiện có của mục "Quy trình duyệt (Mới)": `AwV2_DuyetNcc` · `AwV2_DuyetNccPhuongAn` · `AwV2_KhkkN1..8` render được; **7 leaf HĐ tồn tại trong DB nhưng KHÔNG hiện** — khớp ảnh-3. +3. **Lỗ duy nhất — `resolvePath` fe-admin (`Layout.tsx:175-189`)**: block `awV2Match` chỉ có 2 nhánh `DuyetNcc|DuyetNccPhuongAn|Contract` (`:178`) + `/^KhkkN[1-8]$/` (`:188`) — **0 nhánh `Hd*`** (grep `Hd|KhkkN` toàn file: chỉ `Hdc_*` GĐ4 `:49-55` + KhkkN `:188` = control dương cùng block). Trớ trêu: `lib/contractWorkflowFamily.ts:10-11` TỰ KHAI resolvePath là "chỗ đọc thứ 2 … thiếu là leaf DROP IM LẶNG — gotcha #50", lib dựng sẵn cho đúng việc này mà Layout **chưa import** (grep import: duy nhất `ApprovalWorkflowsV2Page.tsx:39`). Đây là ca "vá tệp A quên tệp B" kinh điển (S180): W6 nối trang Designer, quên nối sidebar. +4. **Designer page slice ĐÃ TRỌN (W6 S187, "type-3 family-slice"):** route path-param `/system/approval-workflows-v2/:typeCode` (`App.tsx:80`) → `findContractWfByTypeCode(typeCode)` (`ApprovalWorkflowsV2Page.tsx:314`) → `selectedTypeInt=3` (`:316-320`) → cắt `history.filter(d => d.code === familyCode)`, `active` suy TỪ lát cắt — cố ý KHÔNG đọc `ActiveOthers` (F-3 phương án ii, `:337-370`) → `lockedCode` khoá ô Mã (`:377`) → `panelLabel = ContractTypeLabel[n]` (`:385-389`) + panelDescription tự giải thích vì sao khoá (`:393-396`). Cùng MỘT đường với `KhkkN{n}` (`:298-308`, `:334-336` "Hai HỌ per-Code dùng CHUNG một đường"). 9-checkbox Sửa-tại-chỗ (ảnh-3, gồm cờ Xóa đỏ) round-trip sẵn cho MỌI workflow V2 kể cả `HD-*` (`ApprovalWorkflowV2AdminFeatures.cs:475,883,1288`). +5. **Việc CỤ THỂ ra 7 leaf "Duyệt HĐ — ":** CHỈ sửa fe-admin `components/Layout.tsx` — import `findContractWfByTypeCode` từ `@/lib/contractWorkflowFamily` + thêm sau `:188`: `if (findContractWfByTypeCode(code)) return '/system/approval-workflows-v2/' + code`. **KHÔNG dùng `?ct=`/`?family=`** — khuôn họ này là path-param `:typeCode` (`HdTP`…`HdNTNCC`) y hệt `KhkkN{n}`. KHÔNG sửa DbInitializer (label "QT Duyệt HĐ — Thầu phụ…" đã khớp khuôn "Duyệt KHKK — Nhóm n"; muốn đổi label thì BẮT BUỘC đường `labelBackfill` `:2301-2302` — không cần). Ghi chú phụ: leaf `AwV2_Contract` cũ ("cả loại Hợp đồng", `:178`) không thấy trong ảnh-3 — chưa đo row DB, không thuộc scope 7-leaf, uncertain vô hại. ## PROPOSE spec 3-mục + wave + checklist -(pending) +### ① Đề-bài (1 đoạn) + +Đồng-khuôn GĐ3 "Duyệt Hợp đồng" với KHKK + Duyệt NCC prod (luật owner S176: đã-deploy = CHUẨN): (Đ1) cây toàn trình đứng TRÁI làm trục điều hướng thay danh-sách; (Đ2+Đ3) menu 7 loại HĐ mang danh-tính đúng trục ContractType — hết nhảy lẫn, hết 2-leaf-cùng-sáng, leaf "Luồng duyệt" chỉ hiện đúng quy trình `HD-*` của loại đó (máy per-loại ĐÃ xong @S188 — toàn bộ việc là UI); (Đ4) bộ thao-tác theo hành-vi KHKK (Đang-duyệt ở lại cùng trang, Đã-duyệt danh-tính chuẩn, nút Xóa ở màn duyệt theo cờ per-Cấp); (Đ5) admin Designer hiện 7 leaf per-loại đã seed sẵn. Tổng: **FE-only + 1 delta BE nhỏ (W5, 0-mig)**. + +### ② Cách implement per-điều-chỉnh (file:line) + +- **Đ1 (cây trái):** `fe-user/pages/contracts/MyContractsPage.tsx:153` grid → `[400px_1fr_360px]`; panel-1 = `PipelineTreePanel currentStage={3} hideHeader hideSearch` + flat-list fallback server-side trong CÙNG panel (khuôn `KhkkListPage.tsx:171` + `KhkkListPanel.tsx:21-24,366-371`); panel-3 = hộp dashed khi chưa chọn / `WorkflowHistoryPanel` khi chọn (QĐ-2 `KhkkListPage.tsx:252-256` — CẤM cây ở panel-3). Gap phải bịt: `usePipelineStages.ts:377` leaf GĐ3 đang `navigate('/contracts/...')` → thêm opt-in `stage3Options.onOpenContract` (analog `onOpenKhkk` `:185,:244`) + wire `PipelineTreePanel.tsx:111` để chọn vào panel-2 qua `?id=`. **Host chỉ fe-user** (glob `fe-admin/src/pages/contracts/`: 4 file, KHÔNG có MyContractsPage); `usePipelineStages` + `PipelineTreePanel` = cặp MIRROR ×2 app → sửa cả 2 bản giữ SHA-identical. +- **Đ2+Đ3 (danh-tính menu + slice):** `fe-user/components/Layout.tsx:151` WfView → `/contracts/workflow-matrix?ct=N` (BỎ `type=3` khỏi URL — trang tự suy applicableType=3 theo path, khuôn alias-path khkk sẵn) · `:152` thêm `&view=approved` (khuôn PE `:180-185`, giữ `phase=9` làm lọc thật) · sửa comment stale `:141-142` ("chung 1 bộ" → 7 bộ per-loại S188) · accordion `:470-485` ưu tiên `ct` khi có + loại trừ pathname `/contracts/workflow-matrix` khỏi nhánh else (phòng-thủ 2 lớp) · `WorkflowMatrixViewPage.tsx` thêm nhánh đọc `ct` → lọc `code === HD-` y khuôn nhánh `group` `:84-98` (map ContractType→mã: const cục-bộ 7-entry khuôn `khkkGroupWorkflowCode` — fe-user KHÔNG mirror lib fe-admin, `contractWorkflowFamily.ts:16-18` tự khai fe-admin-ONLY). fe-admin KHÔNG đụng: `Ct_*` bị ẩn (`Layout.tsx:248`) + cố ý không có WorkflowMatrixViewPage (`:185-187`). +- **Đ4 (thao tác):** Đang-duyệt: `fe-user/Layout.tsx` `Ct_*_Pending` → `/my-contracts?type=N&pendingMe=1` (khuôn PE `:176`; BE param `pendingMe` sẵn) + `MyContractsPage` đọc `pendingMe` gửi server; GIỮ `/inbox` làm hộp thư tổng. Đã-duyệt/Đã-xóa: đã nằm Đ2+Đ3 (`view=approved`; `deleted=1` giữ nguyên ✅). Nút Xóa màn duyệt → W5. 3 món cố-ý-không-port: GIỮ khai-lệch (ngoài scope, chờ anh). +- **Đ5 (admin 7 leaf):** `fe-admin/components/Layout.tsx` import `findContractWfByTypeCode` từ `@/lib/contractWorkflowFamily` + thêm sau `:188`: `if (findContractWfByTypeCode(code)) return '/system/approval-workflows-v2/' + code`. Hết. (Menu-row/policy/Designer/route đã sẵn — xem mục Thứ-5.) +- **W5 BE nhỏ (nút Xóa, 0-mig):** mirror khuôn PE prod — `PeSoftDeleteFeatures.cs:110-114` (3 điều-kiện: ChoDuyet · ĐÚNG-LƯỢT actor · `matchingLevel.AllowApproverDelete`) + contract-surface `PurchaseEvaluationsController.cs:169`. Việc: nới delete-guard `ContractFeatures.cs:896-897` (đang so SỐ `Phase >= DangInKy` — chặn nhầm V2 ChoDuyet=10/TraLai=98/TuChoi=99, finding S160) thành V2-aware + nhánh xóa-bởi-approver đọc cờ (cột `ApprovalWorkflowLevels.AllowApproverDelete` Mig 68 DÙNG CHUNG V2 — Designer đã round-trip cho `HD-*` sẵn: `ApprovalWorkflowV2AdminFeatures.cs:475,883,1288`) + DTO expose cờ (khuôn `PurchaseEvaluationDtos.cs:138`) + FE `ContractWorkflowPanel.tsx` thêm mục Xóa mirror `KhkkWorkflowPanel.tsx:12-14,118,233` (panel SHA-mirror ×2 app). + +### ③ WAVE (5, thứ tự phụ thuộc) + CHECKLIST acceptance đo được + +Chỉnh so đề-xuất lead: **gộp slice-WfView vào W1** (route `:151` đổi sang `?ct=` và trang đọc `ct` là 2 nửa của MỘT thay đổi — tách wave thì trạng-thái trung-gian leaf trỏ `ct` mà trang chưa đọc); W3 thu về pendingMe; W4 độc lập chạy song song được bất kỳ lúc. + +- **W1 — Danh-tính menu + slice per-loại (fe-user, FE nhỏ — chữa bug anh đau nhất):** Layout `:151/:152/:141-142/:470-485` + WorkflowMatrixViewPage nhánh `ct`. + ✅ (i) tái-hiện A: mở nhóm "01. HĐ Thầu phụ" → click "Luồng duyệt" → accordion GIỮ nhóm 01, leaf sáng đúng (trước: đóng 01, mở 03); (ii) tái-hiện B: đứng `?type=1&phase=9&view=approved` → CHỈ leaf "Đã duyệt" sáng (trước: 2 leaf); (iii) WfView `ct=1` chỉ hiện họ `HD-TP` (0 dòng QT-HD-V2-001/6 loại kia); (iv) `grep -rn "workflow-matrix?type=3" fe-user/src` = 0-hit (control dương: grep `workflow-matrix?ct=` ≥1-hit `Layout.tsx`); (v) `npm run build` fe-user PASS. +- **W2 — Cây toàn trình sang trái (FE lớn):** MyContractsPage 3-panel đảo + `stage3Options.onOpenContract` + flatMode. + ✅ (i) grep `grid-cols-\[400px` MyContractsPage.tsx ≥1-hit; (ii) hành-vi: click leaf HĐ trên cây → panel-2 mở detail, URL Ở LẠI `/my-contracts` (trước: navigate rời `/contracts/{id}`); (iii) gõ search → flatMode list; (iv) cặp mirror `usePipelineStages.ts`/`PipelineTreePanel.tsx` 2 app: `git diff --stat` chạm cả 2 bản + so SHA256 từng cặp khớp; (v) `npm run build` 2 app PASS. +- **W3 — Đang-duyệt về cùng trang (FE nhỏ, sau W1 — cùng vùng Layout `:148-152` tránh conflict):** `Ct_*_Pending` → `pendingMe=1`. + ✅ (i) grep `pendingMe=1` fe-user Layout.tsx nhánh Ct_ ≥1-hit; (ii) hành-vi: leaf "Đang duyệt" ở lại `/my-contracts`, list = phiếu đến-lượt-mình (đối chiếu inbox cũ cùng user); (iii) build fe-user PASS. +- **W4 — Admin Designer 7 leaf (fe-admin ≈5 dòng, song song được):** resolvePath nhánh `Hd*`. + ✅ (i) đăng nhập admin → "Quy trình duyệt (Mới)" hiện đủ 17 leaf (2 NCC + 8 KHKK + 7 "QT Duyệt HĐ — …" Order 11..17); (ii) click "QT Duyệt HĐ — Thầu phụ" → panel title "…: HĐ Thầu phụ", ô Mã khoá `HD-TP`, history CHỈ version HD-TP; (iii) `npm run build` fe-admin PASS. +- **W5 — Nút Xóa màn duyệt V2-aware (BE nhỏ + FE, 0-mig, test-before cho guard):** ContractFeatures guard + delete-by-approver + DTO + panel ×2 app. + ✅ (i) `dotnet test SolutionErp.slnx` PASS + test mới: TraLai(98)/TuChoi(99) Drafter xóa được · ChoDuyet(10) CHỈ approver-đúng-lượt-có-cờ xóa được · cờ tắt → 403/409 · V1 `Phase>=DangInKy` VẪN chặn (regression S160); (ii) grep `AllowApproverDelete` trong `ContractFeatures.cs`/Contract-delete-path ≥1-hit (trước: 0-hit toàn Contract-side); (iii) panel 2 app SHA-identical + nút Xóa chỉ render khi DTO cờ bật; (iv) build 2 app PASS. + +**Ngoài wave (chờ anh / data-only):** ① gỡ-ghim hoặc thay `QT-HD-V2-001` (bản type-3 đặt tay duy nhất trên Dev) bằng 7 bản `HD-*` nếu anh muốn "tuyệt-đối mỗi loại 1 quy trình" — việc Designer/DATA, 0 code (van xả `ContractWorkflowGuards.cs:141-143` là CỐ Ý); ② 3 món cố-ý-không-port (skipToFinal / duyệt-thay-CEO / banner-kết-thúc-sớm) cần nở `ContractDetail` DTO nếu anh muốn ngang KHKK tuyệt đối. + +== HẾT — 3/3 mục B1c chốt == diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens1.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens1.md new file mode 100644 index 00000000..a4314d3a --- /dev/null +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens1.md @@ -0,0 +1,13 @@ +# LENS-1 CORRECTNESS — review đối-kháng spec SOLTUON 12-08-2026 (YC-029) + +## Verdict + +_(đang đo — điền cuối lượt)_ + +## Findings + +_(đánh số F-1.. — append ngay khi chốt)_ + +## Đề nghị sửa spec + +_(điền cuối lượt)_ diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens2.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens2.md new file mode 100644 index 00000000..f512b848 --- /dev/null +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens2.md @@ -0,0 +1,15 @@ +# sub-review-b2-lens2 — LENS-2 FIDELITY-KHUÔN + SCOPE + +> Reviewer lane-2/3 (ensemble /fable-clone). Lăng-kính: độ trung-thành với lời anh (YC-029 + 3 ảnh) + khuôn S176 "đã-deploy = CHUẨN" + scope-risk + mirror 2 app + wave order. + +## Verdict + +_(đang đo — điền cuối lượt)_ + +## Findings (F-1..) + +_(append từng finding ngay khi đo xong)_ + +## Đề nghị sửa spec + +_(điền cuối lượt)_ diff --git a/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens3.md b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens3.md new file mode 100644 index 00000000..aed91a99 --- /dev/null +++ b/.claude/workflows/runs/2026-08-12-S190-soltuon-dieu-chinh-hd/sub-review-b2-lens3.md @@ -0,0 +1,15 @@ +# LENS-3 ACCEPTANCE + VẬN HÀNH — review đối-kháng spec SOLTUON 12-08-2026 (YC-029) + +Reviewer lane-3/3 (ensemble /fable-clone). Lăng-kính: **acceptance ô-nào-gãy-khi-chạy-thật** + **vận hành W5 delete-path**. + +## Verdict + +_(điền sau khi đo)_ + +## Findings (F-1..) + +_(append từng finding ngay khi đo xong)_ + +## Đề nghị sửa spec + +_(điền cuối)_