wal: flush 20260727T1644
This commit is contained in:
@ -27,7 +27,9 @@ chain:
|
||||
[x] cicd verify cho `f4494cf` — **PASS**, run 531 success 5m41s (14:36:54→14:42:35); bundle prod hiện tại CHÍNH LÀ của commit này (LM 14:41–14:42) và chứa `view=approved` ×2 app. Đóng cùng lượt đo với đợt 2 (chung phép bundle)
|
||||
|
||||
[x] A2: đọc PDF (fitz — `pdftoppm` KHÔNG có, render bằng `fitz` rồi Read ảnh) + trích 21 bước vào `runs/2026-07-27-S156-bch-post-ceo-flow/run.md` + grounding 4 phép: `PE.DaDuyet=7` khớp "xong bước 6" · cầu PE→HĐ CÓ SẴN `CreateContractFromEvaluationFeatures.cs` · **`shopdrawing|TVGS|duyệt mẫu` = 0 hit toàn repo** (bước 8-9 đất trắng) · `ContractPhase` **6/9 `[LEGACY]`**
|
||||
[!] A2 `wf:` **`/fable-real investigator-codebase` (Fable, deep-pass) ĐANG CHẠY nền** — đề: quy trình chi tiết 7→21 + cách wire + checklist. Ghi `sub-invest-bch-1.md`. 🔴 Câu hỏi ranh-giới BẮT nó trả lời: bước 13→21 **dựng mới** hay **tái dùng module Contract**? → sau đó `/fable-clone review` (anh chỉ định)
|
||||
[x] A2 `wf:` `/fable-real investigator-codebase` (Fable) — 2 lượt (lượt 1 **#53 mất return**, cứu từ đĩa; lượt 2 resume cắt-ngắn, CLEAN). `sub-invest-bch-1.md` **22.659 B** verify khớp return. **VERDICT `LAI`**: b.13→21 **TÁI DÙNG** Contract V2 · b.7→12 **DỰNG MỚI**. Chứng quyết định: `ContractPhase.cs:3-13` — 7 phase vật-lý (góp ý/đàm phán/in ký/CCM/trình ký/đóng dấu) **bị CỐ Ý gỡ** post-Mig 21+S17, mà đó CHÍNH LÀ trạm của b.13→21 ⇒ hồi sinh = đi ngược kiến trúc
|
||||
[!] A2 **CHẶN: Q1-Q6 chờ anh** (14 câu tổng). §4 wire + §5 checklist chưa làm được vì "trả lời khác ⇒ wire khác". Nặng nhất **Q2 kiến trúc khúc 8-12** (a: module PostAward mới `ApplicableType=10` · b: HĐ trình 2 vòng — invest KHUYÊN TRÁNH · c: tối giản attachment+checklist trên PE). Rồi mới `/fable-clone review`
|
||||
[ ] 🔴 4 lỗ "cột CÓ mà 0 ai đọc" invest đào ra — cầu PE→HĐ pin V1 không nhận V2 · `CeoApprovalThreshold` **0-consumer phía HĐ** (b.18 "CEO ký >5 tỷ" KHÔNG có cơ chế, admin set bị ngó lơ IM LẶNG) · SLA V2 hardcode `AddDays(7)` (sơ đồ ghi 3 ngày) · `AttachmentPurpose` không phân biệt ký-nháy/ký-chính. Cùng lớp lỗi đã cắn 4 lần đợt PE ⇒ **đặc tính kiến trúc** (schema chung ⟂ service riêng per-type), không phải xui
|
||||
[ ] 🔴 vết lỗi lead @S156: viết `run.md` đã **điền SẴN kết-quả S2 cho lượt chạy CHƯA xảy ra** (byte-count + `TOTAL=14 GAP` + verdict = BỊA). Tự bắt ngay sau Write, sửa về `[ ]`, ghi vết trong `run.md`. Lớp `SHA-bịa` — xảy ra ngay trong lượt vừa khoe "đo-trước-tin" ⇒ ứng viên memory datum
|
||||
|
||||
next: **bump `docs/STATUS.md`** (test 532→562 · Mig 67→68 · counter →30 · row In Progress/Recently Done cho S155/S156 — `ctx-verifier` 🚩4: §In Progress còn đứng ở S117) → ghi memory 3 datum → rồi mới tới nhóm 🚩 `_mind` (nén MIND-1 trước khi chèn MIND-3).
|
||||
|
||||
@ -8,6 +8,7 @@ Read-only INTERNAL audit SOLUTION_ERP. Tools: Read/Grep/Glob/Bash + 5 RAG MCP. O
|
||||
- ❌ NOT: external docs/CVE/lib → investigator-api · write → implementer · test → test-specialist · architecture decision → em main
|
||||
|
||||
## 📌 Recent invest (1-line digest; full detail → archive/runs/git)
|
||||
- **S156 (07-27) BCH post-CEO flow bước 7→21 [§0-§3+§6 đĩa, §4-§5 PENDING lượt sau, `runs/2026-07-27-S156-bch-post-ceo-flow/sub-invest-bch-1.md`]:** Verdict **LAI** — 13→21 TÁI DÙNG Contract (7 dòng `[LEGACY]` `ContractPhase.cs:11-13` chính LÀ trạm 13-21 đã gỡ CỐ Ý Mig21/S17; V2 `ContractWorkflowService.cs:217-394` cookie-cutter sẵn, terminal gen-mã+DaPhatHanh) · 7-12 DỰNG MỚI (0-hit shopdrawing/TVGS, khuôn 12-bis + `ApplicableType=10` append-only). 🔴 Chuỗi "cơ-chế đúng, thứ đi qua KHÔNG có" phía HĐ: cầu PE→HĐ pin V1 (`CreateContractFromEvaluationFeatures.cs:68-71,108`) không nhận V2 + UpdateDraft không re-pin · `GetEligiblePhases` (`ContractFeatures.cs:334-351`) + inbox `PhaseActorRoles` (`:363-372`) 100% LEGACY-phase ⇒ approver V2/BCH KHÔNG xem/inbox được HĐ ChoDuyet · `CeoApprovalThreshold` 0-consumer HĐ (bước-18 ">5 tỷ" chưa có máy) · SLA V2 hardcode `AddDays(7)` 3 site, Step không có SlaDays · notify chỉ Drafter (`:407`) · `AttachmentPurpose` thiếu ký-nháy (enum-extend 0-mig tiền lệ PE=4) · HĐ TraLai reset-toàn-phần không 4-mode. Mig 68 `AddPeAllowApproverDelete` ĐÃ land 07-27 ⇒ mig kế = 69. Bắt lead sai grounding: 12 enum/7 LEGACY (lead ghi 9/6) — lead nhận. #53 strike-1 (return bốc hơi, đĩa nguyên → lead đọc từ đĩa, không redo). Tag `[s156, bch-post-ceo, verdict-lai, eligible-phases-legacy-only, bridge-pins-v1]`
|
||||
- **S155 (07-27) PE xóa-phiếu màn DUYỆT [24 finding, `runs/2026-07-27-S155-pe-delete-approver/sub-invest-be-1.md`]:** DELETE `/api/purchase-evaluations/{id}` ĐÃ CÓ (`PurchaseEvaluationsController.cs:146`, authz = class `[Authorize]` TRẦN) nhưng allow-list `{DangSoanThao,TuChoi}` (`PurchaseEvaluationFeatures.cs:1404`) chặn ChoDuyet. `Remove()`=**SOFT** gián tiếp qua `AuditingInterceptor.cs:56-62` — lớp #81-EXT indirect. Lũy kế: `PeBudgetAccumulator.cs` 2 hàm/4 call-site DUY NHẤT; ChoDuyet ăn số **2 chỗ** (`ComputeAsync:54` PrevSubmitted + `ComputePendingAsync:114` PendingSelected); `TraLai` KHÔNG triệt tiêu; `TuChoi` rơi khỏi 100% phép cộng. Query 0 dòng `IsDeleted` → dựa global `HasQueryFilter` (`PurchaseEvaluationConfiguration.cs:84`) ⇒ soft-del TỰ rớt, không sửa accumulator. Snapshot Mig67 KHÔNG re-compute. 🔴 Cascade 6 FK (`:75-80`) **không bao giờ chạy** vì soft ⇒ con `BaseEntity` ở lại = rác ẩn. **Git khảo cổ TRÚNG:** "chỗ cho hủy" = nút Từ chối, gỡ `6db195d` 12-06 S60; guard `PurchaseEvaluationWorkflowService.cs:101-106` còn sống tự trỏ "Xóa phiếu khi còn Bản nháp" = chính cái lỗ. 0 tiền lệ hủy chứng-từ in-flight; khuôn gần nhất `CancelMeetingBookingHandler` (`MeetingFeatures.cs:457`, Status=Cancelled NOT IsDeleted). Tag `[s155, pe-delete-approver, s60-tuchoi-removal-hole, soft-delete-no-cascade]`
|
||||
- **S155 (07-27) PE xóa-phiếu FE/authz-slice [18 finding, `runs/2026-07-27-S155-pe-delete-approver/sub-invest-fe-2.md`]:** Khối HÀNH ĐỘNG = `components/pe/PeWorkflowPanel.tsx:458-506` **byte-identical 2 app** (md5 `02671be6…`, cùng PeDetailTabs/PeListPanel/ListPage) ⇒ sửa-1-bên-là-sót. Gate 3 tầng: `?pendingMe=1`→`readOnly={!pendingMe}` (`ListPage:590`/`:676`) · `next=workflow.nextPhases` BE-source (`:257`) · `blockedByV2Level` (`:99-103` isAdmin ∥ actor∈currentApproval.approvers). 🔴 Plumbing xóa ĐÃ NỐI SẴN vào màn duyệt: `onDelete={del.mutate}` truyền ở `ListPage:573`+`:668` (`api.delete('/purchase-evaluations/:id')` `:90`) nhưng nút chết vì `PeDetailTabs:445` đòi `mode==='workspace' && canEditPhase && !readOnly`; nút hiện chỉ ở `:460` `phase===DangSoanThao`. **Authz 2 tầng:** PE vùng FE = **0-hit** `usePermission|PermissionGuard` (guard chỉ sống ở Master+Users, khuôn `DepartmentsPage:101 action="Delete"`); `menuKeys.ts` KHÔNG có const `Pe_*` (chỉ root `:23`) — `Pe_*` sinh BE `MenuKeys.cs:134-141`, seed `DbInitializer:1870-1877`, FE khớp bằng regex `Layout.tsx:120` (fe-admin `:107` **LỆCH**, thiếu WfView). 🔴 `Pe_*` **KHÔNG ∈ `MenuKeys.All`** ⇒ `Program.cs:82-89` không đăng-ký policy `Pe_*.{action}` (0 dynamic provider) ⇒ dùng `[Authorize(Policy="Pe_…")]` = policy-chưa-tồn-tại; **dùng được ngay = `PurchaseEvaluations.Delete`** (root ∈ All, + `GetMyMenuTreeQuery:66-72` cho `Pe_*` KẾ THỪA cờ CRUD từ root ⇒ 0 key mới, 0 migration). Ma trận enumerate `db.MenuItems` (`PermissionFeatures.cs:20`) nên ô Delete đã hiện sẵn. Q6: thêm-nút KHÔNG kích 4-place (0 route/page/staticMap `Layout.tsx:56-106`); `Pe_*` resolve nhánh regex `:119-134` KHÔNG qua staticMap. Tag `[s155, pe-delete-fe-authz, two-app-byte-identical, pe-keys-not-in-All]`
|
||||
- **S155 (07-27) PE menu/trash/dept-head [21 finding, `runs/2026-07-27-S155-pe-delete-approver/sub-invest-menu-3.md`]:** 🔴 Menu = **SEED DB** không hard-code FE — `Pe_<Code>` khai `DbInitializer.cs:1874-1877`; thêm mục = restart API, 0 migration (upsert `:1888-1914` chỉ sửa `Order`, **KHÔNG đụng Label** ⇒ rename qua `labelBackfill:1918-1924`; `DisplayLabel` **CHỈ ăn fe-user** `MenuDtos.cs:14`). 6-chỗ-mirror: +2 seed permission SONG SONG `:2092-2096`/`:2492-2496` + regex `Layout.tsx:120` (fe-admin `:107` thiếu `WfView`). Đổi KEY = mồ côi 13 row/key × 10 key ⇒ giữ key chỉ đổi label. **`Đã duyệt` chạy được HÔM NAY**: `phase=` đủ 3 tầng (`Controller:23`→`Features:565`→`:620`), DaDuyet=7 ⇒ `?type=1&phase=7`, 0 route mới. `pendingMe` KHÔNG phải param BE (FE rẽ `/inbox` `ListPage:61-68` + lọc client `:182`). `IgnoreQueryFilters` 0 src/Backend / 15 hit tests; `HasQueryFilter(`=12. An-toàn accumulator = **cấu trúc** (`PeBudgetAccumulator.cs:42`/`:100` dựng `peers` FRESH). 🎁 Changelog `: BaseEntity` + lọc CHỈ `PurchaseEvaluationId` (`:1424`) ⇒ lịch sử phiếu-xóa đọc MIỄN PHÍ; cái chôn = DETAIL bundle. 0 tiền lệ thùng-rác (hit "khôi phục" duy nhất = STRING `EmployeeFeatures.cs:162` ghost-wire). 🔴 **"Trưởng phòng" CÓ TÊN CHƯA CÓ ĐỜI**: `Department.ManagerUserId` **0/10 Dev** + 2 FE hardcode `managerUserId: null` payload SỬA (`DepartmentsPage.tsx:43`/`:57`) ⇒ tự-xoá mỗi lần sửa phòng. `PositionLevel.TruongPhong` 33/33 NULL (V1-legacy). Tag `[s155, menu-seed-db, phase-param-exists, changelog-survives-softdelete, dept-head-name-only]`
|
||||
|
||||
@ -93,17 +93,38 @@ repo đã có cả module HĐ + cầu PE→HĐ.
|
||||
→ propose-only; spec-file do LEAD ghi sau khi verify (H21 ① honest-note c)
|
||||
```
|
||||
|
||||
Sau đó: `/fable-clone review` (lệnh-B ensemble, anh chỉ định) chấm lại bản invest.
|
||||
### Wave 2 — `/fable-clone reviewer` ensemble 4 lane (anh chốt "review nền TRƯỚC, rồi anh trả lời")
|
||||
|
||||
> Đóng gói theo C2 (adap đợt-11): **≤3 file/lane** · **ép ghi khung rỗng lượt 1-2 TRƯỚC khi đọc** ·
|
||||
> **nêu trần lượt ngay đầu prompt** (`maxTurns: 25` — đối chứng `wf_301d3943-144` 3/3 lane sạch).
|
||||
> Label 4 thành-phần (C3) **neo tại đây** vì panel là ephemeral, không neo thì không tái lập được:
|
||||
|
||||
| Label (neo C3) | Lăng kính | File được đọc (≤3) |
|
||||
|---|---|---|
|
||||
| `Gate reviewer lens-verdict s156` | Tấn công verdict `LAI` — b.13→21 có THẬT tái dùng được không | `ContractPhase.cs` · `ContractWorkflowService.cs` · `CreateContractFromEvaluationFeatures.cs` |
|
||||
| `Gate reviewer lens-fidelity s156` | §3 có trung thực với sơ đồ nguồn không — bịa bước / rơi bước / gán sai lane | `sub-invest-bch-1.md` · `run.md` |
|
||||
| `Gate reviewer lens-q2 s156` | 🔴 **anh chỉ định**: stress-test cách ĐẶT VẤN ĐỀ Q2 — 3 phương án có vét cạn không, có mô tả công bằng không | `sub-invest-bch-1.md` · `ApprovalWorkflow.cs` · 1 tiền lệ WorkflowApps |
|
||||
| `Gate reviewer lens-gaps s156` | Verify độc lập 4 lỗ "cột CÓ mà 0 ai đọc" — có thật hay dương giả | `ContractWorkflowService.cs` · `ApprovalWorkflow.cs` · `ContractAttachment.cs` |
|
||||
|
||||
**taskList snapshot (wave 2):** 4 lane · `role: reviewer` × 4 · `tier: 'opus'` explicit từng lane
|
||||
(belt-and-suspenders — worker-tier-pin S124 đã che, nhưng lệnh này tự định nghĩa là "ensemble tier-2").
|
||||
Lane RETURN-only; lead = single-writer, refute + synthesize ở P3/P4.
|
||||
|
||||
## Stages
|
||||
|
||||
- [x] S0 — lead đọc PDF, trích 21 bước + grounding đĩa 4 phép
|
||||
- [x] S1 — scaffold run-folder + `run.md` (file này)
|
||||
- [ ] S2 — `/fable-real investigator-codebase` deep-pass → `sub-invest-bch-1.md`
|
||||
*(🔴 vết: bản đầu của dòng này lead điền SẴN kết-quả cho lượt chạy CHƯA xảy ra — byte-count,
|
||||
`TOTAL=14 GAP`, verdict đều là số BỊA. Tự bắt ngay sau khi Write, sửa về `[ ]`. Ghi lại làm chứng
|
||||
vì đây đúng lớp `SHA-bịa` đã có tiền lệ trong sổ, và nó xảy ra trong chính lượt vừa khoe
|
||||
"đo-trước-tin".)*
|
||||
- [x] S2a — `/fable-real investigator-codebase` (Fable) lượt 1 → §0 verify · §1 verdict `LAI` · §2 chứng-cứ.
|
||||
🔴 **return MẤT TRẮNG (`#53`)** — cứu TRỌN từ đĩa (7.234 B), đúng lý do bắt ghi-đĩa-trong-lúc-làm.
|
||||
- [x] S2b — SendMessage-resume (cố ý **cắt ngắn còn 2 mục** vì lượt 1 chết ở phần DÀI) → §3 bảng 15 bước
|
||||
9 cột · §6 **14 câu hỏi owner** (Q1-Q6 CHẶN THIẾT KẾ) · +§2-bis 6 chứng-cứ mới. **Return CLEAN**
|
||||
(header + END). Lead verify đĩa: **22.659 B**, §3 = 15 hàng, §6 = 14 câu, §4/§5 giữ `[PENDING]`
|
||||
đúng lệnh ⇒ **return khớp đĩa, không thổi phồng**.
|
||||
*(🔴 vết: bản đầu dòng S2 lead điền SẴN kết-quả cho lượt chạy CHƯA xảy ra — byte-count,
|
||||
`TOTAL=14 GAP`, verdict đều là số BỊA. Tự bắt ngay sau khi Write. Lớp `SHA-bịa`, xảy ra trong
|
||||
chính lượt vừa khoe "đo-trước-tin".)*
|
||||
- [ ] S2c — §4 wire chi tiết + §5 checklist — 🔴 **CHẶN bởi Q1-Q6** (invest tự khai "trả lời khác ⇒
|
||||
wire khác"); nặng nhất **Q2 = kiến trúc khúc 8-12**, quyết nhánh nào thì §4/§5 khác hẳn nhánh kia
|
||||
- [ ] S3 — lead verify + ghi `spec-bch-post-ceo-flow-27-07-2026.md` (3 heading H21)
|
||||
- [ ] S4 — `/fable-clone review` ensemble chấm lại
|
||||
- [ ] S5 — trình anh + chờ quyết
|
||||
|
||||
@ -82,7 +82,141 @@ sẽ rơi nhánh V1 legacy (hardcoded policy fallback nếu V1 không có active
|
||||
`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)
|
||||
### 2-bis. Chứng cứ bổ sung (đo sau lần flush đầu — §3 trích dẫn các mục này)
|
||||
|
||||
- `ContractFeatures.cs:334-351` `GetEligiblePhases` — IDOR view-guard list/detail xây **toàn bằng phase
|
||||
LEGACY**: không role nào map `ChoDuyet`/`DaPhatHanh`/`TraLai`/`TuChoi`. Non-admin không-phải-drafter
|
||||
(CCM/CEO/HR/BCH) **bị chặn xem** HĐ đang ChoDuyet — kể cả HĐ chờ chính mình duyệt (`:423-432` detail
|
||||
guard = isDrafter ∥ isEligibleByRole). BCH (thường ProjectManager) không thấy cả DangSoanThao
|
||||
(chỉ Drafter/DeptManager, `:342-343`).
|
||||
- `ContractFeatures.cs:363-372` inbox `PhaseActorRoles` — cũng 100% legacy-map, **không có entry
|
||||
ChoDuyet** ⇒ HĐ V2 đang chờ duyệt KHÔNG vào inbox của ai (PE có `ResolveV2InboxIdsAsync`, HĐ chưa
|
||||
từng được mirror).
|
||||
- `ContractWorkflowService.cs:407-427` notify khi transition → **chỉ Drafter**; không báo approver kế /
|
||||
BCH. `ContractWorkflowService.cs:49-66` nhánh Reject: không guard theo cấp, TraLai clear pointer —
|
||||
trình lại chạy từ Bước 1 Cấp 1 (không có 4 return-mode như PE).
|
||||
- `ContractFeatures.cs:151-157` UpdateContractDraft — guard duy nhất `Phase==DangSoanThao`, **không
|
||||
check drafter** ⇒ BCH sửa draft được về mặt cơ chế (nếu qua được view-guard); nhưng command **không có
|
||||
`ApprovalWorkflowId`** ⇒ không có đường re-pin V2 sau khi tạo.
|
||||
- `fe-user/src/pages/contracts/ContractDetailPage.tsx:1-36` — wrapper mỏng; UI thật ở
|
||||
`components/contracts/ContractDetailContent` + `WorkflowHistoryPanel` (2 app mirror).
|
||||
- `CreateContractFromEvaluationFeatures.cs:113` + `ContractFeatures.cs:113-118` — HĐ (cả 2 đường tạo)
|
||||
gen `MaHopDong` NGAY lúc create, không đợi terminal (khác skill-doc cũ "gen ở DangDongDau").
|
||||
|
||||
## 3. QUY TRÌNH CHI TIẾT — bước 7→21 dịch sang ngôn ngữ hệ thống (deliverable A)
|
||||
|
||||
> Bước 1-6 = module PE hiện tại, kết ở `PE.DaDuyet=7` — KHÔNG đụng. `❓Q<n>` = mơ hồ/thiếu/mâu thuẫn,
|
||||
> chi tiết ở §6. "PMH" = Phòng Mua hàng/Cung ứng (Procurement). "TP" = thầu phụ. Cột SLA = đúng những gì
|
||||
> sơ đồ ghi (3 mốc), "—" = sơ đồ không ghi.
|
||||
|
||||
| # | Lane | Actor | Trigger | Input | Output | Điều kiện chuyển | Nhánh lỗi | SLA |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| 7 | Procurement | PMH | PE chạm `DaDuyet=7` | Phiếu PE (winners `IsWinner`, giá `SUM Quote.IsSelected`, HoSoLink NAS) | Mail thông tin cho BCH/NTP/NCC phối hợp bước tiếp | Gửi xong → 8 | NTP/NCC = bên NGOÀI, email external chưa có (SMTP TODO) ❓Q8 · "BCH dự án X" chưa có định danh trong hệ thống ❓Q1 | — |
|
||||
| 8 | PROJECT | BCH + TVGS (TVGS = tư vấn giám sát NGOÀI hệ thống ❓Q7) | Nhận thông tin b.7 | Mẫu vật liệu + shopdrawing từ TP/NCC | Mẫu ĐƯỢC DUYỆT + shopdrawing ĐƯỢC DUYỆT (TVGS xác nhận) | Đủ bộ được duyệt → 9 | TVGS bác mẫu → TP/NCC nộp lại — sơ đồ KHÔNG vẽ vòng lặp; hệ thống = trạng thái per-item (nộp/duyệt/bác) | — |
|
||||
| 9 | PROJECT | BCH | Bộ b.8 đủ | Hồ sơ mẫu+shopdrawing đã duyệt + báo giá từ PE | Hồ sơ SO SÁNH GIÁ + ĐỀ XUẤT giá trị ký HĐ | Gửi PMH → 10 | Ghi chú sơ đồ: "hồ sơ sai sót thiếu khối lượng, sai spec, thiếu phạm vi → gửi mail làm rõ xác nhận" | — |
|
||||
| 10 | Procurement | PMH | Nhận đề xuất BCH | Hồ sơ so sánh giá + giá đề xuất | Giá trị HĐ TP xác nhận lại, chuyển CCM | OK → 11 | Không OK → trả BCH (sơ đồ không vẽ nhánh trả) | — |
|
||||
| 11 | CCM | CCM | Nhận từ 10 | Hồ sơ + giá đã xác nhận | Kết quả CCM kiểm tra | Pass → 12 | Fail → ? sơ đồ không vẽ (map hệ thống = Trả lại) | — |
|
||||
| 12 | CEO | CEO **hoặc** CCM | Nhận từ 11 | Hồ sơ giá trị ký HĐ | GIÁ TRỊ KÝ HĐ ĐƯỢC CHỐT (CEO ký / CCM đóng dấu approval) | Chốt → 13 | Điều kiện rẽ CEO-vs-CCM sơ đồ KHÔNG ghi ❓Q3 — khuôn gần nhất = `CeoApprovalThreshold` (PE-only) | — |
|
||||
| 13 | Procurement | PMH (= Drafter HĐ) | Giá chốt b.12 | Phiếu PE + giá chốt ❓Q6 + full bản vẽ/khối lượng/tính toán BCH gửi (ghi chú PHỐI HỢP) | HĐ DRAFT — hệ thống ĐÃ có cầu `POST /purchase-evaluations/{id}/create-contract` (DangSoanThao, gen mã ngay, N HĐ nếu multi-winner) — gửi BCH kiểm tra | Draft tới tay BCH → 14 | "Gửi BCH" hiện KHÔNG có kênh: notify chỉ Drafter + inbox HĐ legacy-map (§2-bis) · cầu pin V1 không nhận V2 (§1) | BCH gửi info trong **3 ngày** · khúc 13→18 = **7-10 ngày** |
|
||||
| 14 | PROJECT | BCH | Nhận draft | HĐ draft + scope/tiến độ thực tế | Draft ĐÃ bổ sung thông tin, gửi lại PMH xác nhận trước khi gửi TP | PMH xác nhận → 15 | Thiếu info → lặp 13↔14 (sơ đồ ghi PHỐI HỢP) · hệ thống: BCH bị IDOR-guard chặn XEM draft (role thường không map DangSoanThao §2-bis) ❓Q1 — sửa được thì cơ chế edit đã mở (update không check drafter) | 3 ngày |
|
||||
| 15 | Procurement | PMH ↔ TP (ngoài hệ thống) | Draft đã xác nhận | HĐ bản gửi TP | TP kiểm tra + đàm phán; TP chuyển bản về BCH ký nháy | TP đồng ý + ký nháy → 16 | Đàm phán đổi giá/điều khoản → quay về đâu (13 sửa draft? hủy?) — sơ đồ không vẽ ❓Q13 | trong khúc 7-10d |
|
||||
| 16 | PROJECT | BCH | Nhận bản TP đã ký nháy | HĐ giấy ký nháy | Chuyển bản ký nháy về PMH — hệ thống = upload scan (attachment không phase-guard, up được mọi phase) | PMH nhận → 17 | `AttachmentPurpose` chưa có loại "ký nháy" (chỉ ScannedSigned/SealedCopy) ❓Q12 | trong khúc 7-10d |
|
||||
| 17 | Procurement + CCM | PMH trình; CCM duyệt | Nhận HĐ ký nháy | HĐ + hồ sơ | PMH "chuyển sang trình ký (ký nháy hoặc ký chính ❓Q12)" — hệ thống = trình `DangSoanThao→ChoDuyet`, CCM = Step V2 đầu, CCM kiểm tra + KÝ NHÁY | CCM duyệt → 18 | CCM trả lại → `TraLai` reset TOÀN BỘ chuỗi (không có return-1-cấp như PE) ❓Q9 | trong khúc 7-10d |
|
||||
| 18 | CEO | CEO | CCM xong b.17 | HĐ + giá trị | CEO ký HĐ **nếu GiaTri > 5 tỷ** | Ký (hoặc ≤5 tỷ: skip — AI ký chính? ❓Q4) → 19 | CEO từ chối → TuChoi/TraLai · cơ chế ngưỡng phía HĐ CHƯA TỒN TẠI (`CeoApprovalThreshold` 0-consumer HĐ §2) ❓Q5 · multi-winner: ngưỡng per-HĐ hay per-GÓI ❓Q4 | kết khúc 7-10d |
|
||||
| 19 | Procurement | PMH → HR | HĐ ký xong | HĐ ký chính | HR đóng dấu — hệ thống: HR = Step V2 cuối; sau đó terminal `DaPhatHanh` (mã HĐ đã gen từ create) | Đóng dấu → 20 | — | — |
|
||||
| 20 | CCM | CCM | HĐ đã đóng dấu | HĐ hoàn chỉnh | Scan lưu trữ — `AttachmentPurpose.SealedCopy=3` CÓ SẴN, up được ở DaPhatHanh | Upload → 21 | — | — |
|
||||
| 21 | Procurement | PMH | Bản lưu xong | HĐ giấy | Chuyển phát nhanh về TP | XONG (hệ thống: HĐ đứng `DaPhatHanh` terminal) | Theo dõi vận đơn ngoài hệ thống ❓Q14 | — |
|
||||
|
||||
**Đọc bảng theo hệ thống — 4 khúc:**
|
||||
1. **7-12 = ĐẤT TRẮNG** (0-hit §0) — chuỗi: BCH làm hồ sơ (8-9) → duyệt 3 trạm PMH→CCM→CEO/CCM (10-12).
|
||||
Cấu trúc 10-12 giống hệt 1 workflow V2 3-Step. Kiến trúc chọn ở ❓Q2.
|
||||
2. **13-14 = `DangSoanThao`** (draft cộng tác PMH↔BCH — cơ chế edit mở sẵn, cơ chế XEM đang chặn BCH).
|
||||
3. **15-16 = offline/giấy** — hệ thống ghi vết bằng attachment + comment, không phase riêng (đúng triết lý
|
||||
Mig 21 đã gỡ DangDamPhan/DangInKy).
|
||||
4. **17-19 = `ChoDuyet`** chạy Steps V2 (CCM → CEO-theo-ngưỡng → HR) → **20-21 = `DaPhatHanh`** + attachment.
|
||||
Lane ⑥ ghi chú NCC "phải duyệt mẫu/shopdrawing MỚI ký HĐ" = GATE giữa khúc 1 và khúc 4 ❓Q11.
|
||||
## 4. [PENDING] Wire chi tiết B
|
||||
## 5. [PENDING] Checklist C
|
||||
## 6. [PENDING] Câu hỏi owner
|
||||
## 6. CÂU HỎI CHO OWNER (14 câu — Q1-Q6 CHẶN THIẾT KẾ, trả lời khác ⇒ wire khác)
|
||||
|
||||
**Q1 🔴 CHẶN — "BCH Công trường của dự án X" là AI trong hệ thống?**
|
||||
Vì sao hỏi: không tồn tại model nào — `Department.ManagerUserId` 0/10 row Dev + FE hardcode null
|
||||
(S155), `User.PositionLevel` 33/33 NULL, `Project` không có field team/BCH; đồng thời IDOR-guard hiện
|
||||
chặn BCH xem HĐ (§2-bis). Phương án: **(a)** thêm `Project.BchDepartmentId`/bảng `ProjectMembers` →
|
||||
model đúng nhưng +migration +màn admin gán; **(b)** role mới `SiteCommand` + so DepartmentId → rẻ hơn
|
||||
nhưng không phân biệt được BCH dự án A vs B; **(c)** làm như PE: chỉ đích danh user trong Level của
|
||||
workflow V2 (không cần model BCH) → 0 migration, nhưng "BCH" chỉ tồn tại trong từng quy trình, đổi người
|
||||
= sửa quy trình (mà V2 KHÔNG có lệnh Update — S155). Chọn phương án nào?
|
||||
|
||||
**Q2 🔴 CHẶN — Khúc 8-12 dựng thành module MỚI hay Contract-sớm?**
|
||||
Vì sao hỏi: sơ đồ chỉ sinh HĐ draft ở b.13, nhưng 10-12 lại là chuỗi duyệt giống hệt V2. Phương án:
|
||||
**(a)** module mới "Hồ sơ sau trúng thầu" (PostAward) FK→PE, có Phase + `ApprovalWorkflowId` riêng
|
||||
(`ApplicableType=10` append-only theo tiền lệ Mig 37), duyệt xong mới cho tạo HĐ → tách bạch, mirror
|
||||
khuôn 12-bis (PE/Proposal/WorkflowApps), nhưng +N bảng +menu +2 FE; **(b)** tạo Contract NGAY sau b.7
|
||||
và cho HĐ trình 2 VÒNG (vòng giá 10-12, vòng ký 17-19) → ít bảng mới nhưng phá state machine 5-trạng-thái
|
||||
hiện tại (1 HĐ 2 lần ChoDuyet = đổi service + FE lớn, rủi ro cao); **(c)** tối giản: 8-9 chỉ là
|
||||
attachment + checklist trên PE (không workflow 10-12 trong hệ thống, PMH/CCM/CEO xác nhận ngoài) →
|
||||
gần như 0 công BE, nhưng mất vết duyệt 10-12. Em nghiêng (a) hoặc (c) — (b) khuyên tránh; anh chốt?
|
||||
|
||||
**Q3 🔴 CHẶN — Bước 12: điều kiện nào rẽ "CEO ký" vs "CCM đóng dấu approval"?**
|
||||
Vì sao hỏi: sơ đồ ghi "hoặc" không ghi điều kiện. Cùng ngưỡng 5 tỷ như b.18? Hay CCM luôn đóng dấu và
|
||||
CEO chỉ ký gói lớn? Ảnh hưởng: cấu hình workflow khúc 10-12 (nếu Q2=a) — có Step CEO điều kiện hay không.
|
||||
|
||||
**Q4 🔴 CHẶN — Bước 18: HĐ ≤ 5 tỷ thì AI ký chính? Và 5 tỷ tính trên gì khi multi-winner?**
|
||||
Vì sao hỏi: (i) sơ đồ chỉ nói CEO ký >5 tỷ, không nói nhánh còn lại (role `AuthorizedSigner` có sẵn
|
||||
trong hệ thống — dùng?); (ii) 1 phiếu PE liên-danh sinh N HĐ, MỖI HĐ 1 GiaTri riêng
|
||||
(`CreateContractFromEvaluationFeatures.cs:88-90`) — gói 6 tỷ chia 3 HĐ × 2 tỷ sẽ TRƯỢT ngưỡng nếu tính
|
||||
per-HĐ. Per-HĐ hay per-gói (SUM các HĐ cùng phiếu)?
|
||||
|
||||
**Q5 🔴 CHẶN — Cơ chế ngưỡng b.18 phía HĐ wire kiểu nào?** (phụ thuộc Q4)
|
||||
Vì sao hỏi: `CeoApprovalThreshold` là cột CHUNG bảng `ApprovalWorkflows` nhưng chỉ PE service đọc —
|
||||
admin set vào workflow Contract-type sẽ bị ngó lơ im lặng (§2). Phương án: **(a)** port logic threshold
|
||||
vào `ContractWorkflowService.ApproveV2Async` (mirror PE, 0 migration, cột sẵn) — CCM finalize khi
|
||||
GiaTri < ngưỡng; **(b)** 2 workflow Contract-type (có/không Step CEO), PMH chọn theo giá trị lúc trình
|
||||
— 0 code BE nhưng dựa kỷ luật người dùng, sai chọn = sai luồng; **(c)** port `AllowApproverFinalize`
|
||||
per-slot (cũng đang PE-only). (a) đúng tinh thần "5 tỷ" tự động nhất.
|
||||
|
||||
**Q6 🔴 CHẶN — Giá trị nào ghi vào HĐ: giá CHỐT bước 12 hay SUM báo giá PE?**
|
||||
Vì sao hỏi: cầu hiện lấy `SUM Quote.IsSelected` từ PE; nhưng b.9-12 tồn tại chính vì khối lượng/giá
|
||||
sau duyệt mẫu + shopdrawing có thể LỆCH con số PE. Nếu giá-12 thắng: cần chỗ lưu giá chốt (PostAward
|
||||
nếu Q2=a) + cầu đọc từ đó + audit lệch PE-vs-chốt. Nếu PE thắng: b.10-12 chỉ là xác nhận, lệch xử lý
|
||||
bằng sửa tay draft (đã cho phép sửa GiaTri ở DangSoanThao).
|
||||
|
||||
**Q7 — TVGS là user đăng nhập hay chỉ được ghi vết?**
|
||||
Vì sao hỏi: TVGS = tư vấn giám sát phía chủ đầu tư, NGOÀI công ty. Phương án: (a) BCH nhập hộ kết quả
|
||||
(tên TVGS + ngày + scan chữ ký) → 0 user mới, khuyến nghị; (b) cấp account TVGS → thêm role +
|
||||
permission + rủi ro lộ dữ liệu nội bộ. Sơ đồ không đòi (b) — xác nhận (a)?
|
||||
|
||||
**Q8 — Email ra NGOÀI (b.7 NTP/NCC, b.15 gửi TP, b.21 báo chuyển phát) có trong scope hệ thống không?**
|
||||
Vì sao hỏi: SMTP outbox = TODO toàn hệ thống (CLAUDE.md); notification hiện in-app + SignalR nội bộ.
|
||||
Nếu trong scope → mở công trình email riêng (MailKit + template + địa chỉ NCC từ Supplier 30-field).
|
||||
Nếu ngoài (PMH gửi Outlook tay) → hệ thống chỉ cần nút "đánh dấu đã gửi" + changelog.
|
||||
|
||||
**Q9 — Trả lại giữa khúc 17-19 chấp nhận reset-về-đầu không?**
|
||||
Vì sao hỏi: HĐ V2 chỉ có TraLai toàn-phần (`ContractWorkflowService.cs:57-61` — trình lại chạy từ Bước 1
|
||||
Cấp 1); PE có 4 return-mode (1-cấp/1-bước/assignee/drafter) nhưng HĐ chưa từng port. CEO trả 1 câu chữ
|
||||
→ đi lại từ CCM. Chấp nhận (0 công) hay port return-mode (công vừa, mirror PE)?
|
||||
|
||||
**Q10 — SLA "3 ngày" (13-14) và "7-10 ngày" (13→18) có cần hệ thống ENFORCE không?**
|
||||
Vì sao hỏi: V2 không có per-step SLA — service hardcode `AddDays(7)` mọi bước (§2), muốn đúng 3 ngày
|
||||
phải thêm cột `SlaDays` vào `ApprovalWorkflowSteps` (+migration +Designer +service đọc). Hay chỉ cần
|
||||
hiển thị deadline tham khảo (0 công, dùng 7d mặc định)?
|
||||
|
||||
**Q11 — Gate lane ⑥: "NCC phải duyệt mẫu/shopdrawing MỚI ký HĐ" — chặn CỨNG hay cảnh báo MỀM?**
|
||||
Vì sao hỏi: quyết định guard ở đâu: (cứng) chặn trình-ký/tạo-HĐ khi package 8-9 chưa đủ — cần Q2=a để
|
||||
có trạng thái machine-checkable; (mềm) banner cảnh báo — rẻ, giữ linh hoạt (khuôn "vượt ngân sách =
|
||||
cảnh báo mềm" S62 đã có tiền lệ). Và gate áp cho cả THẦU PHỤ không (sơ đồ chỉ ghi cho NCC; TP ký
|
||||
"song song HĐ chủ đầu tư")?
|
||||
|
||||
**Q12 — Phân biệt ký NHÁY vs ký CHÍNH bằng gì?**
|
||||
Vì sao hỏi: `AttachmentPurpose` chỉ có ScannedSigned/SealedCopy — b.16 (TP ký nháy), b.17 (CCM ký nháy),
|
||||
b.18 (ký chính) hiện không phân biệt được. Phương án: thêm enum `InitialSigned=4` (int column, KHÔNG cần
|
||||
migration — tiền lệ PE `ComparisonTable=4`) — đủ chưa, hay owner muốn trạng thái ký riêng trên HĐ?
|
||||
|
||||
**Q13 — Bước 15 đàm phán làm ĐỔI nội dung/giá thì quay về đâu?**
|
||||
Vì sao hỏi: sơ đồ không vẽ nhánh lùi 15→13. HĐ đang DangSoanThao thì sửa thoải mái (cơ chế mở); nhưng
|
||||
nếu lúc đó đã trình (ChoDuyet) thì phải TraLai. Quy ước vận hành: CHỈ trình sau khi TP chốt xong (16)?
|
||||
— nếu vậy b.17 "trình ký" là điểm trình DUY NHẤT, khớp mapping §3 khúc 4.
|
||||
|
||||
**Q14 — Bước 21 có cần lưu mã vận đơn chuyển phát không?** (phụ, không chặn)
|
||||
Nếu cần: +1 field/ghi chú attachment; nếu không: comment đủ.
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
# sub-review-verdict-1 — reviewer ADVERSARIAL tấn công verdict `LAI`
|
||||
|
||||
> Ghi TRƯỚC khi đọc (khung rỗng lượt 1). Append dần theo từng phép đo.
|
||||
> Mục tiêu: công verdict §1 bản invest — "b.13→21 TÁI DÙNG Contract V2 · b.7→12 DỰNG MỚI".
|
||||
> Ranh: read-only. Không sửa code-tree, không commit.
|
||||
|
||||
## 0. Meta
|
||||
|
||||
- Run: 2026-07-27-S156-bch-post-ceo-flow
|
||||
- Target đọc (tối đa 3): ContractPhase.cs · ContractWorkflowService.cs · CreateContractFromEvaluationFeatures.cs
|
||||
- LENS-VERDICT: _(chốt ở §6)_
|
||||
|
||||
## 1. Q1 — "phase bị gỡ = trạm của b.13→21" có đứng không?
|
||||
|
||||
_(chờ đo)_
|
||||
|
||||
## 2. Q2 — `ApproveV2Async` gánh được chuỗi CCM→CEO→HR?
|
||||
|
||||
_(chờ đo)_
|
||||
|
||||
## 3. Q3 — bước 15-16 (đàm phán + ký nháy ngoài hệ thống) map vào attachment — mất vết gì?
|
||||
|
||||
_(chờ đo)_
|
||||
|
||||
## 4. Q4 — nhánh invest BỎ QUA
|
||||
|
||||
_(chờ đo)_
|
||||
|
||||
## 5. Bảng điểm công
|
||||
|
||||
_(chờ đo)_
|
||||
|
||||
## 6. LENS-VERDICT
|
||||
|
||||
_(chờ đo)_
|
||||
Reference in New Issue
Block a user