3.7 KiB
3.7 KiB
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) · vaiimplementer-frontendGhi 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.tsx→ 0 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:674w.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-v2trảallowApproverDelete=truetrên đúngidcũ,VersionKHÔ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:
CeoApprovalThresholdECHO NGHIÊM —:529if (request.CeoApprovalThreshold != def.CeoApprovalThreshold) throw ConflictException. KHÔNG phải "null = bỏ qua" (khác hẳnCode/ApplicableTypeở:521/:525dùngis string/is intnên null mới được bỏ qua). ⇒ gửi thiếu ⇒null != 5_000_000⇒ 409. Comment BE:459-463tự khai lý do: null LÀ giá trị có nghĩa (= bỏ ngưỡng).- Chỉ trường hạng AN TOÀN. Cấm (409): ±Bước (
:539) · đổiStep.Order(:554) · đổiLevel.Ordertừng dòng (:575) · ±Cấp / bỏ trống Cấp (:618-630) ·Code·ApplicableType·CeoApprovalThreshold· F5AllowApproverFinalize(:580) · F2AllowApproverSkipToFinal(: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 · đổiApproverUserId· 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). - Payload liệt kê tay từng field (
:605-621khối POST) — thêm field mà quên dây = silent drop, TS xanh, BE defaultfalse, UI vẫn tick. Đúng bẫy đã xảy ra thật ởsub-implementer-frontend-2.md §2.4.