truong-leave-day #124
			
				
			
		
		
		
	| 
						 | 
					@ -216,19 +216,20 @@ class TicketController extends Controller
 | 
				
			||||||
        $reason = $request->input('reason');
 | 
					        $reason = $request->input('reason');
 | 
				
			||||||
        $isAccept = $request->input('is_accept') ?? false;
 | 
					        $isAccept = $request->input('is_accept') ?? false;
 | 
				
			||||||
        $user = auth('admins')->user(); // user create ticket
 | 
					        $user = auth('admins')->user(); // user create ticket
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        $start_date = Carbon::create($startDate)->setTimezone(env('TIME_ZONE'));
 | 
					        $start_date = Carbon::create($startDate)->setTimezone(env('TIME_ZONE'));
 | 
				
			||||||
        $end_date = Carbon::create($endDate)->setTimezone(env('TIME_ZONE'));
 | 
					        $end_date = Carbon::create($endDate)->setTimezone(env('TIME_ZONE'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get mảng ngày nghỉ 
 | 
				
			||||||
 | 
					        $dataListPeriod = $this->getAllPeriodNew($start_date, $startPeriod, $end_date, $endPeriod);
 | 
				
			||||||
 | 
					        if (empty($dataListPeriod)) {
 | 
				
			||||||
 | 
					            return AbstractController::ResultError('Không thể tính toán khoảng thời gian nghỉ hợp lệ.');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // --- Chỉ kiểm tra ngày phép khi loại là ONLEAVE ---
 | 
					        // --- Chỉ kiểm tra ngày phép khi loại là ONLEAVE ---
 | 
				
			||||||
        if ($type === 'ONLEAVE' && !$isAccept) {
 | 
					        if ($type === 'ONLEAVE' && !$isAccept) {
 | 
				
			||||||
            // Get mảng ngày nghỉ 
 | 
					 | 
				
			||||||
            $dataListPeriod = $this->getAllPeriodNew($start_date, $startPeriod, $end_date, $endPeriod);
 | 
					 | 
				
			||||||
            if (empty($dataListPeriod)) {
 | 
					 | 
				
			||||||
                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 nghỉ phép đang ở trạng thái WAITING
 | 
					            // Lấy thông tin tickets nghỉ phép đang ở trạng thái WAITING
 | 
				
			||||||
            $ticketsWaiting = Ticket::where('user_id', $user->id)->where('status', 'WAITING')->where('type', 'ONLEAVE')
 | 
					            $ticketsWaiting = Ticket::where('user_id', $user->id)->where('status', 'WAITING')->whereIn('type', ['ONLEAVE'])
 | 
				
			||||||
                ->get();
 | 
					                ->get();
 | 
				
			||||||
            $dataListPeriodWaiting = [];
 | 
					            $dataListPeriodWaiting = [];
 | 
				
			||||||
            if ($ticketsWaiting->count() > 0) {
 | 
					            if ($ticketsWaiting->count() > 0) {
 | 
				
			||||||
| 
						 | 
					@ -237,11 +238,34 @@ class TicketController extends Controller
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $ticketsWaitingWFH = Ticket::where('user_id', $user->id)->where('status', 'WAITING')->whereIn('type', ['WFH'])
 | 
				
			||||||
 | 
					                ->get();
 | 
				
			||||||
 | 
					            $dataListPeriodWaitingWFH = [];
 | 
				
			||||||
 | 
					            if ($ticketsWaitingWFH->count() > 0) {
 | 
				
			||||||
 | 
					                foreach ($ticketsWaitingWFH as $ticket) {
 | 
				
			||||||
 | 
					                    $dataListPeriodWaitingWFH = array_merge($dataListPeriodWaitingWFH, $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Lấy thông tin tickets nghỉ phép đang ở trạng thái CONFIRMED
 | 
					            // Lấy thông tin tickets nghỉ phép đang ở trạng thái CONFIRMED
 | 
				
			||||||
            $ticketsConfirmed = Ticket::where('user_id', $user->id)->where('status', 'CONFIRMED')
 | 
					            $ticketsConfirmed = Ticket::where('user_id', $user->id)
 | 
				
			||||||
                ->whereIn('type', ['ONLEAVE'])
 | 
					                ->where('status', 'CONFIRMED')
 | 
				
			||||||
                ->where(DB::raw('DATE(start_date)'), '>=', $start_date->toDateString())
 | 
					                ->whereIn('type', ['ONLEAVE', 'WFH'])
 | 
				
			||||||
                ->where(DB::raw('DATE(end_date)'), '<=', $end_date->toDateString())
 | 
					                ->where(function ($query) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                    $query->where(function ($q) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                        // Trường hợp 1: start_date nằm trong khoảng
 | 
				
			||||||
 | 
					                        $q->whereBetween(DB::raw('DATE(start_date)'), [$start_date->toDateString(), $end_date->toDateString()]);
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                        ->orWhere(function ($q) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                            // Trường hợp 2: end_date nằm trong khoảng
 | 
				
			||||||
 | 
					                            $q->whereBetween(DB::raw('DATE(end_date)'), [$start_date->toDateString(), $end_date->toDateString()]);
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        ->orWhere(function ($q) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                            // Trường hợp 3: Khoảng thời gian được chọn nằm trong khoảng của ticket
 | 
				
			||||||
 | 
					                            $q->where(DB::raw('DATE(start_date)'), '<=', $start_date->toDateString())
 | 
				
			||||||
 | 
					                                ->where(DB::raw('DATE(end_date)'), '>=', $end_date->toDateString());
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
                ->get();
 | 
					                ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $dataListPeriodConfirmed = [];
 | 
					            $dataListPeriodConfirmed = [];
 | 
				
			||||||
| 
						 | 
					@ -250,10 +274,11 @@ class TicketController extends Controller
 | 
				
			||||||
                    $dataListPeriodConfirmed = array_merge($dataListPeriodConfirmed, $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period));
 | 
					                    $dataListPeriodConfirmed = array_merge($dataListPeriodConfirmed, $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            // dd($dataListPeriodConfirmed,$ticketsConfirmed,$start_date->toDateString(),$end_date->toDateString());
 | 
				
			||||||
            // Chuyển đổi mảng đa chiều thành mảng chuỗi để có thể so sánh
 | 
					            // Chuyển đổi mảng đa chiều thành mảng chuỗi để có thể so sánh
 | 
				
			||||||
            $periodStrings = [];
 | 
					            $periodStrings = [];
 | 
				
			||||||
            $waitingPeriodStrings = [];
 | 
					            $waitingPeriodStrings = [];
 | 
				
			||||||
 | 
					            $waitingPeriodStringsWFH = [];
 | 
				
			||||||
            $confirmedPeriodStrings = [];
 | 
					            $confirmedPeriodStrings = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach ($dataListPeriod as $period) {
 | 
					            foreach ($dataListPeriod as $period) {
 | 
				
			||||||
| 
						 | 
					@ -274,6 +299,15 @@ class TicketController extends Controller
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach ($dataListPeriodWaitingWFH as $period) {
 | 
				
			||||||
 | 
					                if ($period['period'] == 'ALL') {
 | 
				
			||||||
 | 
					                    $waitingPeriodStringsWFH[] = $period['date'] . '_S';
 | 
				
			||||||
 | 
					                    $waitingPeriodStringsWFH[] = $period['date'] . '_C';
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $waitingPeriodStringsWFH[] = $period['date'] . '_' . $period['period'];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach ($dataListPeriodConfirmed as $period) {
 | 
					            foreach ($dataListPeriodConfirmed as $period) {
 | 
				
			||||||
                if ($period['period'] == 'ALL') {
 | 
					                if ($period['period'] == 'ALL') {
 | 
				
			||||||
                    $confirmedPeriodStrings[] = $period['date'] . '_S';
 | 
					                    $confirmedPeriodStrings[] = $period['date'] . '_S';
 | 
				
			||||||
| 
						 | 
					@ -288,6 +322,11 @@ class TicketController extends Controller
 | 
				
			||||||
                return AbstractController::ResultError('Đã có ticket đang chờ duyệt trong thời gian này, không thể tạo ticket mới!');
 | 
					                return AbstractController::ResultError('Đã có ticket đang chờ duyệt trong thời gian này, không thể tạo ticket mới!');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Kiểm tra xem có sự trùng lặp giữa request mới và tickets đang chờ duyệt WFH
 | 
				
			||||||
 | 
					            if (count(array_intersect($periodStrings, $waitingPeriodStringsWFH)) > 0) {
 | 
				
			||||||
 | 
					                return AbstractController::ResultError('Đã có ticket đang chờ duyệt trong thời gian này, không thể tạo ticket mới!');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Kiểm tra xem có sự trùng lặp giữa request mới và tickets đã được duyệt
 | 
					            // Kiểm tra xem có sự trùng lặp giữa request mới và tickets đã được duyệt
 | 
				
			||||||
            if (count(array_intersect($periodStrings, $confirmedPeriodStrings)) > 0) {
 | 
					            if (count(array_intersect($periodStrings, $confirmedPeriodStrings)) > 0) {
 | 
				
			||||||
                return AbstractController::ResultError('Đã có ticket được duyệt trong thời gian này, không thể tạo ticket mới!');
 | 
					                return AbstractController::ResultError('Đã có ticket được duyệt trong thời gian này, không thể tạo ticket mới!');
 | 
				
			||||||
| 
						 | 
					@ -317,7 +356,7 @@ class TicketController extends Controller
 | 
				
			||||||
                $monthsInfoWaiting = $balanceCheckResultWaiting['months_info'];
 | 
					                $monthsInfoWaiting = $balanceCheckResultWaiting['months_info'];
 | 
				
			||||||
                if ($balanceCheckResultWaiting['success']) {
 | 
					                if ($balanceCheckResultWaiting['success']) {
 | 
				
			||||||
                    $waitingTicketsMessage .= "------------------------------------------------";
 | 
					                    $waitingTicketsMessage .= "------------------------------------------------";
 | 
				
			||||||
                }else{
 | 
					                } else {
 | 
				
			||||||
                    $waitingTicketsMessage .=  $balanceCheckResultWaiting['message'] . "\n------------------------------------------------";
 | 
					                    $waitingTicketsMessage .=  $balanceCheckResultWaiting['message'] . "\n------------------------------------------------";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod, $monthsInfoWaiting);
 | 
					                $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod, $monthsInfoWaiting);
 | 
				
			||||||
| 
						 | 
					@ -338,6 +377,85 @@ class TicketController extends Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return AbstractController::ResultError("Không thỏa mãn điều kiện ngày phép", $balanceCheckResult);
 | 
					                return AbstractController::ResultError("Không thỏa mãn điều kiện ngày phép", $balanceCheckResult);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else if ($type === 'WFH') {
 | 
				
			||||||
 | 
					            // Lấy thông tin tickets nghỉ phép đang ở trạng thái WAITING
 | 
				
			||||||
 | 
					            $ticketsWaiting = Ticket::where('user_id', $user->id)->where('status', 'WAITING')->whereIn('type', ['WFH', 'ONLEAVE'])
 | 
				
			||||||
 | 
					                ->get();
 | 
				
			||||||
 | 
					            $dataListPeriodWaiting = [];
 | 
				
			||||||
 | 
					            if ($ticketsWaiting->count() > 0) {
 | 
				
			||||||
 | 
					                foreach ($ticketsWaiting as $ticket) {
 | 
				
			||||||
 | 
					                    $dataListPeriodWaiting = array_merge($dataListPeriodWaiting, $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Lấy thông tin tickets nghỉ phép đang ở trạng thái CONFIRMED
 | 
				
			||||||
 | 
					            $ticketsConfirmed = Ticket::where('user_id', $user->id)
 | 
				
			||||||
 | 
					                ->where('status', 'CONFIRMED')
 | 
				
			||||||
 | 
					                ->whereIn('type', ['ONLEAVE', 'WFH'])
 | 
				
			||||||
 | 
					                ->where(function ($query) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                    $query->where(function ($q) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                        // Trường hợp 1: start_date nằm trong khoảng
 | 
				
			||||||
 | 
					                        $q->whereBetween(DB::raw('DATE(start_date)'), [$start_date->toDateString(), $end_date->toDateString()]);
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                        ->orWhere(function ($q) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                            // Trường hợp 2: end_date nằm trong khoảng
 | 
				
			||||||
 | 
					                            $q->whereBetween(DB::raw('DATE(end_date)'), [$start_date->toDateString(), $end_date->toDateString()]);
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        ->orWhere(function ($q) use ($start_date, $end_date) {
 | 
				
			||||||
 | 
					                            // Trường hợp 3: Khoảng thời gian được chọn nằm trong khoảng của ticket
 | 
				
			||||||
 | 
					                            $q->where(DB::raw('DATE(start_date)'), '<=', $start_date->toDateString())
 | 
				
			||||||
 | 
					                                ->where(DB::raw('DATE(end_date)'), '>=', $end_date->toDateString());
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                ->get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $dataListPeriodConfirmed = [];
 | 
				
			||||||
 | 
					            if ($ticketsConfirmed->count() > 0) {
 | 
				
			||||||
 | 
					                foreach ($ticketsConfirmed as $ticket) {
 | 
				
			||||||
 | 
					                    $dataListPeriodConfirmed = array_merge($dataListPeriodConfirmed, $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // dd($dataListPeriodConfirmed,$ticketsConfirmed,$start_date->toDateString(),$end_date->toDateString());
 | 
				
			||||||
 | 
					            // Chuyển đổi mảng đa chiều thành mảng chuỗi để có thể so sánh
 | 
				
			||||||
 | 
					            $periodStrings = [];
 | 
				
			||||||
 | 
					            $waitingPeriodStrings = [];
 | 
				
			||||||
 | 
					            $confirmedPeriodStrings = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach ($dataListPeriod as $period) {
 | 
				
			||||||
 | 
					                if ($period['period'] == 'ALL') {
 | 
				
			||||||
 | 
					                    $periodStrings[] = $period['date'] . '_S';
 | 
				
			||||||
 | 
					                    $periodStrings[] = $period['date'] . '_C';
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $periodStrings[] = $period['date'] . '_' . $period['period'];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach ($dataListPeriodConfirmed as $period) {
 | 
				
			||||||
 | 
					                if ($period['period'] == 'ALL') {
 | 
				
			||||||
 | 
					                    $confirmedPeriodStrings[] = $period['date'] . '_S';
 | 
				
			||||||
 | 
					                    $confirmedPeriodStrings[] = $period['date'] . '_C';
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $confirmedPeriodStrings[] = $period['date'] . '_' . $period['period'];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach ($dataListPeriodWaiting as $period) {
 | 
				
			||||||
 | 
					                if ($period['period'] == 'ALL') {
 | 
				
			||||||
 | 
					                    $waitingPeriodStrings[] = $period['date'] . '_S';
 | 
				
			||||||
 | 
					                    $waitingPeriodStrings[] = $period['date'] . '_C';
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $waitingPeriodStrings[] = $period['date'] . '_' . $period['period'];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // Kiểm tra xem có sự trùng lặp giữa request mới và tickets đang chờ duyệt
 | 
				
			||||||
 | 
					            if (count(array_intersect($periodStrings, $waitingPeriodStrings)) > 0) {
 | 
				
			||||||
 | 
					                return AbstractController::ResultError('Đã có ticket đang chờ duyệt trong thời gian này, không thể tạo ticket mới!');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Kiểm tra xem có sự trùng lặp giữa request mới và tickets đã được duyệt
 | 
				
			||||||
 | 
					            if (count(array_intersect($periodStrings, $confirmedPeriodStrings)) > 0) {
 | 
				
			||||||
 | 
					                return AbstractController::ResultError('Đã có ticket được duyệt trong thời gian này, không thể tạo ticket mới!');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // --- Kết thúc kiểm tra ---
 | 
					        // --- Kết thúc kiểm tra ---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -375,7 +493,7 @@ class TicketController extends Controller
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
            // Thêm kiểm tra null trước khi gửi mail
 | 
					            // Thêm kiểm tra null trước khi gửi mail
 | 
				
			||||||
            if ($dataMasterStartPeriod && $dataMasterEndPeriod && $dataMasterType) {
 | 
					            if ($dataMasterStartPeriod && $dataMasterEndPeriod && $dataMasterType) {
 | 
				
			||||||
            Mail::to($value->email)->send(new TicketMail($data));
 | 
					                Mail::to($value->email)->send(new TicketMail($data));
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                Log::error("Missing category data for ticket ID: {$ticket->id}. Mail not sent.");
 | 
					                Log::error("Missing category data for ticket ID: {$ticket->id}. Mail not sent.");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -391,11 +509,11 @@ 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'], ...]
 | 
					     * @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, ...]
 | 
					     * @return array Kết quả kiểm tra ['success' => bool, 'message' => string|null, ...]
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private function checkLeaveBalance($user, ?array $dataListPeriod = null, ?array $monthsInfoWaiting = null): array
 | 
					    private function checkLeaveBalance($user, ?array $dataListPeriod = null, ?array $monthsInfoWaiting = null, ?bool $isAccept = false): array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Kiểm tra giới hạn nghỉ phép theo tháng
 | 
					        // Kiểm tra giới hạn nghỉ phép theo tháng
 | 
				
			||||||
        if (!empty($dataListPeriod)) {
 | 
					        if (!empty($dataListPeriod)) {
 | 
				
			||||||
            return $this->checkMonthlyLeaveLimit($user, $dataListPeriod, $monthsInfoWaiting);
 | 
					            return $this->checkMonthlyLeaveLimit($user, $dataListPeriod, $monthsInfoWaiting, $isAccept);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Đủ điều kiện
 | 
					        // Đủ điều kiện
 | 
				
			||||||
| 
						 | 
					@ -446,7 +564,7 @@ class TicketController extends Controller
 | 
				
			||||||
        return $maxDaysPerMonth;
 | 
					        return $maxDaysPerMonth;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function checkMonthlyLeaveLimit($user, array $dataListPeriod, ?array $monthsInfoWaiting = null): array
 | 
					    private function checkMonthlyLeaveLimit($user, array $dataListPeriod, ?array $monthsInfoWaiting = null, ?bool $isAccept = false): array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Danh sách ngày nghỉ theo tháng
 | 
					        // Danh sách ngày nghỉ theo tháng
 | 
				
			||||||
        $requestMonths = $this->groupLeaveRequestsByMonth($dataListPeriod);
 | 
					        $requestMonths = $this->groupLeaveRequestsByMonth($dataListPeriod);
 | 
				
			||||||
| 
						 | 
					@ -477,7 +595,7 @@ class TicketController extends Controller
 | 
				
			||||||
            $totalDaysInMonth = $usedDaysInMonth + $usedDaysInMonthWithoutPay + $monthData['days_requested'];
 | 
					            $totalDaysInMonth = $usedDaysInMonth + $usedDaysInMonthWithoutPay + $monthData['days_requested'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Tổng phép có trong tháng
 | 
					            // Tổng phép có trong tháng
 | 
				
			||||||
            $totalLeaveDaysInMonth = $this->getTotalLeaveDaysInMonth($user, $monthData['year'], $monthData['month']);
 | 
					            $totalLeaveDaysInMonth = $this->getTotalLeaveDaysInMonth($user, $monthData['year'], $monthData['month'], $isAccept);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Tính tổng số ngày nghỉ có phép đến tháng hiện tại
 | 
					            // Tính tổng số ngày nghỉ có phép đến tháng hiện tại
 | 
				
			||||||
            $totalLeaveDaysInMonthToMonth = $this->getTotalLeaveDaysInMonthToMonth($user, $monthData['year'], $monthData['month']);
 | 
					            $totalLeaveDaysInMonthToMonth = $this->getTotalLeaveDaysInMonthToMonth($user, $monthData['year'], $monthData['month']);
 | 
				
			||||||
| 
						 | 
					@ -487,16 +605,16 @@ class TicketController extends Controller
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $remainingDaysInMonthRemaining = $remainingDaysInMonth - $remainingDaysInMonthIsUsed;
 | 
					            $remainingDaysInMonthRemaining = $remainingDaysInMonth - $remainingDaysInMonthIsUsed;
 | 
				
			||||||
            // if ($monthsInfoWaiting) {
 | 
					            // if ($monthsInfoWaiting) {
 | 
				
			||||||
                // dd(
 | 
					            // dd(
 | 
				
			||||||
                //         "Ngày phép còn lại trong tháng: " . $remainingDaysInMonthRemaining,
 | 
					            //         "Ngày phép còn lại trong tháng: " . $remainingDaysInMonthRemaining,
 | 
				
			||||||
                //         "Ngày phép còn lại: " . $remainingDaysInMonth,
 | 
					            //         "Ngày phép còn lại: " . $remainingDaysInMonth,
 | 
				
			||||||
                //         "Ngày phép đã sử dụng: " . $remainingDaysInMonthIsUsed,
 | 
					            //         "Ngày phép đã sử dụng: " . $remainingDaysInMonthIsUsed,
 | 
				
			||||||
                //         "Ngày phép yêu cầu: " . $monthData['days_requested'],
 | 
					            //         "Ngày phép yêu cầu: " . $monthData['days_requested'],
 | 
				
			||||||
                //         "Tổng ngày nghỉ trong tháng: " . $totalDaysInMonth,
 | 
					            //         "Tổng ngày nghỉ trong tháng: " . $totalDaysInMonth,
 | 
				
			||||||
                //         "Ngày phép đã sử dụng: " . $usedDaysInMonth,
 | 
					            //         "Ngày phép đã sử dụng: " . $usedDaysInMonth,
 | 
				
			||||||
                //     );
 | 
					            //     );
 | 
				
			||||||
            // }
 | 
					            // }
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
            $month_data_status = 'ok';
 | 
					            $month_data_status = 'ok';
 | 
				
			||||||
            $days_will_use = 0;
 | 
					            $days_will_use = 0;
 | 
				
			||||||
            $days_will_use_without_pay = 0;
 | 
					            $days_will_use_without_pay = 0;
 | 
				
			||||||
| 
						 | 
					@ -510,33 +628,44 @@ class TicketController extends Controller
 | 
				
			||||||
                $days_will_use = 0;
 | 
					                $days_will_use = 0;
 | 
				
			||||||
                $days_will_use_without_pay = $monthData['days_requested'];
 | 
					                $days_will_use_without_pay = $monthData['days_requested'];
 | 
				
			||||||
            } else if ($remainingDaysInMonthRemaining < $monthData['days_requested']) { // không đủ ngày phép
 | 
					            } else if ($remainingDaysInMonthRemaining < $monthData['days_requested']) { // không đủ ngày phép
 | 
				
			||||||
                $hasInsufficientDays = true;
 | 
					                if (
 | 
				
			||||||
                $month_data_status = 'insufficient_days';
 | 
					                    $remainingDaysInMonthRemaining >= $maxDaysPerMonth
 | 
				
			||||||
                $daysNotEnough = $monthData['days_requested'] - $remainingDaysInMonthRemaining;
 | 
					                ) {
 | 
				
			||||||
                $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.";
 | 
					                    $hasInsufficientDays = true;
 | 
				
			||||||
                $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage;
 | 
					                    $month_data_status = 'exceed_max_days';
 | 
				
			||||||
                $remainingDaysInMonthIsUsed = $remainingDaysInMonth; // lấy số ngày phép còn lại của tháng đó
 | 
					                    $daysNotEnough = $monthData['days_requested'] - $maxDaysPerMonth;
 | 
				
			||||||
 | 
					                    $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 - Bạn đã sử dụng {$usedDaysInMonth} ngày phép, còn lại {$remainingDaysInMonthRemaining} ngày phép.\n - Bạn sẽ sử dụng {$maxDaysPerMonth} ngày phép và {$daysNotEnough} ngày không phép.";
 | 
				
			||||||
 | 
					                    $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage;
 | 
				
			||||||
 | 
					                    $days_will_use = $maxDaysPerMonth;
 | 
				
			||||||
 | 
					                    $days_will_use_without_pay = $monthData['days_requested'] - $maxDaysPerMonth;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $hasInsufficientDays = true;
 | 
				
			||||||
 | 
					                    $month_data_status = 'insufficient_days';
 | 
				
			||||||
 | 
					                    $daysNotEnough = $monthData['days_requested'] - $remainingDaysInMonthRemaining;
 | 
				
			||||||
 | 
					                    $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; // lấy số ngày phép còn lại của tháng đó
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $days_will_use = $remainingDaysInMonthRemaining;
 | 
					                    $days_will_use = $remainingDaysInMonthRemaining;
 | 
				
			||||||
                $days_will_use_without_pay = $daysNotEnough;
 | 
					                    $days_will_use_without_pay = $daysNotEnough;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            } else if (
 | 
					            } else if (
 | 
				
			||||||
                $remainingDaysInMonthRemaining >= $monthData['days_requested']
 | 
					                $remainingDaysInMonthRemaining >= $monthData['days_requested']
 | 
				
			||||||
                // || $remainingDaysInMonthIsUsed + $monthData['days_requested'] > $maxDaysPerMonth
 | 
					 | 
				
			||||||
            ) { // Đủ ngày phép ở tháng đó
 | 
					            ) { // Đủ 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
 | 
					                // 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
 | 
				
			||||||
                if($totalDaysInMonth > $maxDaysPerMonth){
 | 
					                if ($totalDaysInMonth > $maxDaysPerMonth) {
 | 
				
			||||||
                    $daysWithoutPermission = $totalDaysInMonth - $maxDaysPerMonth;
 | 
					                    $daysWithoutPermission = $totalDaysInMonth - $maxDaysPerMonth;
 | 
				
			||||||
                    $daysWillUse = $maxDaysPerMonth - $usedDaysInMonth; // số ngày phép sẽ sử dụng
 | 
					                    $daysWillUse = $maxDaysPerMonth - $usedDaysInMonth; // số ngày phép sẽ sử dụng
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $hasInsufficientDays = true;
 | 
					                    $hasInsufficientDays = true;
 | 
				
			||||||
                    $month_data_status = 'exceed_max_days';
 | 
					                    $month_data_status = 'exceed_max_days';
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                    $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 - Bạn đã sử dụng {$usedDaysInMonth} ngày phép, còn lại {$remainingDaysInMonthRemaining} ngày phép.\n - Bạn sẽ sử dụng " . $daysWillUse . " ngày phép và {$daysWithoutPermission} ngày không phép.";
 | 
					                    $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 - Bạn đã sử dụng {$usedDaysInMonth} ngày phép, còn lại {$remainingDaysInMonthRemaining} ngày phép.\n - Bạn sẽ sử dụng " . $daysWillUse . " ngày phép và {$daysWithoutPermission} ngày không phép.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage;
 | 
					                    $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage;
 | 
				
			||||||
                    $days_will_use = $daysWillUse;
 | 
					                    $days_will_use = $daysWillUse;
 | 
				
			||||||
                    $days_will_use_without_pay = $daysWithoutPermission;
 | 
					                    $days_will_use_without_pay = $daysWithoutPermission;
 | 
				
			||||||
                }else if ($monthData['days_requested'] + $remainingDaysInMonthIsUsed > $maxDaysPerMonth) {
 | 
					                } else if ($monthData['days_requested'] + $remainingDaysInMonthIsUsed > $maxDaysPerMonth) {
 | 
				
			||||||
                    if ($remainingDaysInMonthIsUsed > 0) {
 | 
					                    if ($remainingDaysInMonthIsUsed > 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        $daysWillUse = $maxDaysPerMonth - $remainingDaysInMonthIsUsed; // số ngày phép sẽ sử dụng
 | 
					                        $daysWillUse = $maxDaysPerMonth - $remainingDaysInMonthIsUsed; // số ngày phép sẽ sử dụng
 | 
				
			||||||
| 
						 | 
					@ -613,7 +742,7 @@ class TicketController extends Controller
 | 
				
			||||||
            ->sum('categories.c_value');
 | 
					            ->sum('categories.c_value');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function getTotalLeaveDaysInMonth($user, int $year, int $month): float
 | 
					    private function getTotalLeaveDaysInMonth($user, int $year, int $month, ?bool $isAccept = false): float
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $leaveDaysInfo = LeaveDays::where('ld_user_id', $user->id)
 | 
					        $leaveDaysInfo = LeaveDays::where('ld_user_id', $user->id)
 | 
				
			||||||
            ->where('ld_year', $year)
 | 
					            ->where('ld_year', $year)
 | 
				
			||||||
| 
						 | 
					@ -626,8 +755,15 @@ class TicketController extends Controller
 | 
				
			||||||
            // } else {
 | 
					            // } else {
 | 
				
			||||||
            $totalAllocated = $leaveDaysInfo->ld_day_total;
 | 
					            $totalAllocated = $leaveDaysInfo->ld_day_total;
 | 
				
			||||||
            // }
 | 
					            // }
 | 
				
			||||||
            // $totalAllocated = $month; //(+ tạm để check)
 | 
					
 | 
				
			||||||
 | 
					            // Nếu là duyệt ticket thì sẽ cộng thêm số ngày phép còn lại của tháng hiện tại
 | 
				
			||||||
 | 
					            if ($isAccept) {
 | 
				
			||||||
 | 
					                if ($month >= $totalAllocated) {
 | 
				
			||||||
 | 
					                    $totalAllocated += $month - $totalAllocated;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            // bên hàm duyệt ticket sẽ check lại để + 1 ngày trước job để đảm bảo đủ ngày phép
 | 
					            // bên hàm duyệt ticket sẽ check lại để + 1 ngày trước job để đảm bảo đủ ngày phép
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Log::warning("No LeaveDays record found for user ID: {$user->id}, year: {$year}. Assuming 0 allocated days.");
 | 
					            Log::warning("No LeaveDays record found for user ID: {$user->id}, year: {$year}. Assuming 0 allocated days.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -756,8 +892,8 @@ class TicketController extends Controller
 | 
				
			||||||
        if ($action == "confirm") {
 | 
					        if ($action == "confirm") {
 | 
				
			||||||
            if ($ticket->type == "ONLEAVE") {
 | 
					            if ($ticket->type == "ONLEAVE") {
 | 
				
			||||||
                $dataListPeriod = $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
 | 
					                $dataListPeriod = $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
 | 
				
			||||||
                $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod);
 | 
					                $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod, null, true);
 | 
				
			||||||
                // dd($balanceCheckResult,$dataListPeriod);
 | 
					                // dd($balanceCheckResult, $dataListPeriod);
 | 
				
			||||||
                if ($balanceCheckResult['success'] == false) {
 | 
					                if ($balanceCheckResult['success'] == false) {
 | 
				
			||||||
                    if ($balanceCheckResult['months_info']) {
 | 
					                    if ($balanceCheckResult['months_info']) {
 | 
				
			||||||
                        foreach ($balanceCheckResult['months_info'] as $monthInfo) {
 | 
					                        foreach ($balanceCheckResult['months_info'] as $monthInfo) {
 | 
				
			||||||
| 
						 | 
					@ -875,27 +1011,25 @@ class TicketController extends Controller
 | 
				
			||||||
                        Log::warning("User ID: {$ticket->user_id} has used more leave days ({$totalUsedLeaveDays}) than allocated ({$totalAllocatedDays})");
 | 
					                        Log::warning("User ID: {$ticket->user_id} has used more leave days ({$totalUsedLeaveDays}) than allocated ({$totalAllocatedDays})");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // Cập nhật cột ld_day_total với số ngày đã làm tròn
 | 
					                        // Cập nhật cột ld_day_total với số ngày đã làm tròn
 | 
				
			||||||
                        if ($roundedExcessDays > 0) {
 | 
					                        $leaveDaysInfo->ld_day_total += $roundedExcessDays;
 | 
				
			||||||
                            $leaveDaysInfo->ld_day_total += $roundedExcessDays;
 | 
					                        $leaveDaysInfo->save();
 | 
				
			||||||
                            $leaveDaysInfo->save();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            Log::info("Updated leave days for User ID: {$ticket->user_id}. Added {$roundedExcessDays} days (rounded from {$excessDays})");
 | 
					                        Log::info("Updated leave days for User ID: {$ticket->user_id}. Added {$roundedExcessDays} days (rounded from {$excessDays})");
 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else if ($ticket->type == "WFH") {
 | 
					            } else if ($ticket->type == "WFH") {
 | 
				
			||||||
                $dataListPeriod = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
 | 
					                $dataListPeriod = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
 | 
				
			||||||
                foreach ($dataListPeriod as $result) {
 | 
					                foreach ($dataListPeriod as $result) {
 | 
				
			||||||
                list($year, $month, $day) = explode('-', $result['date']);
 | 
					                    list($year, $month, $day) = explode('-', $result['date']);
 | 
				
			||||||
                Notes::create([
 | 
					                    Notes::create([
 | 
				
			||||||
                    'n_user_id' => $ticket->user_id,
 | 
					                        'n_user_id' => $ticket->user_id,
 | 
				
			||||||
                    'n_day' => $day,
 | 
					                        'n_day' => $day,
 | 
				
			||||||
                    'n_month' => $month,
 | 
					                        'n_month' => $month,
 | 
				
			||||||
                    'n_year' => $year,
 | 
					                        'n_year' => $year,
 | 
				
			||||||
                    'n_time_type' => $result['period'],
 | 
					                        'n_time_type' => $result['period'],
 | 
				
			||||||
                    'n_reason' => $ticket->type,
 | 
					                        'n_reason' => $ticket->type,
 | 
				
			||||||
                    'n_note' => $ticket->reason
 | 
					                        'n_note' => $ticket->reason
 | 
				
			||||||
                ]);
 | 
					                    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    //WFH - start tracking
 | 
					                    //WFH - start tracking
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue