# 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.

### 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. 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 đủ.
