wal: flush 20260727T1300

This commit is contained in:
pqhuy1987
2026-07-27 13:00:00 +07:00
parent 3ec2f116a2
commit ad932b1211
2 changed files with 48 additions and 2 deletions

View File

@ -124,4 +124,48 @@ NHƯNG cùng filter đó làm phiếu xóa **vô hình với MỌI query** ⇒ m
**KHÔNG làm đợt này:** nút xóa FE · menu restructure · màn "Đã xóa" (mục 3-28) — đợt 2.
**Lý do phân đợt:** F.0 chứng minh A-E không chạy nếu thiếu F ⇒ đợt 1 xong là UAT được ngay, biết chắc nền đúng trước khi xây tiếp; blast radius ≥6 module nên tách để truy lỗi dễ.
- [ ] S4-đợt1 — hmw fan-out Opus 5 MAX
- [x] S4-đợt1 — hmw 5 wave + lead-vá · **DEPLOY `b1bae77` · CICD PASS 6/6** (mig ở TOP history prod, cột khớp, smoke 8/8, PUT 401, bundle rotate ×2)
---
# ĐỢT 2 — nút xóa + menu + màn "Đã xóa" (anh lệnh 2026-07-27)
**Phạm vi:** checklist PHẦN I mục **328** (trừ mục 3 đã gộp F-11 đợt 1).
## 🔴 HỢP-ĐỒNG LIÊN-LANE — chốt TRƯỚC khi phóng (bài học đợt 1: 2 nửa build sạch mà không nối được)
Mọi tên dưới đây là **CANONICAL**. BE phải hiện thực ĐÚNG tên này; FE phải gọi ĐÚNG tên này. Lệch một ký tự = silent drop, cả hai build vẫn xanh.
### API
| Việc | Method + Route | Authz |
|---|---|---|
| Xóa phiếu **khi đang duyệt** (đường MỚI) | `DELETE /api/purchase-evaluations/{id}/by-approver` | `[Authorize(Policy = "PurchaseEvaluations.Delete")]` |
| Xóa **nháp** (đường CŨ) | `DELETE /api/purchase-evaluations/{id}`**GIỮ NGUYÊN, KHÔNG gắn policy** | chỉ `[Authorize]` trần |
| List **phiếu đã xóa** | `GET /api/purchase-evaluations/deleted?type=&page=&pageSize=` | `[Authorize(Policy = "PurchaseEvaluations.Read")]` |
### Menu key (factory trong `MenuKeys.cs`, KHÔNG vào `MenuKeys.All`)
- `PurchaseEvaluationApproved(code)``Pe_{code}_Approved` — nhãn **"Đã duyệt"**
- `PurchaseEvaluationDeleted(code)``Pe_{code}_Deleted` — nhãn **"Đã xóa"**
- Đổi nhãn `Pe_{code}_Pending`: `"Duyệt"`**"Đang duyệt"** qua `labelBackfill`
### Route FE (KHÔNG page mới cho 2 mục đầu — tái dùng `PurchaseEvaluationsListPage`)
- Đang duyệt → `/purchase-evaluations?type={N}&pendingMe=1` *(y như cũ, chỉ đổi nhãn menu)*
- Đã duyệt → `/purchase-evaluations?type={N}&phase=7` *(0 route mới, `phase=` đã thông 3 tầng)*
- Đã xóa → `/purchase-evaluations?type={N}&deleted=1` *(view mới, gọi endpoint `/deleted`)*
## Ràng buộc CỨNG mang từ spec + review đợt 1
- **7a**: đường xóa **nháp** GIỮ NGUYÊN không policy — gắn vào là `Drafter` mất quyền xóa nháp của chính mình (đo thật: 11/13 role `CanDelete=0`)
- **7c**: phải cấp `CanDelete` cho role approver đích (vd `Procurement`) — seeder `:2120-2126` **skip-if-exists****không bao giờ chạm `CanDelete`** ⇒ sửa seeder KHÔNG vá được prod, phải tick tay hoặc viết upgrade-path
- **B2**: guard xóa-khi-duyệt = đúng lượt **∧** `matchingLevel.AllowApproverDelete` (**PER-ROW**, dùng khuôn `:859`, KHÔNG dùng `g.Any(...)` `:1182`)
- **8a**: `IgnoreQueryFilters()` **GỠ** filter chứ không ĐẢO ⇒ **BẮT BUỘC** kèm `.Where(x => x.IsDeleted)`
- **8b**: handler mới **mặc định 0 rào** ⇒ phải sao khối IDOR `PurchaseEvaluationFeatures.cs:596-617`
- **D3**: `IgnoreQueryFilters` chỉ ở **đúng 1 handler mới**; CẤM helper dùng chung trả `IQueryable`, CẤM sửa `Configuration:84`, CẤM cờ `includeDeleted` trên query list hiện có
- **12**: thêm key vào **CẢ HAI** danh sách permission seed `:2092-2096` **và** `:2492-2496`
- **11**: đổi nhãn phải qua `labelBackfill` — sửa `tree.Add`**vô tác dụng** trên DB đang chạy
- **14a**: `PeWorkflowPanel` nhận đúng 3 prop `{evaluation, readOnly, onApproved}`**KHÔNG có `onDelete`**; phải THÊM prop + mutation
- **19**: `PeWorkflowPanel.tsx` phải giữ **md5 giống nhau ×2 app** sau khi sửa
- Nhân bản: menu sinh trong `foreach PurchaseEvaluationTypeCodes` ⇒ mỗi mục mới **× số loại phiếu**
- [ ] Đ2-W1 — BE (xóa-by-approver + list deleted + menu seed + changelog)
- [ ] Đ2-W2 — FE (nút xóa + 3 mục menu + màn Đã xóa)
- [ ] Đ2-W3 — test + reviewer → deploy