diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php index 2965054..85ffd2f 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php @@ -229,19 +229,51 @@ class TicketController extends Controller return AbstractController::ResultError('Không thể tính toán khoảng thời gian nghỉ hợp lệ.'); } // Lây thông tin tickets đang ở trạng thái WAITING - $ticketsWaiting = Ticket::where('user_id', $user->id)->where('status', 'WAITING')->get(); + $ticketsWaiting = Ticket::where('user_id', $user->id)->where('status', 'WAITING')->where('type', 'ONLEAVE')->get(); + $dataListPeriodWaiting = []; if ($ticketsWaiting->count() > 0) { foreach ($ticketsWaiting as $ticket) { - $dataListPeriod = array_merge($dataListPeriod, $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period)); + $dataListPeriodWaiting = array_merge($dataListPeriodWaiting, $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period)); } } - // dd($dataListPeriod); + // Tạo thông báo về tickets waiting nếu có + $waitingTicketsMessage = ''; + if (!empty($dataListPeriodWaiting)) { + // Kiểm tra số dư ngày phép cho tickets waiting + $totalWaitingDays = $this->calculateTotalLeaveDays($dataListPeriodWaiting); + $waitingTicketsMessage = "Bạn đang có " . $ticketsWaiting->count() . " yêu cầu nghỉ phép chưa được duyệt"; + + // Nếu muốn thêm chi tiết từng ticket waiting + if ($ticketsWaiting->count() > 0) { + $waitingTicketsMessage .= ":\n"; + foreach ($ticketsWaiting as $ticket) { + $startDateFormat = Carbon::parse($ticket->start_date)->format('d/m/Y'); + $endDateFormat = Carbon::parse($ticket->end_date)->format('d/m/Y'); + $waitingTicketsMessage .= "- " . $ticket->startPeriodName . " (" . $startDateFormat . ") - " . + $ticket->endPeriodName . " (" . $endDateFormat . ")\n"; + } + } + } + + $balanceCheckResultWaiting = $this->checkLeaveBalance($user, $dataListPeriodWaiting); + if ($balanceCheckResultWaiting['months_info']) { + $monthsInfoWaiting = $balanceCheckResultWaiting['months_info']; + $waitingTicketsMessage .= $balanceCheckResultWaiting['message'] . "\n------------------------------------------------"; + $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod, $monthsInfoWaiting); + } else { + $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod); + } - // Kiểm tra số dư ngày phép - $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod); - // dd($balanceCheckResult); // Nếu không đủ ngày phép, trả về thông báo và không tạo ticket if (!$balanceCheckResult['success']) { + $finalMessage = $waitingTicketsMessage; + if (!empty($finalMessage)) { + $finalMessage .= "\n\n"; + } + $finalMessage .= $balanceCheckResult['message']; + $balanceCheckResult['message'] = $finalMessage . "\n\nBạn có chấp nhận không?\n"; + $balanceCheckResult['waitingTicketMessage'] = $waitingTicketsMessage; + return AbstractController::ResultError("Không thỏa mãn điều kiện ngày phép", $balanceCheckResult); } } @@ -297,22 +329,18 @@ class TicketController extends Controller * @param array|null $dataListPeriod Danh sách các ngày xin nghỉ [['date' => 'Y-m-d', 'period' => 'ALL|S|C'], ...] * @return array Kết quả kiểm tra ['success' => bool, 'message' => string|null, ...] */ - private function checkLeaveBalance($user, ?array $dataListPeriod = null): array + private function checkLeaveBalance($user, ?array $dataListPeriod = null, ?array $monthsInfoWaiting = null): array { // Kiểm tra giới hạn nghỉ phép theo tháng - $monthsInfo = []; if (!empty($dataListPeriod)) { - $monthlyCheckResult = $this->checkMonthlyLeaveLimit($user, $dataListPeriod); - if (!$monthlyCheckResult['success']) { - return $monthlyCheckResult; - } + return $this->checkMonthlyLeaveLimit($user, $dataListPeriod, $monthsInfoWaiting); } // Đủ điều kiện return [ 'success' => true, 'message' => null, - 'months_info' => $monthsInfo + 'months_info' => [] ]; } @@ -356,7 +384,7 @@ class TicketController extends Controller return $maxDaysPerMonth; } - private function checkMonthlyLeaveLimit($user, array $dataListPeriod): array + private function checkMonthlyLeaveLimit($user, array $dataListPeriod, ?array $monthsInfoWaiting = null): array { // Danh sách ngày nghỉ theo tháng $requestMonths = $this->groupLeaveRequestsByMonth($dataListPeriod); @@ -366,6 +394,13 @@ class TicketController extends Controller $remainingDaysInMonthIsUsed = 0; foreach ($requestMonths as $monthKey => $monthData) { + if ($monthsInfoWaiting) { + foreach ($monthsInfoWaiting as $monthInfo) { + if ($monthInfo['month'] == $monthData['month'] && $monthInfo['year'] == $monthData['year']) { + $remainingDaysInMonthIsUsed += $monthInfo['remaining_days_in_month_remaining']; + } + } + } // Tính tổng số ngày nghỉ có phép trong tháng $usedDaysInMonth = $this->getUsedLeaveDaysInMonth($user, $monthData['year'], $monthData['month'], 'ONLEAVE'); @@ -387,18 +422,6 @@ class TicketController extends Controller //Ngày phép còn lại trong tháng $remainingDaysInMonth = $totalLeaveDaysInMonth - $totalLeaveDaysInMonthToMonth; - $month_data = [ - 'year' => $monthData['year'], - 'month' => $monthData['month'], - 'total_leave_days_in_month' => $totalLeaveDaysInMonth, //tổng số ngày phép - 'total_leave_days_in_month_to_month' => $totalLeaveDaysInMonthToMonth, // tổng ngày nghỉ có phép - 'remaining_days_in_month' => $remainingDaysInMonth, //ngày phép còn lại - 'days_used' => $usedDaysInMonth, //tổng số ngày nghỉ có phép ở tháng hiện tại - 'days_used_without_pay' => $usedDaysInMonthWithoutPay, //tổng số ngày nghỉ không phép ở tháng hiện tại - 'days_requested' => $monthData['days_requested'], //số ngày yêu cầu nghỉ của tháng - 'status' => 'ok', // mặc định là ok - ]; - $remainingDaysInMonthRemaining = $remainingDaysInMonth - $remainingDaysInMonthIsUsed; // Xử lý các trường hợp thiếu ngày phép if ($remainingDaysInMonthRemaining <= 0) { //hết phép @@ -413,7 +436,7 @@ class TicketController extends Controller $monthMessage = "* Tháng {$monthData['month']}/{$monthData['year']}: \n - Số ngày phép còn lại: {$remainingDaysInMonthRemaining}, Số ngày yêu cầu: {$monthData['days_requested']}.\n - Bạn sẽ sử dụng {$remainingDaysInMonthRemaining} ngày phép và {$daysNotEnough} ngày không phép."; $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage; - $remainingDaysInMonthIsUsed = $remainingDaysInMonth; + $remainingDaysInMonthIsUsed = $remainingDaysInMonth; // lấy số ngày phép còn lại của tháng đó } else if ($remainingDaysInMonthRemaining >= $monthData['days_requested']) { // Đủ ngày phép ở tháng đó // 1. Check thêm rule 1 tháng chỉ được nghỉ tối đa $maxDaysPerMonth ngày có phép, ngày vượt sẽ là ngày không phép @@ -424,16 +447,30 @@ class TicketController extends Controller $monthMessage = "* Theo quy định ngày phép tôi đa mỗi tháng là {$maxDaysPerMonth} ngày. \nTháng {$monthData['month']}/{$monthData['year']}: \n - Số ngày phép còn lại: {$remainingDaysInMonthRemaining}, Số ngày yêu cầu: {$monthData['days_requested']}.\n - Bạn sẽ sử dụng {$maxDaysPerMonth} ngày phép và {$daysWithoutPermission} ngày không phép."; $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage; } + $remainingDaysInMonthRemaining = $monthData['days_requested']; } + + $month_data = [ + 'year' => $monthData['year'], + 'month' => $monthData['month'], + 'total_leave_days_in_month' => $totalLeaveDaysInMonth, //tổng số ngày phép + 'total_leave_days_in_month_to_month' => $totalLeaveDaysInMonthToMonth, // tổng ngày nghỉ có phép + 'remaining_days_in_month' => $remainingDaysInMonth, //ngày phép còn lại + 'days_used' => $usedDaysInMonth, //tổng số ngày nghỉ có phép ở tháng hiện tại + 'days_used_without_pay' => $usedDaysInMonthWithoutPay, //tổng số ngày nghỉ không phép ở tháng hiện tại + 'days_requested' => $monthData['days_requested'], //số ngày yêu cầu nghỉ của tháng + 'remaining_days_in_month_remaining' => $remainingDaysInMonthRemaining, + 'status' => 'ok', // mặc định là ok + ]; + // Thêm thông tin tháng vào mảng kết quả $monthsInfo[] = $month_data; } - // Trả về kết quả tổng hợp if ($hasInsufficientDays) { return [ 'success' => false, - 'message' => $errorMessage . "\n\nBạn có chấp nhận không?\n", + 'message' => $errorMessage, 'warning_type' => 'exceed_monthly_limit', 'months_info' => $monthsInfo ]; @@ -441,7 +478,7 @@ class TicketController extends Controller return [ 'success' => true, - 'message' => "Đủ ngày phép cho tất cả tháng yêu cầu.", + 'message' => "Đủ ngày phép cho yêu cầu.", 'months_info' => $monthsInfo ]; } diff --git a/FRONTEND/src/pages/LeaveManagement/LeaveManagement.tsx b/FRONTEND/src/pages/LeaveManagement/LeaveManagement.tsx index 2910ead..7621a54 100644 --- a/FRONTEND/src/pages/LeaveManagement/LeaveManagement.tsx +++ b/FRONTEND/src/pages/LeaveManagement/LeaveManagement.tsx @@ -308,7 +308,7 @@ const LeaveManagement = () => { try { const timestamp = moment().format('DDMMYYYY_HHmmss') const fileName = `LeaveManagement_${date.year}_${timestamp}.xlsx` - + await exportFile( exportLeaveManagement, { @@ -576,11 +576,11 @@ const LeaveManagement = () => { mr={'md'} src={ import.meta.env.VITE_BACKEND_URL.includes('local') - ? import.meta.env.VITE_BACKEND_URL + - 'storage/' + - user.user.avatar - : import.meta.env.VITE_BACKEND_URL + - 'image/storage/' + + ? import.meta.env.VITE_BACKEND_URL + + 'storage/' + + user.user.avatar + : import.meta.env.VITE_BACKEND_URL + + 'image/storage/' + user.user.avatar } />