Files
solution-erp/.claude/workflows/runs/2026-07-27-S155-pe-delete-approver/sub-implementer-frontend-6.md
2026-07-27 12:24:07 +07:00

3.7 KiB
Raw Blame History

sub-implementer-frontend-6 — WAVE 5 · [F-7] nối dây FE cho PUT /approval-workflows-v2/{id} (vá F3 HIGH)

run 2026-07-27-S155-pe-delete-approver · WAVE 5 (vá 3 FLAG HIGH trước deploy) · vai implementer-frontend Ghi TRONG LÚC LÀM, flush từng phần (#53 đã ăn 5/5 sub run này). File luôn hợp lệ giữa chừng.

0. F3 nói gì (đọc nguyên văn reviewer-diff-dot1.md:84-113, không tóm tắt lại theo trí nhớ)

  • Đo được, không phải cảm giác: grep -rn "api.put" fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx0 hit. 3 đường ghi duy nhất của Designer: api.delete :286 · api.patch …/user-selectable :297 · api.post('/approval-workflows-v2') :589.
  • Hệ quả: ~600 dòng BE mới (UpdateAwDefinitionCommand + Validator + Handler + 3 helper) là mã chết với người dùng UAT. Owner tick cờ F6 → Lưu → POST → sinh Id MỚI → phiếu đang treo pin Id CŨ (PurchaseEvaluationWorkflowService.cs:674 w.Id == awId) ⇒ cờ không bao giờ tới phiếu cần cứu.
  • Reviewer cho 3 đường (a)/(b)/(c); owner đã chốt (a) = nối dây FE trong đợt 1.
  • Tiêu chí nghiệm thu reviewer đặt (:113): tick cờ F6 cho 1 NV trên version đang có phiếu treo → lưu bằng đường "Sửa tại chỗ" → GET /api/approval-workflows-v2 trả allowApproverDelete=true trên đúng id, Version KHÔNG tăng.

1. Hợp đồng BE — đọc THẲNG từ mã, không tin MEMORY-PACK

Neo File:line Sự thật
Endpoint ApprovalWorkflowsV2Controller.cs:45-51 [HttpPut("{id:guid}")] [Authorize(Policy="Workflows.Create")], mediator.Send(cmd with { Id = id })204 NoContent
Command ApprovalWorkflowV2AdminFeatures.cs:449-464 { Id, Name, Description, Steps, Reason?=null, Code?=null, ApplicableType?=null, CeoApprovalThreshold?=null }
Step input :442-447 Id BẮT BUỘC (Guid, không nullable) · Order · Name · DepartmentId · Levels
Level input :424-440 Id Guid? (null = dòng MỚI) · Order · Name · ApproverUserId · 7 cờ an-toàn (4×Return, EditDetails, EditBudget, AllowApproverDelete) · 2 cờ echo bool? (SkipToFinal, Finalize)

3 bẫy payload (task nêu) — đối chiếu mã, cả 3 đều THẬT:

  1. CeoApprovalThreshold ECHO NGHIÊM:529 if (request.CeoApprovalThreshold != def.CeoApprovalThreshold) throw ConflictException. KHÔNG phải "null = bỏ qua" (khác hẳn Code/ApplicableType:521/:525 dùng is string/is int nên null mới được bỏ qua). ⇒ gửi thiếu ⇒ null != 5_000_000409. Comment BE :459-463 tự khai lý do: null LÀ giá trị có nghĩa (= bỏ ngưỡng).
  2. Chỉ trường hạng AN TOÀN. Cấm (409): ±Bước (:539) · đổi Step.Order (:554) · đổi Level.Order từng dòng (:575) · ±Cấp / bỏ trống Cấp (:618-630) · Code · ApplicableType · CeoApprovalThreshold · F5 AllowApproverFinalize (:580) · F2 AllowApproverSkipToFinal (:583) · bỏ/đổi người đang có chữ ký sống (:658-673). Cho sửa: thêm/bớt người trong Cấp CÓ SẴN · đổi ApproverUserId · 7 cờ quyền-tại-chỗ (gồm F6) · tên (workflow/step/level) · Step.DepartmentId (:705-706, BE không kiểm NV có thuộc Phòng hay không).
  3. Payload liệt kê tay từng field (:605-621 khối POST) — thêm field mà quên dây = silent drop, TS xanh, BE default false, UI vẫn tick. Đúng bẫy đã xảy ra thật ở sub-implementer-frontend-2.md §2.4.