[CLAUDE] FE-User · FE-Admin: PE flow sơ-đồ — badge "Duyệt thay CEO" trên cấp finalize + làm mờ Bước CEO "không trình tới"
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m2s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m2s
Trong khối "Quy trình duyệt" của phiếu (PeWorkflowPanel, sơ đồ Bước→Cấp→NV), cấp được cấu hình AllowApproverFinalize (Mig 58) giờ hiện badge tím "⚑ Duyệt thay CEO" + tooltip; các Bước/Cấp SAU cấp finalize (vd Ban Giám đốc / CEO) làm mờ + nhãn "không trình tới" → người xem phiếu biết NGAY trong sơ đồ rằng quy trình DỪNG ở cấp này (duyệt thay CEO), không lên CEO (anh Kiệt FDC). Dùng field allowApproverFinalize đã expose ở flow-level (S89 #3). first-reachable theo Step.Order→ Level.Order (khớp BE finalize). Bổ sung cho callout note (#3) = chỉ-dẫn trong chính sơ đồ flow. FE-only, 2 app SHA-mirror, build xanh. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -114,6 +114,16 @@ export function PeWorkflowPanel({
|
||||
// (admin bật per-slot ở Designer). Duyệt tới cấp này = TỰ kết thúc (BE auto theo cờ cấp,
|
||||
// KHÔNG cần ô-tích). FE dùng cờ này để: (1) hiện banner cảnh báo + (2) bắt chọn giá chốt.
|
||||
const approverFinalizeEligible = levelOptions?.allowApproverFinalize === true
|
||||
// [S89 anh Kiệt FDC] Cấp "Duyệt thay CEO" (finalize) ĐẦU-TIÊN theo thứ tự duyệt trong flow →
|
||||
// badge cấp đó + làm mờ Bước/Cấp SAU ("không trình tới") để người xem phiếu biết quy trình
|
||||
// DỪNG ở cấp này (duyệt thay CEO), không lên Ban Giám đốc.
|
||||
const finalizeFlowStep = evaluation.approvalFlow?.steps.find(s => s.levels.some(l => l.allowApproverFinalize)) ?? null
|
||||
const finalizeFlowLevelOrder = finalizeFlowStep?.levels.find(l => l.allowApproverFinalize)?.order ?? null
|
||||
const isStepAfterFinalize = (stepOrder: number) => finalizeFlowStep != null && stepOrder > finalizeFlowStep.order
|
||||
const isLevelAfterFinalize = (stepOrder: number, levelOrder: number) =>
|
||||
isStepAfterFinalize(stepOrder)
|
||||
|| (finalizeFlowStep != null && stepOrder === finalizeFlowStep.order
|
||||
&& finalizeFlowLevelOrder != null && levelOrder > finalizeFlowLevelOrder)
|
||||
// Ứng viên giá chốt — chỉ giá nào đã có giá trị (≠ null).
|
||||
const priceCandidates = ([
|
||||
{ source: 'Ncc', label: 'Giá NCC (giá chào thầu)', amount: evaluation.winnerQuoteTotal },
|
||||
@ -288,6 +298,7 @@ export function PeWorkflowPanel({
|
||||
step.status === 'Current' && 'border-brand-300 bg-brand-50/50',
|
||||
step.status === 'Done' && 'border-emerald-200 bg-emerald-50/40',
|
||||
step.status === 'Pending' && 'border-slate-200 bg-white',
|
||||
isStepAfterFinalize(step.order) && 'opacity-50',
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-2 text-xs font-medium">
|
||||
@ -305,13 +316,21 @@ export function PeWorkflowPanel({
|
||||
{step.departmentName}
|
||||
</span>
|
||||
)}
|
||||
{isStepAfterFinalize(step.order) && (
|
||||
<span
|
||||
className="rounded bg-slate-100 px-1.5 py-0.5 text-[10px] font-medium text-slate-400"
|
||||
title="Quy trình đã kết thúc ở cấp 'Duyệt thay CEO' phía trên — bước này không được trình tới"
|
||||
>
|
||||
không trình tới
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{step.levels.length > 0 && (
|
||||
<ul className="mt-1.5 ml-7 space-y-1 border-l-2 border-violet-200 pl-2">
|
||||
{step.levels.map(lv => {
|
||||
const lvIcon = lv.status === 'Done' ? '✓' : lv.status === 'Current' ? '●' : '○'
|
||||
return (
|
||||
<li key={lv.order} className="text-[11px]">
|
||||
<li key={lv.order} className={cn('text-[11px]', isLevelAfterFinalize(step.order, lv.order) && 'opacity-50')}>
|
||||
<div className="flex items-start gap-1.5">
|
||||
<span className={cn(
|
||||
'mt-0.5 inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[9px] font-bold',
|
||||
@ -326,6 +345,15 @@ export function PeWorkflowPanel({
|
||||
{lv.name || `Cấp ${lv.order}`}
|
||||
{lv.status === 'Current' && <span className="ml-1.5 text-[10px] font-normal text-brand-700">đang chờ</span>}
|
||||
{lv.status === 'Done' && <span className="ml-1.5 text-[10px] font-normal text-emerald-600">đã duyệt</span>}
|
||||
{/* [S89 anh Kiệt FDC] Cấp này duyệt = KẾT THÚC quy trình, duyệt THAY CEO. */}
|
||||
{lv.allowApproverFinalize && (
|
||||
<span
|
||||
className="ml-1.5 inline-flex items-center rounded bg-violet-100 px-1.5 py-0.5 text-[9px] font-semibold text-violet-800"
|
||||
title="Cấp này duyệt là KẾT THÚC quy trình — duyệt THAY CEO, không trình lên Ban Giám đốc"
|
||||
>
|
||||
⚑ Duyệt thay CEO
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-x-1 gap-y-0.5 text-slate-500">
|
||||
{lv.approvers.length === 0
|
||||
|
||||
Reference in New Issue
Block a user