From 6aa4dcb525eb1af8c1de761f79e709e1f03d5f30 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Thu, 18 Jun 2026 16:21:31 +0700 Subject: [PATCH] [CLAUDE] FE-User: PE khoa nut Xac nhan khi phai chon gia ma chua co gia nao (Mig 54 fix) Empty-candidates edge: neu duyet cap cuoi ma priceCandidates rong, nut Xac nhan van mo -> bam -> BE Conflict kho hieu. Khoa nut + giu message ro rang. Phong-thu thuan (double-check xac nhan edge UNREACHABLE qua submit-guard winnerQuoteTotal>0 :194) + sua mau thuan UX cu. fe-user/fe-admin SHA-identical (4d6c89d9). 2 workflow review (Round1 schema 1/4 + Round2 free-text 2/3 PASS). Co-Authored-By: Claude Opus 4.8 --- fe-admin/src/components/pe/PeWorkflowPanel.tsx | 5 ++++- fe-user/src/components/pe/PeWorkflowPanel.tsx | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/fe-admin/src/components/pe/PeWorkflowPanel.tsx b/fe-admin/src/components/pe/PeWorkflowPanel.tsx index df2975a..edb1a3f 100644 --- a/fe-admin/src/components/pe/PeWorkflowPanel.tsx +++ b/fe-admin/src/components/pe/PeWorkflowPanel.tsx @@ -358,7 +358,10 @@ export function PeWorkflowPanel({ // [Mig 54] ① bộ chọn giá chốt khi duyệt CUỐI hoặc CCM tích done — bắt buộc chọn. const isApproveAction = !isCancel && !isSendBack const shouldPickPrice = isApproveAction && (currentIsFinalApprover || finalizeByCcm) - const priceMissing = shouldPickPrice && priceCandidates.length > 0 && !approvedPriceSource + // [Mig 54 fix] Khoá "Xác nhận" khi PHẢI chọn giá mà: chưa có giá nào (candidates + // rỗng — buộc nhập PRO/CCM hoặc chọn NCC thắng thầu trước) HOẶC chưa chọn giá. Tránh + // người duyệt bấm rồi nhận lỗi BE "Chọn 1 giá chốt" khó hiểu (empty-candidates edge). + const priceMissing = shouldPickPrice && (priceCandidates.length === 0 || !approvedPriceSource) return ( 0 && !approvedPriceSource + // [Mig 54 fix] Khoá "Xác nhận" khi PHẢI chọn giá mà: chưa có giá nào (candidates + // rỗng — buộc nhập PRO/CCM hoặc chọn NCC thắng thầu trước) HOẶC chưa chọn giá. Tránh + // người duyệt bấm rồi nhận lỗi BE "Chọn 1 giá chốt" khó hiểu (empty-candidates edge). + const priceMissing = shouldPickPrice && (priceCandidates.length === 0 || !approvedPriceSource) return (