53 lines
3.7 KiB
Markdown
53 lines
3.7 KiB
Markdown
# sub-implementer-frontend-1 — W3 ĐỢT-1b: FE panel duyệt KHKK ×2 app (S161, 2026-07-29)
|
||
|
||
> Ghi TỪNG MỤC trong lúc làm (chống #53). Task: panel `KhkkWorkflowPanel.tsx` + gắn DetailPage + types transitions, SHA-pair ×2 app, build ×2.
|
||
> BE logic W3 CHƯA có (task 1 skeleton song song) ⇒ bấm nút sẽ 404/500 — CHẤP NHẬN đợt này.
|
||
|
||
## MỤC 0 — Baseline SHA (trước khi sửa)
|
||
|
||
```
|
||
340e64d0… fe-user/src/types/khkk.ts = fe-admin (PAIR OK)
|
||
9b91606e… fe-user/src/pages/khkk/KhkkDetailPage.tsx = fe-admin (PAIR OK)
|
||
```
|
||
|
||
## MỤC 1 — RECON: field THẬT của detail DTO (BE đĩa, KHÔNG suy)
|
||
|
||
Nguồn: `src/Backend/SolutionErp.Application/ContractSigningPlans/ContractSigningPlanFeatures.cs`
|
||
|
||
| Cái | Bằng chứng | Ghi chú |
|
||
|---|---|---|
|
||
| `ContractSigningPlanDetailDto` | `:119-147` | field CUỐI = `List<ContractSigningPlanWorkflowStepDto> WorkflowSteps` `:147` |
|
||
| `ContractSigningPlanWorkflowStepDto(Id, Order, Name, DepartmentId, Levels)` | `:112-117` | KHÔNG có `DepartmentName`, KHÔNG có `Status` |
|
||
| `ContractSigningPlanWorkflowLevelDto(Id, Order, Name, ApproverUserId, ApproverFullName)` | `:105-110` | KHÔNG có `Status`, KHÔNG có `allowApproverFinalize` (W1 rào type-10) |
|
||
| `ContractSigningPlanLevelOpinionDto` | `:93-103` | có `ApproverUserId` (`:99`) — FE types W2 **THIẾU** field này ⇒ bổ sung |
|
||
| con-trỏ đôi | `:136-137` `CurrentWorkflowStepIndex` + `CurrentApprovalLevelOrder` | |
|
||
| Tree build | `:537-566` | Steps sort `Order`, Levels sort `Order`, `ApproverFullName` join Users `:549-552` |
|
||
|
||
🔴 **KHÁC PE CĂN BẢN — đây là điểm dễ đứt nhất của wave này:** PE trả `approvalFlow` đã có sẵn
|
||
`status: 'Done'|'Current'|'Pending'` per Bước/Cấp (BE precompute). **KHKK trả CÂY THÔ, KHÔNG status**
|
||
⇒ FE **phải tự suy** trạng thái từ con-trỏ đôi. Không có field `status` nào để đọc.
|
||
|
||
🔴 **Ngữ nghĩa con-trỏ (BE tự khai, `:224-226`):** `CurrentWorkflowStepIndex` là **INDEX 0-based** vào
|
||
list Steps đã sort theo Order — **KHÔNG phải Order**. `CurrentApprovalLevelOrder` là **GIÁ TRỊ** `Level.Order`.
|
||
Luật so khớp OR-of-N canonical BE `:259-260`:
|
||
`steps[idx].Levels.Any(l => l.Order == CurrentApprovalLevelOrder && l.ApproverUserId == userId)`
|
||
⇒ FE mirror ĐÚNG vị ngữ này (nhiều Level **cùng Order** = OR-of-N; lấy `.some()`, KHÔNG `.find()` 1 người).
|
||
|
||
Rào XEM BE `:184-195` (`EnsureCanViewAsync`): Admin ∨ drafter ∨ (phase ≠ DangSoanThao ∧ approver-của-workflow-đã-pin).
|
||
⇒ phiếu **Nháp** approver KHÔNG đọc được; **TraLai** thì đọc được.
|
||
|
||
Endpoint transitions: **CHƯA có trong controller** (`ContractSigningPlansController.cs` grep `HttpPost` → chỉ
|
||
`/`, `/{id}/dossier-items`, `/{id}/attachments`). Đúng như đề bài: đợt-1 FE đi trước BE.
|
||
|
||
## MỤC 2 — Khuôn PE panel: cái GIỮ / cái BỎ
|
||
|
||
Nguồn `fe-user/src/components/pe/PeWorkflowPanel.tsx` (1063 dòng).
|
||
|
||
GIỮ (mirror): sơ đồ Bước→Cấp ✓/●/○ `:381-478` · banner đến-lượt `:489-508` (`actorInV2Level`/`blockedByV2Level`
|
||
`:109-114`) · nút 3 màu emerald/amber/red `:546-562` · Dialog + ô ý kiến `:869-870` · `useAuth()` lấy actor `:66-67`
|
||
· `qc.invalidateQueries` + `toast.error(getErrorMessage(e))` `:288`.
|
||
|
||
BỎ (đơn-giản-hoá theo lệnh): price-picker `:794-820` · budget/pendingPriors `:170-180` · file-đính-kèm-khi-duyệt
|
||
`:823-868` · 4 return-mode radio `:635-713` (W3 = TraLai toàn phần, spec §②-3(c)) · `skipToFinal`/`finalizeByCcm`/
|
||
`applyLevelFinalize` `:57-63` (spec §②-3(b): **CẤM** port 2 đường kết thúc sớm) · xóa-mềm-bởi-approver `:295-312`.
|