# sub-implementer-backend-1 — ĐỢT 1 (hạng mục F + schema F6) > run `2026-07-27-S155-pe-delete-approver` · vai `implementer-backend` · spec canonical = `spec-pe-delete-approver.md` PHẦN II + checklist mục 1-2 > Ghi TRONG LÚC LÀM (bài học #53). Trạng thái cập nhật dần từ trên xuống. ## Phạm vi nhận (theo TASK) | # | Mục | Trạng thái | |---|---|---| | 1 | `ApprovalWorkflowLevel += AllowApproverDelete` (F6) | ⏳ | | 2 | Migration `AddPeAllowApproverDelete` (3-file rule) | ⏳ | | 3 | F-10 vá comment sai `ApprovalWorkflow.cs:81-82` | ⏳ | | 4 | F-1..F-4 + F-1a/b/c `UpdateAwDefinitionCommand` | ⏳ | | 5 | F-5/F-5a hạng NỬA (bớt người / đổi ApproverUserId) | ⏳ | | 6 | F-6 message 403 in GUID → tên người | ⏳ | KHÔNG làm: nút xóa FE · menu · màn "Đã xóa" · F-9 usage-check DeleteAwDefinition · F-11 (FE) · F-7/F-8 (FE). --- ## PHẦN 0 — Khảo sát nền (đọc trước khi viết dòng nào) Số đo lấy từ đĩa, KHÔNG lấy từ memoryPack: | Sự kiện | Bằng chứng | |---|---| | 8 cờ Allow* per-Level hiện có (F1×4, F3, F4, F2, F5) | `src/Backend/SolutionErp.Domain/ApprovalWorkflowsV2/ApprovalWorkflow.cs:104-142` | | EF `HasDefaultValue` cho từng cờ | `.../Configurations/ApprovalWorkflowConfiguration.cs:80-103` | | KHÔNG tồn tại lệnh Update — admin V2 chỉ 4 việc | `ApprovalWorkflowV2AdminFeatures.cs` (Get :101 · Create :238 · SetUserSelectable :384 · Delete :404) | | POST tự tăng Version + hạ IsActive mọi bản cùng type | `:325-328` · `:331-334` · new `ApprovalWorkflow{}` `:336` | | 3 verb ghi controller đều `[Authorize(Policy="Workflows.Create")]`; class chỉ `[Authorize]` trần `:18` | `ApprovalWorkflowsV2Controller.cs:29 / :40 / :48` | | Con trỏ LAI: StepIndex = INDEX list sort · LevelOrder = so GIÁ TRỊ | `PurchaseEvaluationWorkflowService.cs:686` · `:689-695` | | 403 in GUID trần | `PurchaseEvaluationWorkflowService.cs:701-707` (`string.Join(", ", allowedUserIds)`) | **🔴 Phát hiện MỚI (chưa có trong spec/memoryPack) — quyết định cài đặt F-5/F-5a phụ thuộc nó:** 1. **7 bảng LevelOpinion** FK `ApprovalWorkflowLevelId` chứ không phải 1 (PE + Contract + Proposal + Leave + Ot + Travel + VehicleBooking) — grep `ApprovalWorkflowLevelId` trong `Domain/` ra 7 entity. Chặn-lịch-sự chỉ soi PE ⇒ **vẫn nổ FK 547** khi workflow thuộc module Văn phòng số (khớp §F.3 blast-radius ≥6 module). 2. **CẢ 7 LevelOpinion đều là `AuditableEntity`** (không phải BaseEntity) — vd `PurchaseEvaluationLevelOpinion.cs`, `ProposalLevelOpinion.cs:16`. Hệ quả: `Remove()` một opinion **KHÔNG xoá cứng** — `AuditingInterceptor.cs` đổi `Deleted→Modified` ⇒ row Ở LẠI ⇒ **FK vẫn Restrict**. Muốn dọn rác phải `ExecuteDeleteAsync()` (bypass change-tracker). 3. **Chỉ PE + Contract có `HasQueryFilter(!IsDeleted)`**; Proposal/Leave/Ot/Travel/VehicleBooking **KHÔNG** có (grep `HasQueryFilter` toàn `Configurations/` = 16 hit, 0 hit cho 5 bảng Office). ⇒ F-5a "loại trừ opinion của phiếu đã IsDeleted" **phải viết `!p.IsDeleted` TƯỜNG MINH**, không được dựa global filter (dựa filter ⇒ đúng cho PE, SAI cho 5 module Office). 4. `Microsoft.EntityFrameworkCore.Relational 10.0.6` đã có trong `SolutionErp.Application.csproj:13` ⇒ `ExecuteDeleteAsync` dùng được ở tầng Application. ---