From e05e92b96bc295f67baf653614670e3f7b379fbf Mon Sep 17 00:00:00 2001 From: Truong Vo <41848815+vmtruong301296@users.noreply.github.com> Date: Mon, 16 Jun 2025 08:15:14 +0700 Subject: [PATCH 1/5] =?UTF-8?q?fix=20l=E1=BB=97i=20c=C3=B3=20ph=C3=A9p=20?= =?UTF-8?q?=C4=91=C6=B0=E1=BB=A3c=20duy=E1=BB=87t=20trong=20th=E1=BB=9Di?= =?UTF-8?q?=20gian=20=C4=91=C6=B0=E1=BB=A3c=20ch=E1=BB=8Dn=20khi=20t?= =?UTF-8?q?=E1=BA=A1o=20ticket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/Http/Controllers/TicketController.php | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php index 8ea27d8..2e21060 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php @@ -238,10 +238,24 @@ class TicketController extends Controller } // 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) + ->where('status', 'CONFIRMED') ->whereIn('type', ['ONLEAVE']) - ->where(DB::raw('DATE(start_date)'), '>=', $start_date->toDateString()) - ->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(); $dataListPeriodConfirmed = []; @@ -250,7 +264,7 @@ class TicketController extends Controller $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 = []; @@ -292,7 +306,7 @@ class TicketController extends Controller 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!'); } - + // Tạo thông báo về tickets waiting nếu có $waitingTicketsMessage = ''; if (!empty($dataListPeriodWaiting)) { -- 2.39.2 From 655d9cd4c6f8ea861340430b1d035ab90067e314 Mon Sep 17 00:00:00 2001 From: Truong Vo <41848815+vmtruong301296@users.noreply.github.com> Date: Mon, 16 Jun 2025 09:29:45 +0700 Subject: [PATCH 2/5] =?UTF-8?q?Hi=E1=BB=87u=20ch=E1=BB=89nh=20ng=C3=A0y=20?= =?UTF-8?q?ph=C3=A9p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/Http/Controllers/TicketController.php | 177 ++++++++++++------ 1 file changed, 119 insertions(+), 58 deletions(-) diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php index 2e21060..4f38421 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php @@ -216,19 +216,20 @@ class TicketController extends Controller $reason = $request->input('reason'); $isAccept = $request->input('is_accept') ?? false; $user = auth('admins')->user(); // user create ticket - + $start_date = Carbon::create($startDate)->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 --- 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 - $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(); $dataListPeriodWaiting = []; if ($ticketsWaiting->count() > 0) { @@ -240,21 +241,21 @@ class TicketController extends Controller // 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']) - ->where(function($query) use ($start_date, $end_date) { - $query->where(function($q) use ($start_date, $end_date) { + ->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()); - }); + ->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(); @@ -306,7 +307,7 @@ class TicketController extends Controller 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!'); } - + // Tạo thông báo về tickets waiting nếu có $waitingTicketsMessage = ''; if (!empty($dataListPeriodWaiting)) { @@ -331,7 +332,7 @@ class TicketController extends Controller $monthsInfoWaiting = $balanceCheckResultWaiting['months_info']; if ($balanceCheckResultWaiting['success']) { $waitingTicketsMessage .= "------------------------------------------------"; - }else{ + } else { $waitingTicketsMessage .= $balanceCheckResultWaiting['message'] . "\n------------------------------------------------"; } $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod, $monthsInfoWaiting); @@ -352,6 +353,62 @@ class TicketController extends Controller 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 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']; + } + } + + // 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 --- @@ -389,7 +446,7 @@ class TicketController extends Controller ); // Thêm kiểm tra null trước khi gửi mail if ($dataMasterStartPeriod && $dataMasterEndPeriod && $dataMasterType) { - Mail::to($value->email)->send(new TicketMail($data)); + Mail::to($value->email)->send(new TicketMail($data)); } else { Log::error("Missing category data for ticket ID: {$ticket->id}. Mail not sent."); } @@ -405,11 +462,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'], ...] * @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 if (!empty($dataListPeriod)) { - return $this->checkMonthlyLeaveLimit($user, $dataListPeriod, $monthsInfoWaiting); + return $this->checkMonthlyLeaveLimit($user, $dataListPeriod, $monthsInfoWaiting, $isAccept); } // Đủ điều kiện @@ -460,7 +517,7 @@ class TicketController extends Controller 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 $requestMonths = $this->groupLeaveRequestsByMonth($dataListPeriod); @@ -491,7 +548,7 @@ class TicketController extends Controller $totalDaysInMonth = $usedDaysInMonth + $usedDaysInMonthWithoutPay + $monthData['days_requested']; // 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 $totalLeaveDaysInMonthToMonth = $this->getTotalLeaveDaysInMonthToMonth($user, $monthData['year'], $monthData['month']); @@ -501,16 +558,16 @@ class TicketController extends Controller $remainingDaysInMonthRemaining = $remainingDaysInMonth - $remainingDaysInMonthIsUsed; // if ($monthsInfoWaiting) { - // dd( - // "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 đã sử dụng: " . $remainingDaysInMonthIsUsed, - // "Ngày phép yêu cầu: " . $monthData['days_requested'], - // "Tổng ngày nghỉ trong tháng: " . $totalDaysInMonth, - // "Ngày phép đã sử dụng: " . $usedDaysInMonth, - // ); + // dd( + // "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 đã sử dụng: " . $remainingDaysInMonthIsUsed, + // "Ngày phép yêu cầu: " . $monthData['days_requested'], + // "Tổng ngày nghỉ trong tháng: " . $totalDaysInMonth, + // "Ngày phép đã sử dụng: " . $usedDaysInMonth, + // ); // } - + $month_data_status = 'ok'; $days_will_use = 0; $days_will_use_without_pay = 0; @@ -535,22 +592,21 @@ class TicketController extends Controller $days_will_use_without_pay = $daysNotEnough; } else if ( $remainingDaysInMonthRemaining >= $monthData['days_requested'] - // || $remainingDaysInMonthIsUsed + $monthData['days_requested'] > $maxDaysPerMonth ) { // Đủ 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 - if($totalDaysInMonth > $maxDaysPerMonth){ + if ($totalDaysInMonth > $maxDaysPerMonth) { $daysWithoutPermission = $totalDaysInMonth - $maxDaysPerMonth; $daysWillUse = $maxDaysPerMonth - $usedDaysInMonth; // số ngày phép sẽ sử dụng $hasInsufficientDays = true; $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."; $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage; $days_will_use = $daysWillUse; $days_will_use_without_pay = $daysWithoutPermission; - }else if ($monthData['days_requested'] + $remainingDaysInMonthIsUsed > $maxDaysPerMonth) { + } else if ($monthData['days_requested'] + $remainingDaysInMonthIsUsed > $maxDaysPerMonth) { if ($remainingDaysInMonthIsUsed > 0) { $daysWillUse = $maxDaysPerMonth - $remainingDaysInMonthIsUsed; // số ngày phép sẽ sử dụng @@ -627,7 +683,7 @@ class TicketController extends Controller ->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) ->where('ld_year', $year) @@ -640,8 +696,15 @@ class TicketController extends Controller // } else { $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 + } else { Log::warning("No LeaveDays record found for user ID: {$user->id}, year: {$year}. Assuming 0 allocated days."); } @@ -770,8 +833,8 @@ class TicketController extends Controller if ($action == "confirm") { if ($ticket->type == "ONLEAVE") { $dataListPeriod = $this->getAllPeriodNew($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period); - $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod); - // dd($balanceCheckResult,$dataListPeriod); + $balanceCheckResult = $this->checkLeaveBalance($user, $dataListPeriod, null, true); + // dd($balanceCheckResult, $dataListPeriod); if ($balanceCheckResult['success'] == false) { if ($balanceCheckResult['months_info']) { foreach ($balanceCheckResult['months_info'] as $monthInfo) { @@ -889,27 +952,25 @@ class TicketController extends Controller 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 - if ($roundedExcessDays > 0) { - $leaveDaysInfo->ld_day_total += $roundedExcessDays; - $leaveDaysInfo->save(); + $leaveDaysInfo->ld_day_total += $roundedExcessDays; + $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") { $dataListPeriod = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period); foreach ($dataListPeriod as $result) { - list($year, $month, $day) = explode('-', $result['date']); - Notes::create([ - 'n_user_id' => $ticket->user_id, - 'n_day' => $day, - 'n_month' => $month, - 'n_year' => $year, - 'n_time_type' => $result['period'], - 'n_reason' => $ticket->type, - 'n_note' => $ticket->reason - ]); + list($year, $month, $day) = explode('-', $result['date']); + Notes::create([ + 'n_user_id' => $ticket->user_id, + 'n_day' => $day, + 'n_month' => $month, + 'n_year' => $year, + 'n_time_type' => $result['period'], + 'n_reason' => $ticket->type, + 'n_note' => $ticket->reason + ]); //WFH - start tracking -- 2.39.2 From 5b65415d767b33e8641bc35e5a13621eeea5d68b Mon Sep 17 00:00:00 2001 From: Truong Vo <41848815+vmtruong301296@users.noreply.github.com> Date: Mon, 16 Jun 2025 09:41:54 +0700 Subject: [PATCH 3/5] =?UTF-8?q?B=E1=BB=95=20sung=20check=20ticket=20=C4=91?= =?UTF-8?q?ang=20=C4=91=C6=B0=E1=BB=A3c=20duy=E1=BB=87t=20k=20th=E1=BB=83?= =?UTF-8?q?=20t=E1=BA=A1o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/Http/Controllers/TicketController.php | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php index 4f38421..9b4fdd7 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php @@ -238,6 +238,15 @@ 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 $ticketsConfirmed = Ticket::where('user_id', $user->id) ->where('status', 'CONFIRMED') @@ -269,6 +278,7 @@ class TicketController extends Controller // Chuyển đổi mảng đa chiều thành mảng chuỗi để có thể so sánh $periodStrings = []; $waitingPeriodStrings = []; + $waitingPeriodStringsWFH = []; $confirmedPeriodStrings = []; foreach ($dataListPeriod as $period) { @@ -289,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) { if ($period['period'] == 'ALL') { $confirmedPeriodStrings[] = $period['date'] . '_S'; @@ -303,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!'); } + // 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 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!'); @@ -354,6 +378,16 @@ class TicketController extends Controller 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') @@ -405,6 +439,19 @@ class TicketController extends Controller } } + 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!'); -- 2.39.2 From 2c8bb92775e3eb274d0aa68ac09bdb1bd8b7ee0a Mon Sep 17 00:00:00 2001 From: Truong Vo <41848815+vmtruong301296@users.noreply.github.com> Date: Mon, 16 Jun 2025 13:31:15 +0700 Subject: [PATCH 4/5] =?UTF-8?q?B=E1=BB=95=20sung=20check=20ng=C3=A0y=20ph?= =?UTF-8?q?=C3=A9p=20t=E1=BB=91i=20=C4=91a=201=20th=C3=A1ng=20m=E1=BA=B7c?= =?UTF-8?q?=20d=C3=B9=20c=C3=B2n=20nhi=E1=BB=81u=20ph=C3=A9p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/Http/Controllers/TicketController.php | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php index 9b4fdd7..7fd2542 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php @@ -628,15 +628,27 @@ class TicketController extends Controller $days_will_use = 0; $days_will_use_without_pay = $monthData['days_requested']; } else if ($remainingDaysInMonthRemaining < $monthData['days_requested']) { // không đủ ngày phép - $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 đó + if ( + $remainingDaysInMonthRemaining >= $maxDaysPerMonth + ) { + $hasInsufficientDays = true; + $month_data_status = 'exceed_max_days'; + $daysNotEnough = $monthData['days_requested'] - $remainingDaysInMonthRemaining; + $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_without_pay = $daysNotEnough; + $days_will_use = $remainingDaysInMonthRemaining; + $days_will_use_without_pay = $daysNotEnough; + } } else if ( $remainingDaysInMonthRemaining >= $monthData['days_requested'] ) { // Đủ ngày phép ở tháng đó -- 2.39.2 From cd9c01cdeea6879fca4ec2c2174f3359cc383a13 Mon Sep 17 00:00:00 2001 From: Truong Vo <41848815+vmtruong301296@users.noreply.github.com> Date: Mon, 16 Jun 2025 13:34:41 +0700 Subject: [PATCH 5/5] fix --- BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php index 7fd2542..75ea608 100644 --- a/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php +++ b/BACKEND/Modules/Admin/app/Http/Controllers/TicketController.php @@ -633,7 +633,7 @@ class TicketController extends Controller ) { $hasInsufficientDays = true; $month_data_status = 'exceed_max_days'; - $daysNotEnough = $monthData['days_requested'] - $remainingDaysInMonthRemaining; + $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; -- 2.39.2