Files
solution-erp/.claude/workflows/runs/2026-07-27-S155-pe-delete-approver/sub-d2-fe-2.md
2026-07-27 13:12:40 +07:00

72 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# sub-d2-fe-2 — ĐỢT 2 FRONTEND (nút Xóa màn duyệt + menu + màn "Đã xóa")
- **role:** implementer-frontend · **run:** `2026-07-27-S155-pe-delete-approver` · **đợt:** 2
- **scope:** `fe-admin/src/**` + `fe-user/src/**` ONLY. KHÔNG chạm `src/Backend/**`, KHÔNG chạm `tests/`.
- **ghi TRONG LÚC LÀM** (flush từng phần, tự `wc -c` sau mỗi flush).
---
## 0. Nền đã ĐO (trước khi sửa) — số thật, không phải trí nhớ
| Đo | Kết quả |
|---|---|
| `PeWorkflowPanel.tsx` md5 ×2 app | `02671be6334110028c55fe82f5e70dee` (IDENTICAL, 942 dòng) |
| `PurchaseEvaluationsListPage.tsx` md5 ×2 app | `99e38e167d2f745ea7628174f1d2d6bf` (IDENTICAL — **bonus**, spec không nói) |
| `usePermission.ts` md5 ×2 app | `2b210b753e8fe2704407c787cb82779d` (IDENTICAL) |
| `Layout.tsx` | **DIVERGE** admin `ca59f56c…` / user `cab674f4…` (đúng như thiết kế — 2 app khác staticMap) |
| `lib/menuKeys.ts` | DIVERGE đúng 2 dòng (`Off_AttendanceReport` admin-only) |
| `git status` lúc bắt đầu | sạch (chỉ `.session-counter.json`) ⇒ **lane BE chưa land gì** |
## 1. 🔴 PHỤ THUỘC LIÊN-LANE — FE gọi gì, BE phải có gì
Hợp-đồng `run.md:139-154` chốt 3 route + 2 menu-key. FE bám ĐÚNG. **NHƯNG** hợp-đồng
**không** đặt tên cho 2 thứ FE bắt buộc phải có — khai ở đây để lead verify, KHÔNG tự chế lung tung:
### (D1) Cờ F6 per-NGƯỜI trong bundle chi tiết phiếu
- FE đọc: `evaluation.currentLevelOptions.allowApproverDelete`
- BE PHẢI thêm: `bool AllowApproverDelete` làm **member positional thứ 9** của
`ApprovalWorkflowOptionsDto` (`src/Backend/…/PurchaseEvaluations/Dtos/PurchaseEvaluationDtos.cs:123-131`)
+ gán từ `curLevel.AllowApproverDelete` tại `PurchaseEvaluationFeatures.cs:1088-1096`.
- Vì sao chỗ này mà không phải chỗ khác: `currentLevelOptions` là kênh **DUY NHẤT** per-NGƯỜI —
nó resolve bằng `l.ApproverUserId == currentUser.UserId` (`PurchaseEvaluationFeatures.cs:1083-1085`).
Kênh còn lại `approvalFlow.steps[].levels[].allowApproverFinalize`**OR-of-N per-CẤP**
(`:1182 g.Any(...)`) — dùng nó là vi phạm B2 (`run.md:159` per-ROW).
- **Nếu BE quên:** field về `undefined` → gate `=== true` false → **nút KHÔNG BAO GIỜ HIỆN**,
build 2 bên vẫn xanh. Đúng dạng silent-drop đợt 1. ⇒ lead phải grep xác nhận.
### (D2) Chỗ chứa "lý do xóa" trong request
- Hợp-đồng chỉ ghi `DELETE /api/purchase-evaluations/{id}/by-approver`, **không** nói payload.
- FE gửi **CẢ HAI** đường cho tương thích mọi kiểu binding BE:
`api.delete(url, { params: { reason }, data: { reason } })`
→ BE bind `[FromQuery] string? reason` ✅ · bind `[FromBody] {Reason}` ✅ · không nhận gì ✅ (bị bỏ qua).
- Chủ ý: thà thừa 1 query-param còn hơn mất vết audit vì lệch tên. Ghi rõ để reviewer không tưởng là cẩu thả.
### (D3) DTO list "Đã xóa"
- FE khai `PeDeletedListItem = PeListItem + { deletedAt?, deletedBy?, deletedByName? }`**tất cả optional**,
render phòng thủ (`—` khi thiếu). BE trả thêm/thiếu đều không vỡ. Tên bám `AuditableEntity`
(`src/Backend/SolutionErp.Domain/Common/AuditableEntity.cs:5-7`: `IsDeleted`/`DeletedAt`/`DeletedBy`).
## 2. 🚩 FLAG — mục "vá `WfView` cho fe-admin" TÔI KHÔNG LÀM (tiền-đề của lệnh sai)
Lệnh: *"vá lệch sẵn có: `fe-admin:107` THIẾU `WfView` so với `fe-user:120`"*.
Đo trước khi làm thì tiền-đề **không đứng**:
| Bằng chứng | fe-user | fe-admin |
|---|---|---|
| Page `pages/pe/WorkflowMatrixViewPage.tsx` | CÓ (323 dòng) | **KHÔNG CÓ** |
| Route `/purchase-evaluations/workflow-matrix` | `App.tsx:60` | **KHÔNG CÓ** (`App.tsx:78-81` chỉ 4 route PE) |
| Types `types/approvalWorkflowV2.ts` | CÓ | **KHÔNG CÓ** (admin để type inline trong `ApprovalWorkflowsV2Page.tsx`) |
| Catch-all | — | `App.tsx:107-114` render *"Trang này chưa được build"* |
⇒ Thêm `WfView` vào regex admin **một mình** = đẻ link chết dẫn tới "Trang này chưa được build".
Đó là **regression nhìn thấy được**, tệ hơn trạng-thái-hiện-tại (leaf bị drop im lặng).
Sửa cho đúng cần **3 file mới bên admin** (page + types + route) = ngoài phạm vi đợt 2, và là
lựa-chọn UX (admin nên thấy matrix read-only hay Designer sửa được?) ⇒ **thuộc quyền owner/lead**.
**3 đường cho lead chọn (đều ≤ 1 lượt):**
- **(a)** mirror hẳn: copy `WorkflowMatrixViewPage.tsx` + `types/approvalWorkflowV2.ts` sang admin + route + regex.
- **(b)** rẻ nhất: admin map `Pe_{code}_WfView``/system/approval-workflows-v2/{code}` (Designer đã sống, `Layout.tsx:130-136`).
- **(c)** giữ nguyên: coi lệch này là CỐ Ý (admin có Designer rồi, không cần bản read-only) → ghi 1 dòng comment cho người sau khỏi "vá" lại.
Tôi để nguyên trạng (đường **c** *de facto*) + không chèn comment tránh đụng byte thừa. Chờ lead.