month = $month ?? Carbon::now()->month; $this->year = $year ?? Carbon::now()->year; } /** * Execute the job. */ public function handle() { $users = User::get(); foreach ($users as $user) { $leaveDay = LeaveDays::where('ld_user_id', $user->id) ->where('ld_year', $this->year) ->first(); $notes = Notes::where('n_reason', 'TEMPORARY_ONLEAVE') ->where('n_user_id', $user->id) ->where('n_year', $this->year) ->where('n_month', $this->month) ->whereExists(function ($query) use ($user) { $query->select(DB::raw(1)) ->from('tickets') ->where('tickets.user_id', $user->id) ->where('tickets.status', 'CONFIRMED') ->where('tickets.type', 'ONLEAVE'); }) ->get(); $maxDaysPerMonth = $this->getMaxLeaveDaysPerMonth(); // Tổng ngày nghỉ sẽ dùng trong tháng $willUsedDaysInMonth = 0; foreach ($notes as $note) { $willUsedDaysInMonth += $note->n_time_type == 'ALL' ? 1.0 : 0.5; } // Tổng phép đang có $onleaveDaysTotal = $leaveDay->ld_day_total + $leaveDay->ld_additional_day + $leaveDay->ld_special_leave_day; // Phép đã sử dụng tới tháng hiện tại $usedOnleaveDaysTotal = Notes::join('categories', function ($join) { $join->on('notes.n_time_type', '=', 'categories.c_code') ->where('categories.c_type', 'TIME_TYPE'); }) ->where('n_user_id', $user->id) ->where('n_year', $this->year) ->where('n_month', "<=", $this->month) ->where('n_reason', 'ONLEAVE') ->sum('categories.c_value'); // Phép còn lại $remainingOnleaveDays = $onleaveDaysTotal - $usedOnleaveDaysTotal; // Log::debug("User {$user->name}\n"); // Log::debug( // "📊 Thống kê ngày phép:\n" . // " - Tháng: {$this->month}\n" . // " - Tổng ngày nghỉ sẽ dùng trong tháng: $willUsedDaysInMonth\n" . // " - Tổng ngày phép: $onleaveDaysTotal\n" . // " - Tổng ngày phép đã nghỉ: $usedOnleaveDaysTotal\n" . // " - Tổng ngày phép còn lại: $remainingOnleaveDays\n" // ); $onleave_days_will_use = 0; // Ngày phép sẽ dùng $nopay_days_will_use = 0; // Ngày ko phép sẽ dùng // Ngày phép còn lại <= 0 (Hết phép) if ($remainingOnleaveDays <= 0) { $onleave_days_will_use = 0; $nopay_days_will_use = $willUsedDaysInMonth; Log::debug("--- Hết phép trong tháng ---"); } // Ngày phép còn lại < ngày yêu cầu (Không đủ phép) else if ($remainingOnleaveDays < $willUsedDaysInMonth) { // Vượt limit if ($willUsedDaysInMonth > $maxDaysPerMonth) { // Phép còn lại > limit if ($remainingOnleaveDays > $maxDaysPerMonth) { $onleave_days_will_use = $maxDaysPerMonth; $nopay_days_will_use = $willUsedDaysInMonth - $maxDaysPerMonth; } // Phép còn lại < limit else { $onleave_days_will_use = $remainingOnleaveDays; $nopay_days_will_use = $willUsedDaysInMonth - $remainingOnleaveDays; } Log::debug("--- Không đủ phép trong tháng, vượt quá limit ---",); } // Không vượt limit else { $onleave_days_will_use = $remainingOnleaveDays; $nopay_days_will_use = $willUsedDaysInMonth - $remainingOnleaveDays; Log::debug("--- Không đủ phép trong tháng, ko vượt limit ---"); } } // Ngày phép còn lại >= ngày yêu cầu (Đủ phép) else { // Vượt limit if ($willUsedDaysInMonth > $maxDaysPerMonth) { $onleave_days_will_use = $maxDaysPerMonth; $nopay_days_will_use = $willUsedDaysInMonth - $maxDaysPerMonth; Log::debug("--- Đủ phép, vượt limit ---"); } // Không vượt limit else { $onleave_days_will_use = $willUsedDaysInMonth; $nopay_days_will_use = 0; Log::debug("--- Đủ phép ---"); } } Log::debug("", [ "Phep" => $onleave_days_will_use, "Khong Phep" => $nopay_days_will_use ]); // Có nghỉ không phép if ($nopay_days_will_use > 0) { foreach ($notes as $note) { $value = ($note->n_time_type === 'ALL') ? 1.0 : 0.5; if ($note->n_time_type === 'ALL' && $onleave_days_will_use == 0.5) { // Chỉ còn 0.5 phép, chia thành 2 bản ghi: 1 phép, 1 không phép // Ưu tiên phép cho buổi sáng (S), không phép cho buổi chiều (C) Notes::create([ 'n_user_id' => $user->id, 'n_day' => $note->n_day, 'n_month' => $note->n_month, 'n_year' => $note->n_year, 'n_time_type' => 'S', 'n_reason' => 'ONLEAVE', 'n_note' => $note->n_note, 'ticket_id' => $note->ticket_id ]); Notes::create([ 'n_user_id' => $user->id, 'n_day' => $note->n_day, 'n_month' => $note->n_month, 'n_year' => $note->n_year, 'n_time_type' => 'C', 'n_reason' => 'LEAVE_WITHOUT_PAY', 'n_note' => $note->n_note, 'ticket_id' => $note->ticket_id ]); $note->delete(); $onleave_days_will_use = 0; $nopay_days_will_use -= 0.5; } elseif ($onleave_days_will_use > 0) { // Dùng ngày phép trước $use = min($onleave_days_will_use, $value); $note->update([ 'n_reason' => "ONLEAVE" ]); $onleave_days_will_use -= $use; } elseif ($nopay_days_will_use > 0) { // Hết phép, chuyển sang không phép $use = min($nopay_days_will_use, $value); $note->update([ 'n_reason' => "LEAVE_WITHOUT_PAY" ]); $nopay_days_will_use -= $use; } } } // Đủ phép else { foreach ($notes as $note) { $note->update([ 'n_reason' => "ONLEAVE" ]); } } } } private function getMaxLeaveDaysPerMonth(): int { $limitLeaveMonth = Category::where('c_type', 'LIMIT_LEAVE_MONTH')->where('c_code', "LIMIT")->first(); if ($limitLeaveMonth) { $maxDaysPerMonth = (int)$limitLeaveMonth->c_value; } else { $maxDaysPerMonth = 3; // default nếu k có setting } return $maxDaysPerMonth; } }