Dong ca UAT goc (Tra Sol): "lo bam sai cai goi thau, quay lai khong duoc, phai
xoa thi no moi ko co luy ke len". Dot 1 (b1bae77) da dung NEN (co F6 + lenh sua
quy trinh tai cho); dot 2 la phan nguoi dung cham vao.
- App: PeSoftDeleteFeatures.cs MOI
- DELETE /api/purchase-evaluations/{id}/by-approver — 3 rao: phase ChoDuyet
^ dung luot actor ^ matchingLevel.AllowApproverDelete (PER-NGUOI, khong g.Any)
- GET /api/purchase-evaluations/deleted — IgnoreQueryFilters() KEM .Where(IsDeleted)
(IgnoreQueryFilters GO filter chu khong DAO — thieu Where la liet ke ca phieu song)
+ tai lap khoi IDOR cua list hien hanh
- ghi vet ChangelogAction.Delete + ly do
- Api: 2 endpoint moi. 🔴 by-approver CO Y KHONG co [Authorize(Policy)] — do tren DB:
moi vai dang lam nguoi duyet (Procurement/CostControl...) deu CanDelete=0 va khong
seeder nao nang co do => gan policy la 403 voi dung nguoi can dung, ma FE gate cung
quyen nen khong thay nut khong thay loi (gotcha #44). Quyen = 3 rao handler; co F6
la admin tick dich danh tung nguoi => chat hon quyen theo vai.
- Dto: ApprovalWorkflowOptionsDto + AllowApproverDelete. Thieu field nay thi FE gate
luon sai => nut KHONG BAO GIO hien, ma BE lan FE deu build sach (reviewer bat).
- Domain/Infra: 2 menu key Pe_{code}_Approved / _Deleted (KHONG vao MenuKeys.All =>
giu 54/216) + seed tree + labelBackfill "Duyet" -> "Dang duyet" + 2 danh sach permission
- FE x2 app: nut Xoa trong PeWorkflowPanel (md5 mirror khop) + dialog ly do + Layout
regex/route cho 2 muc moi + man "Da xoa" chi-xem
- Tests: +11 (562 tong, 0 fail). T27 khoa CA LOP loi entity-co-co-ma-DTO-khong-co
(fault-inject xac nhan: go field ra => T27 do ngay)
Review: 12 FLAG, chot chan H1 (DTO thieu field) da va. Deploy KHONG co migration
nhung CO seed menu => phai restart API.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nen cho tinh nang "xoa phieu PE o man duyet" (UAT: phieu bam sai goi thau dang
an luy ke). Dot 1 lam NEN, dot 2 moi lam nut xoa.
Vi sao phai lam nen truoc: phieu dang chay pin ApprovalWorkflowId va doc workflow
SONG theo Id do. Moi POST tao workflow moi = Id MOI, nen tick co tren ban moi
KHONG BAO GIO toi duoc phieu dang treo. Phai co lenh sua-tai-cho giu nguyen Id.
- Domain: ApprovalWorkflowLevel + AllowApproverDelete (F6, per-NGUOI) + Mig
20260727033522_AddPeAllowApproverDelete (AddColumn bit default false, no new table)
- Application: UpdateAwDefinitionCommand + Validator + Handler
- 2 phep thu: (T1) khung khong doi - Order tung row bat bien
(T2) luat choi khong doi - cam CeoApprovalThreshold, AllowApproverFinalize,
Code, ApplicableType => 409 bao tao ban moi
- diff theo Level.Id (CAM delete-then-insert: no FK Restrict + mo coi LevelOpinion)
- guard 2 tang chu ky: tang 1 chu ky tren ho so CON SONG; tang 2 chu ky CON LUU
(cha xoa mem hoac opinion xoa mem) - ca hai deu CHAN, khong xoa cung
- purge chi khi ho so cha KHONG CON ROW; boc transaction (ExecuteDelete tu commit)
- KHONG tang Version, KHONG dung IsActive, KHONG doi Id
- Api: PUT /api/approval-workflows-v2/{id} + [Authorize(Policy="Workflows.Create")]
- Infra: message 403 in TEN NGUOI thay GUID tran
- FE: Designer tach "Sua tai cho" (PUT) vs "Tao phien ban moi" (POST) + o tick F6
- Tests: +21 (551 tong, 0 fail) - gom F12 chung minh phieu dang chay nhan thay doi ngay
Review: 14 FLAG, 3 HIGH da va (ExecuteDelete ngoai transaction / purge xoa cung
chu ky phieu xoa mem / endpoint khong co day FE goi toi).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Phiếu mà quy trình duyệt có cấp bật AllowApproverFinalize (Mig 58) sẽ kết thúc tại cấp đó,
KHÔNG trình CEO. Hiển thị note cho MỌI NGƯỜI NẮM ở 3 surface (anh Kiệt FDC). KHÔNG migration
(cột AllowApproverFinalize đã có Mig 58, prod ở Mig 59).
BE (3 file, computed DTO):
- PurchaseEvaluationDtos.cs: +bool EndsBeforeCeo +string? FinalizeStepName +string? FinalizeLevelName
trên DetailBundle + ListItem; flow-level +bool AllowApproverFinalize.
- PurchaseEvaluationFeatures.cs: detail compute first-reachable (Step.Order↑→Level.Order↑, dept-name
in-memory); list + inbox projection qua 3 subquery EF-safe (lv.Step!.Name). V1 (workflowId==null) → false.
- CreateContractFromEvaluationFeatures.cs: ListApproved projection cùng DTO → +3 subquery y hệt.
FE 2-app (fe-user + fe-admin SHA-mirror component):
- PeFinalizeChip.tsx (MỚI, chip tím) ở 3 danh sách: PeListPanel + PurchaseEvaluationsListPage (cây) + InboxPage.
- PeWorkflowPanel.tsx: note callout trong phiếu, branch DaDuyet (past-tense) / đang-chạy; copy boundary-aware
"...là KẾT THÚC, không trình CEO. Các cấp trước vẫn duyệt như thường." (tránh cấp giữa hiểu nhầm).
- UserDashboardPage.tsx (chỉ fe-user): dải "Phiếu Duyệt NCC gần đây" + chip (admin dashboard để nguyên).
- types: PeListItem/PeDetailBundle/PeApprovalFlowLevel +field.
Tests: +PeFinalizeProjectionTests (EF-translate smoke 3 subquery + first-reachable + V1-false). Full suite 421→422.
em-main self-gate sau workflow (impl-frontend return rỗng #53 → mirror fe-admin + verify 5 site recover-disk).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CCM (Lưu Trần / anh Kiệt FDC) — làm 3/4 mục (mục 3 "CCM sửa ngân sách" để riêng):
1. Multi-winner: chọn NHIỀU NTP/NCC/ĐVDV cùng trúng → winnerQuoteTotal = SUM
ThanhTien MỌI đơn vị isWinner (vd 3 ông 37.8+9+10 = 56.8tr). Cột mới
PurchaseEvaluationSupplier.IsWinner (Mig 58, backfill từ SelectedSupplierId).
SelectWinner → multi-toggle SupplierIds[]. FE: bảng so sánh tick nhiều ô +
dòng "Tổng chi phí đã chọn"; mọi guard/checklist/computeGiaChaoThau/tạo-HĐ
đổi sang isWinner (selectedSupplierId = null khi liên-danh ≥2).
2. Ngân sách = 0 hợp lệ: nới submit-guard + 3 validator (chỉ chặn khi NULL,
số 0 cố ý đi qua; fallback ProInitial chỉ khi null). Mirror BE + FE.
3. Cấp KẾT THÚC quy trình: ApprovalWorkflowLevel.AllowApproverFinalize (Mig 58)
— admin bật per-cấp trong Workflow Designer; duyệt tới cấp đó TỰ DaDuyet,
bỏ qua CEO (AUTO theo cấu hình quy trình, không ô-tích runtime — anh Kiệt
chốt). FE: banner cảnh báo + bắt chọn giá chốt.
Mig 58 AddPeMultiWinnerAndLevelFinalize (2 AddColumn bool + backfill IsWinner,
additive/reversible). Test 377→395 (+PeMultiWinnerTests +PeApproverFinalizeTests
+budget=0; auto-model gọn bớt 2 test bypass/opt-out). FE 2 app SHA-mirror.
Build sạch BE + 2 FE local.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
anh Kiet/Tra Sol UAT: list state dang canh giua (max-w-5xl) trong 2 ben -> tra ve bo cuc goc 8e68ed1: grid lg:[400px_1fr_360px], list bam trai + 2 placeholder panel lap day man hinh, KHONG canh giua. Giu nguyen focus overlay S78 (bam phieu -> overlay truot tu phai che het menu+list; Duyet/Thu gon/Esc -> dong ve danh sach). <lg single-col compact. 2 app SHA256-identical. FE-only, 0 BE, 0 migration. Build PASS x2. Recover tu agent process-death (edit hoan chinh tren disk, em-main build-verify + mirror fe-admin).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Surface co gap GAP tren MOI danh sach phieu de CEO/nguoi duyet thay urgency ngay tren danh sach khong can mo phieu (anh Kiet FDC). Cay danh sach: emoji -> pill labeled. Khung 'Danh sach phieu' cho duyet (Workspace + picker) + inbox 'phieu cho toi duyet': them pill (truoc day thieu). NEW PeUrgentChips.tsx single-source-of-truth (style khop badge detail S69) x2 app. FE-only, 0 BE, 0 migration — DTO da co IsUrgentByPro/Ccm tu S69 Mig 53. Build PASS x2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
S76 (anh Kiet FDC + chi Tra Sol) — form ngan sach + hien thi quyen nhap NS trong flow:
- Part 1: form ngan sach -> MA TRAN 3 cot, moi phong nhap+dieu chinh cot minh
(PRO canEditPro / CCM canEditCcm / Du an FE hien-thi-only). Mig 56
+ProInitialAmount/ProAdjustmentAmount (additive-nullable + data-migrate
ProEstimate->ProInitial). full moi cot = ban hanh + hieu chinh.
- Part 2: Workflow Designer (fe-admin) +badge "NS PRO/CCM" canh approver
(suy tu role Admin|Procurement / Admin|CostControl, hien-thi-only no-authz).
- Part 3: flow quy trinh fe-user/fe-admin (Duyet NCC) +badge tuong tu.
- Fix race mat-du-lieu Part 1 (useIsFetching khoa Luu khi refetch — dong
cua-so stale-echo, reviewer Part2/3 bat).
- Test 339->344 (+5). 2 workflow review (Part 1 PASS + Part 2/3 PASS).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Yêu cầu anh Kiệt FDC (sau họp sếp). Mig 53 AddPeUrgentAndCeoApprovalThreshold — 3 AddColumn, no new table (Mig 52→53). Rollout an toàn: cột nullable, ngưỡng null = giữ luồng duyệt cũ 100% cho tới khi admin set.
B — CCM duyệt-final theo NGƯỠNG GIÁ TRỊ ("gói CEO phân quyền theo giá trị"):
- ApprovalWorkflow += CeoApprovalThreshold (decimal?, admin nhập trong Workflow Designer).
- ApproveV2Async: actor role CostControl (CCM) + winnerQuoteTotal (tổng giá NCC được chọn) < ngưỡng → DaDuyet luôn (bỏ CEO); ≥ ngưỡng → đẩy lên CEO như cũ. Ngưỡng null = luồng tuyến tính cũ. Q4 chốt nhận diện theo ROLE người duyệt.
- reviewer PASS 0 blocker: cascade-safe (Off/role không lan), tested load-bearing (CCM dưới ngưỡng → DaDuyet skip CEO).
A — cờ gấp per-vai (visibility-only, Q3 KHÔNG đổi luồng):
- PE += IsUrgentByPro (PRO đỏ) / IsUrgentByCcm (CCM xanh).
- Endpoint PUT /purchase-evaluations/{id}/urgent role-gated (Procurement→ByPro, CostControl→ByCcm, Admin→cả 2, khác→Forbidden) + notify CEO (Director) khi MỚI bật (best-effort).
FE ×2 app: Workflow Designer ô "Ngưỡng giá trị gói CEO" (fe-admin) + PE detail nút bật/tắt cờ gấp đỏ/xanh theo role + badge GẤP + hint "giá trị gói vs ngưỡng → CCM duyệt-final/cần CEO" + PE list badge gấp.
DTO: PE detail += isUrgentByPro/Ccm + winnerQuoteTotal + ceoApprovalThreshold; list += isUrgentByPro/Ccm; workflow V2 += ceoApprovalThreshold.
+14 test (292→306): PeCcmThresholdFinalizeTests 5 (B routing) + PeUrgentToggleAuthzTests 9 (A authz). Build slnx 0/0 · npm build ×2 0 err · dotnet test 306 PASS.
C (sau duyệt xong chuyển phiếu đến dự án) — chờ anh Kiệt làm chi tiết form, CHƯA làm.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Anh chốt self-service: admin gán phòng cha để dựng sơ đồ org cho trang Hồ sơ Nhân sự.
DepartmentsPage: +Select "Phòng cha (Thuộc khối/phòng)" (option "— Không có (cấp gốc) —"
= null) + query departments-all (pageSize 200) + cột "Thuộc" hiện tên phòng cha + gửi
parentId trong Create/Update + pre-select khi sửa + loại-trừ-chính-nó khỏi dropdown
(cycle sâu hơn = BE 409 ConflictException -> toast). +parentId vào type Department.
Build PASS fe-admin (0 TS error). Mirror fe-user defer (quản lý phòng ban = admin).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Mig 50 ReplaceBudgetModuleWithPeWorkItemBudgets: bang moi PeWorkItemBudgets (1 record/cap Du an x Hang muc, UNIQUE filtered [IsDeleted]=0) + drop 5 bang Budget cu + PE/Contracts drop BudgetId + backfill BudgetManualAmount->BudgetPeriodAmount TRUOC DropColumn (phieu UAT giu so) + DELETE menu/permission Bg_* IN-list children-first
- BE: PUT {id}/budget/pro (role Procurement) + {id}/budget/ccm (role CostControl, Adjustment cho phep AM) fail-closed Forbidden-truoc-side-effect + EnsureTrackedAsync race-safe (catch unique -> re-fetch winner, loi khac rethrow) + auto-create record khi tao phieu + budgetSummary DTO (luy ke trinh-truoc/chon-thau-truoc/de-xuat-ky-nay + full fallback du-tru-PRO + canEdit flags) + submit-guard (3) doi predicate BudgetPeriodAmount -> "chua nhap Ngan sach ky nay" + PATCH budget-adjust absolute-set 2 field moi + Contract GIU BudgetManual* (HD nhap tay khong doi) + ke thua HD map BudgetPeriodAmount
- FE x2 app SHA256 identical: bang "TONG HOP NGAN SACH TRINH KY" block A (full dam + ban hanh + V0 hieu chinh + du tru PRO + ghi chu, editable theo canEditPro/canEditCcm) + block B 9 dong cong thuc Excel (5=1+3, 6=2+4, 7=full-5, 8 tu nhap default 7, 9=4+8) + to mau vuot ngan sach #C00000 / am do / red-soft row8>row7 + "Chua chon" khi count=0 + banner phieu chua gan Hang muc + o "Ngan sach ky nay" o create/header + XOA pages/components/types budgets + routes + menuKeys + Layout staticMap 4-place
- Tests: +22 PeWorkItemBudgetTests (auto-create x3, ensure/race x2, authz matrix PRO x5 + CCM x3, budgetSummary aggregates x5, adjust x4) - 14 BudgetPolicyTests xoa theo module - 1 test via-BudgetId -> 263 PASS (45 Domain + 218 Infra, 0 fail)
- database-agent advise adopted: khong FK vat ly PE/Contracts->Budgets (DropColumn khong can DropForeignKey) + DropIndex truoc DropColumn (SQL 5074) + IN-list thay LIKE Bg_% (underscore wildcard + miss root) + khong Serializable wrap (nested-tx conflict codegen)
- Reviewer PASS-with-minor 0 blocker (verdict-first survived); 2 minor da sua truoc commit (comment adjustMut absolute-set + dead key budgetId); note: F4 approver-edit-budget UI entry tam drafter-only, BE van cho approver scope - cho UAT anh Kiet
- Scaffold-bug caught: EF tu sinh RenameColumn BudgetManualAmount->ExpectedRemainingAmount (SAI semantics) -> thay bang Add+UPDATE+Drop
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Doi tu "Du an (Nam)" gop 1 node -> Nam la tang ngoai cung (DESC, bg-slate-50),
trong Nam chua Du an (A-Z vi), trong Du an chua Hang muc cong viec, roi phieu.
- yearGroups useMemo thay projectGroups + expand-state localStorage key v3.
- Build x2 PASS, SHA256 mirror identical 95D524EE.
- Tree Panel 1: moi cap (Du an, Nam-tao-phieu) = 1 folder label "Ten du an (Nam)",
level 2 = Hang muc cong viec (WorkItemId Mig 49, phieu cu null -> "(Chua gan hang muc)"),
bo tang NCC khoi tree (van hien o card/detail). Expand-state localStorage key v2.
- scripts/s59-wipe-testing-data.sql DA CHAY prod (anh chot AskUserQuestion): xoa 10 PE
+ 7 HD [DEMO] + 64 notif + 1 workflow V2 cu inactive; reset PeSeq/CtSeq -> ma moi tu 001;
GIU master 70/86/22 + users 55 + templates 9 + 7 workflow ghim. Uploads orphan da don.
Double-check chất lượng P11-A ở Max (agents trước chạy High + truncate 3×) →
phát hiện 2 bug THẬT trong workflow-picker FE của WorkflowAppDetailPage (core
approve/reject/return ĐÚNG, chỉ sub-flow chọn quy trình hỏng):
Bug #1 (HIGH) — pinWorkflow PUT /{id} chỉ gửi {approvalWorkflowId} → UpdateDraft
validator (Reason NotEmpty, NumDays>0...) fail → 400. Nút "Lưu quy trình" vỡ.
Bug #2 (HIGH) — fetch workflow expect flat array nhưng endpoint trả
AwAdminOverviewDto {types:[...]} → picker rỗng/crash. FE copy nhầm pattern hỏng
của ProposalCreatePage thay vì PE/Contract proven.
Fix:
- BE: thêm endpoint chuyên dụng PUT /{id}/workflow + Set{Module}WorkflowCommand/Handler
cho 4 module — chỉ set ApprovalWorkflowId trên draft Nhap/TraLai (verify ApplicableType
per module), KHÔNG validate field khác. Single-responsibility, bulletproof.
- FE: sửa fetch mirror PE/Contract (data.types.find(t=>t.applicableType===X)?.history
.filter(isUserSelectable)) + pin gọi endpoint mới. fe-admin+fe-user SHA256 identical.
- Test: +3 SetWorkflow (happy no-status-change / wrong ApplicableType Conflict / submitted
guard) → 141→144 PASS.
Verify: BE build 0 error · 144 test PASS · FE build ×2 · SHA256 identical.
Bonus phát hiện: ProposalCreatePage (S37) có bug #2 có sẵn (latent, chưa exercise UAT)
→ flag spawn task riêng, KHÔNG fix trong commit này.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>