[CLAUDE] PurchaseEvaluation: CCM 3-fix — multi-winner sum + budget=0 hợp lệ + cấp KẾT THÚC quy trình (Mig 58, anh Kiệt FDC)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m10s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m10s
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>
This commit is contained in:
@ -51,6 +51,7 @@ type LevelDto = {
|
||||
allowApproverEditDetails: boolean
|
||||
allowApproverEditBudget: boolean
|
||||
allowApproverSkipToFinal: boolean
|
||||
allowApproverFinalize: boolean // [Mig 58 CCM item 4] slot Duyệt = KẾT THÚC (không trình CEO)
|
||||
// [S76] Hiển thị-only: approver được nhập/điều chỉnh ngân sách cột nào (suy từ role).
|
||||
canEditProBudget: boolean
|
||||
canEditCcmBudget: boolean
|
||||
@ -106,6 +107,7 @@ type EditLevelEntry = {
|
||||
allowApproverEditDetails: boolean
|
||||
allowApproverEditBudget: boolean
|
||||
allowApproverSkipToFinal: boolean
|
||||
allowApproverFinalize: boolean
|
||||
}
|
||||
type EditStep = { name: string; departmentId: string | null; levelEntries: EditLevelEntry[] }
|
||||
|
||||
@ -154,6 +156,7 @@ function copyFromDefinition(d: DefinitionDto): EditStep[] {
|
||||
allowApproverEditDetails: l.allowApproverEditDetails ?? false,
|
||||
allowApproverEditBudget: l.allowApproverEditBudget ?? false,
|
||||
allowApproverSkipToFinal: l.allowApproverSkipToFinal ?? false,
|
||||
allowApproverFinalize: l.allowApproverFinalize ?? false,
|
||||
})),
|
||||
}))
|
||||
}
|
||||
@ -171,6 +174,7 @@ function makeDefaultLevelEntry(order: LevelOrder, approverUserId: string): EditL
|
||||
allowApproverEditDetails: false,
|
||||
allowApproverEditBudget: false,
|
||||
allowApproverSkipToFinal: false,
|
||||
allowApproverFinalize: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,6 +602,7 @@ function Designer({
|
||||
allowApproverEditDetails: e.allowApproverEditDetails,
|
||||
allowApproverEditBudget: e.allowApproverEditBudget,
|
||||
allowApproverSkipToFinal: e.allowApproverSkipToFinal,
|
||||
allowApproverFinalize: e.allowApproverFinalize,
|
||||
})),
|
||||
})),
|
||||
})
|
||||
@ -989,6 +994,17 @@ function Designer({
|
||||
/>
|
||||
<span>Cho phép duyệt thẳng Cấp cuối khi đang duyệt</span>
|
||||
</label>
|
||||
{/* [Mig 58 CCM item 4 — anh Kiệt FDC] Duyệt là KẾT THÚC: NV slot
|
||||
này duyệt xong → DaDuyet luôn, KHÔNG trình tiếp CEO (vd Cấp anh Chương). */}
|
||||
<label className="col-span-2 flex items-center gap-1 text-[11px] text-emerald-700">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="h-3 w-3"
|
||||
checked={entry.allowApproverFinalize}
|
||||
onChange={e => updateField('allowApproverFinalize', e.target.checked)}
|
||||
/>
|
||||
<span>Duyệt là KẾT THÚC quy trình (không trình tiếp CEO)</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user