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

5.0 KiB
Raw Blame History

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[].allowApproverFinalizeOR-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 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.