From 95a529c3079b49bc56e2cd1fbd1a6c31ca2d918c Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Mon, 27 Jul 2026 16:32:48 +0700 Subject: [PATCH] wal: flush 20260727T1632 --- .../2026-07-27-S156-bch-post-ceo-flow/run.md | 18 +++- .../sub-invest-bch-1.md | 88 +++++++++++++++++++ 2 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 .claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/sub-invest-bch-1.md diff --git a/.claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/run.md b/.claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/run.md index 6154cef..6137bea 100644 --- a/.claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/run.md +++ b/.claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/run.md @@ -64,11 +64,23 @@ lượng/tính toán chính xác để PMH soạn HĐ) · `7-10 ngày` (khoảng | `PurchaseEvaluationPhase.DaDuyet = 7` | terminal thành công ⇒ **khớp lời anh "xong bước 6"** | | Cầu PE → HĐ | **CÓ SẴN** `src/Backend/SolutionErp.Application/PurchaseEvaluations/CreateContractFromEvaluationFeatures.cs` | | `grep -li "shopdrawing\|TVGS\|duyet mau"` trên `src/Backend` + 2 FE | 🔴 **0 hit** ⇒ bước 8-9 là **đất trắng hoàn toàn** | -| `ContractPhase` | 9 phase, **6 đánh dấu `[LEGACY]`**; sống: `DangSoanThao=2` · `ChoDuyet=10` · `DaPhatHanh=9` · `TraLai=98` · `TuChoi=99` | +| `ContractPhase` | **12 giá trị enum, 7 dòng `[LEGACY]`**; sống 5: `DangSoanThao=2` · `DaPhatHanh=9` · `ChoDuyet=10` · `TraLai=98` · `TuChoi=99` | 🔴 **Câu hỏi ranh giới mà invest PHẢI trả lời (đừng giả định hộ):** bước 13→21 là **dựng mới**, hay -**tái dùng module Contract đang có** (7 ContractType × 9 phase, feature-complete)? Sơ đồ có lane -"KÝ KẾT HỢP ĐỒNG" riêng, nhưng repo đã có cả module HĐ + cầu PE→HĐ. +**tái dùng module Contract đang có** (feature-complete)? Sơ đồ có lane "KÝ KẾT HỢP ĐỒNG" riêng, nhưng +repo đã có cả module HĐ + cầu PE→HĐ. + +> ✅ **ĐÃ TRẢ LỜI** (invest §1, `sub-invest-bch-1.md`): **`LAI`** — bước **13→21 TÁI DÙNG** Contract V2 +> (KHÔNG hồi sinh LEGACY enum) · bước **7→12 DỰNG MỚI** theo khuôn cookie-cutter V2 sẵn có. +> 🔑 Lý do quyết định nằm ở `ContractPhase.cs:3-13`: 7 phase vật-lý trung gian (góp ý/đàm phán/in ký/ +> CCM/trình ký/đóng dấu) **bị CỐ Ý gỡ** post-Mig 21 + Session 17, thay bằng `ChoDuyet=10` + con-trỏ chạy +> trên workflow V2 admin-config. **Các "trạm" của bước 13→21 CHÍNH LÀ những phase đã bị gỡ** ⇒ hồi sinh +> enum = đi ngược quyết định kiến trúc S16-S17. + +> 🔧 **Đính chính số của lead (invest bắt, máy xác nhận):** lead ghi "9 phase, 6 LEGACY" — đếm máy ra +> **12 giá trị / 7 `[LEGACY]`**. Sai cả hai số; lead neo nhầm vào `DaPhatHanh = 9` rồi đọc thành "9 phase". +> Kết luận ranh-giới KHÔNG đổi, nhưng số trong bảng trên đã sửa. *(Cùng lớp `meta-count` đã có tiền lệ: +> lead ĐO tốt nhưng ĐẾM sai — và lần này con-đo bắt được lead, đúng chiều vòng KIỂM sinh ra để phục vụ.)* --- diff --git a/.claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/sub-invest-bch-1.md b/.claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/sub-invest-bch-1.md new file mode 100644 index 0000000..a770a19 --- /dev/null +++ b/.claude/workflows/runs/2026-07-27-S156-bch-post-ceo-flow/sub-invest-bch-1.md @@ -0,0 +1,88 @@ +# sub-invest-bch-1 — Quy trình bước 7→21 (lane PROJECT/BCH) + wire + checklist + +> **Run:** `2026-07-27-S156-bch-post-ceo-flow` · agent: investigator-codebase (/fable-real, effort max) +> **Trạng thái file:** GHI TRONG LÚC LÀM — mục nào chưa có ghi `[PENDING]`. File này = sản phẩm chính (#53 mitigation). +> **Nguồn sự-thật sơ đồ:** bảng 21 bước trong `run.md` cùng thư mục. KHÔNG bịa bước ngoài bảng. + +--- + +## 0. Verify grounding lead (4 phép — làm lại từ đĩa, không tin suông) + +| Phép | Lệnh em chạy | Kết quả | Khớp lead? | +|---|---|---|---| +| shopdrawing/TVGS/duyệt mẫu | `grep -rli "shopdrawing\|TVGS\|duyet mau\|duyệt mẫu"` trên `src/Backend` + `fe-admin/src` + `fe-user/src` | **0 hit** | ✅ khớp — bước 8-9 đất trắng | +| `ContractPhase` LEGACY | Read `src/Backend/SolutionErp.Domain/Contracts/ContractPhase.cs` | 12 giá trị enum, 7 dòng `[LEGACY]` comment (DangChon/DangGopY/DangDamPhan/DangInKy/DangKiemTraCCM/DangTrinhKy/DangDongDau); sống = DangSoanThao=2, DaPhatHanh=9, ChoDuyet=10, TraLai=98, TuChoi=99 | ✅ khớp (lead nói "6 LEGACY" — đếm lại là **7** kể cả DangChon=1; sai số nhỏ không đổi kết luận) | +| Cầu PE→HĐ | Read `CreateContractFromEvaluationFeatures.cs` (204 dòng) | CÓ THẬT, guard `Phase==DaDuyet` + `IsWinner≥1` + `ContractId==null`, multi-winner → N HĐ draft | ✅ khớp | +| `PurchaseEvaluationPhase.DaDuyet=7` | (đã biết từ S133/S155 + `ListApprovedPurchaseEvaluationsQuery:173` filter `Phase == DaDuyet`) | terminal thành công | ✅ khớp | + +**VÌ SAO LEGACY (quyết định câu ranh giới):** `ContractPhase.cs:3-13` ghi thẳng — post-Mig 21 (S16) ++ Session 17 spec 5-trạng-thái, 7 phase VẬT-LÝ trung gian (góp ý/đàm phán/in ký/CCM/trình ký/đóng dấu) +bị **CỐ Ý bỏ**, thay bằng `ChoDuyet=10` đơn nhất + con trỏ `CurrentWorkflowStepIndex`/`CurrentApprovalLevelOrder` +chạy trên **workflow V2 admin-config** (`ApprovalWorkflows` Steps=Phòng > Levels=Cấp OR-of-N). +⇒ Các "trạm vật-lý" của bước 13→21 sơ đồ (đàm phán, ký nháy, CCM kiểm tra, CEO ký, HR đóng dấu) +**chính là** những phase đã bị gỡ — công ty đã từng mô hình hoá đúng dải này bằng enum cứng và ĐÃ THAY +bằng mô hình phẳng cấu hình được. Hồi sinh enum = đi ngược quyết định kiến trúc S16-S17. + +--- + +## 1. VERDICT RANH GIỚI (deliverable B câu hỏi bắt buộc) + +**`LAI` — tách làm 2 khúc:** + +- **Bước 13→21 = TÁI DÙNG module Contract hiện có** (không dựng mới, không hồi sinh LEGACY enum). + Chứng: + 1. Cầu PE→HĐ có sẵn (`CreateContractFromEvaluationFeatures.cs:92-115` tạo draft `DangSoanThao` + + gen mã ngay + GiaTri = SUM quote IsSelected per winner). + 2. Contract V2 approve = cookie-cutter PE (`ContractWorkflowService.cs:217-394 ApproveV2Async`: + OR-of-N match `:259-260`, UPSERT `ContractLevelOpinions` `:292-316`, skipToFinal `:320-352`, + terminal gen mã + `DaPhatHanh` `:366-385`). Trạm 17→18→19 map thành Steps của 1 workflow + `ApplicableType.Contract=3` (`ApprovalWorkflow.cs:57` — CÓ SẴN). + 3. Bước 15-16 (đàm phán giấy + ký nháy với thầu phụ NGOÀI hệ thống) = upload attachment + `AttachmentPurpose.ScannedSigned=2` (`ContractAttachment.cs:8`) + comment/changelog — mô hình + phẳng hấp thụ trạm offline bằng chứng-từ đính kèm, đúng cách 7 phase cũ bị gỡ. + 4. Bước 19-20 (đóng dấu + scan lưu trữ) = `SealedCopy=3` (`ContractAttachment.cs:9`) có sẵn. +- **Bước 7→12 = DỰNG MỚI (đất trắng có chứng 0-hit)** — nhưng dựng theo khuôn cookie-cutter V2 + có sẵn (12-bis đã lặp 12×: PE → Contract → Proposal → 4 WorkflowApps), KHÔNG phát minh pattern mới. + Lý do không nhét vào PE: PE.Phase đã terminal `DaDuyet`, gắn thêm chuỗi duyệt thứ 2 lên cùng entity + = 2 con trỏ workflow trên 1 record (mâu thuẫn `ApprovalWorkflowId` 1-cột). Lý do không nhét vào + Contract: bước 8-12 xảy ra TRƯỚC khi có HĐ draft (bước 13 mới sinh draft); và giá trị ký HĐ được + chốt ở bước 12 là INPUT cho draft. + +**Điểm LAI thứ 3 (phát hiện ngoài câu hỏi):** cầu PE→HĐ hiện pin **V1** `WorkflowDefinitionId` +(`CreateContractFromEvaluationFeatures.cs:68-71,108`) và **KHÔNG có tham số** `ApprovalWorkflowId` V2, +trong khi create-HĐ thường (`ContractFeatures.cs:37,79,109`) ĐÃ nhận pin V2 từ S29. HĐ sinh từ phiếu +sẽ rơi nhánh V1 legacy (hardcoded policy fallback nếu V1 không có active def) — đúng lớp lỗi +"cơ-chế đúng, thứ đi qua nó KHÔNG có". Muốn bước 13→21 chạy trạm V2 thì cầu PHẢI nhận + pin V2. +`[ĐÃ VERIFY — xem §2 mục B-1]` + +--- + +## 2. Chứng cứ nền đã thu (ghi dần) + +- `ContractPhase.cs:14-28` — enum 12 giá trị, sống 5. +- `CreateContractFromEvaluationFeatures.cs:53-60` guard DaDuyet/winner/idempotent; `:88-90` GiaTri per + winner = SUM `Quote.IsSelected` của NCC đó; `:104` carry PaymentTerms → DraftData; `:106-107` carry + NS kỳ này → BudgetManual*; `:113` gen `MaHopDong` NGAY lúc tạo từ phiếu (khác luồng thường: gen ở + terminal DaPhatHanh `ContractWorkflowService.cs:371-377` — HĐ từ phiếu có mã trước khi duyệt). +- `ApprovalWorkflow.cs:53-67` — `ApplicableType` 9 giá trị (1-9), append-only (tiền lệ Mig 37 extend + enum KHÔNG cần migration bảng). Slot 10 trống cho module mới. +- `ApprovalWorkflow.cs:43` `CeoApprovalThreshold` — grep toàn `src/Backend`: consumer CHỈ PE + (`PurchaseEvaluationWorkflowService.cs` + PE features/DTOs + admin features). **0 hit trong + `ContractWorkflowService.cs`** ⇒ bước 18 "CEO ký nếu >5 tỷ" hiện KHÔNG có cơ chế phía HĐ (cột DB + dùng chung có sẵn, service HĐ không đọc — admin set vào workflow Contract-type sẽ bị NGÓ LƠ im lặng). +- `ApprovalWorkflowLevel.cs:156-169` — **Mig 68 `AddPeAllowApproverDelete` ĐÃ LAND** (file mig + `20260727033522_*` tồn tại) ⇒ mọi migration mới của run này đánh số từ **69**. +- `ContractAttachment.cs:5-11` — Purpose: DraftExport=1 / ScannedSigned=2 / SealedCopy=3 / Other=99. + KHÔNG phân biệt ký-nháy (initial) vs ký-chính — bước 16 vs 17 cần thêm giá trị enum (int column, + tiền lệ PE `ComparisonTable=4` thêm enum không cần migration). +- `ContractsController.cs:12-13` — class-level `[Authorize]` TRẦN, 0 per-action policy (mirror PE + S147/S155). 29 endpoint sống: CRUD + transitions + comments + attachments + 7×2 details + changelogs + + department-approvals. +- `ContractWorkflowService.cs:341,358,390` — SLA V2 advance = **hardcode `AddDays(7)`**; + `ApprovalWorkflowStep` KHÔNG có cột SlaDays ⇒ SLA "3 ngày BCH bổ sung" (ghi chú sơ đồ) không config + được per-step trong V2 hiện tại. + +## 3. [PENDING] Quy trình chi tiết A (bảng 7→21) +## 4. [PENDING] Wire chi tiết B +## 5. [PENDING] Checklist C +## 6. [PENDING] Câu hỏi owner