truong-leave-day #116
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -14,7 +14,7 @@ class CategoryController extends Controller
 | 
			
		|||
     * @param Request $request The HTTP request object.
 | 
			
		||||
     * @return \Illuminate\Http\JsonResponse The JSON response containing the list of master data.
 | 
			
		||||
     */
 | 
			
		||||
    public function getListMaster(Request $request)
 | 
			
		||||
    public static function getListMaster(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $data = Category::where('c_type', '=', $request->type)->where('c_active', '=', 1)->select('id', 'c_code', 'c_name', 'c_value', 'c_type')->get();
 | 
			
		||||
        return AbstractController::ResultSuccess($data);
 | 
			
		||||
| 
						 | 
				
			
			@ -24,4 +24,9 @@ class CategoryController extends Controller
 | 
			
		|||
        $data = Category::where('c_type', '=', $type)->where('c_code', '=', $code)->where('c_active', '=', 1)->select('id', 'c_code', 'c_name', 'c_value', 'c_type')->first();
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
    public static function getListMasterByType($type)
 | 
			
		||||
    {
 | 
			
		||||
        $data = Category::where('c_type', '=', $type)->where('c_active', '=', 1)->select('id', 'c_code', 'c_name', 'c_value', 'c_type')->get();
 | 
			
		||||
        return $data;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ class LeaveManagementController extends Controller
 | 
			
		|||
        })
 | 
			
		||||
            ->leftJoin("categories as reason", function ($join) {
 | 
			
		||||
                $join->on('n_reason', '=', 'reason.c_code');
 | 
			
		||||
                $join->on('reason.c_type', DB::raw("CONCAT('REASON')"));
 | 
			
		||||
                $join->on('reason.c_type', DB::raw("CONCAT('REASON_NOTES')"));
 | 
			
		||||
            })
 | 
			
		||||
            ->select(
 | 
			
		||||
                DB::raw('notes.n_user_id as n_user_id'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,7 +105,6 @@ class TicketController extends Controller
 | 
			
		|||
                ->paginate($request->get('per_page'))->toArray(),
 | 
			
		||||
            ['status' => true]
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return response()->json($responseData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +227,7 @@ class TicketController extends Controller
 | 
			
		|||
            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 đ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')
 | 
			
		||||
                ->get();
 | 
			
		||||
            $dataListPeriodWaiting = [];
 | 
			
		||||
| 
						 | 
				
			
			@ -238,9 +237,9 @@ class TicketController extends Controller
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Lấy thông tin tickets đ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')
 | 
			
		||||
                ->whereIn('type', ['ONLEAVE', 'LEAVE_WITHOUT_PAY'])
 | 
			
		||||
                ->whereIn('type', ['ONLEAVE'])
 | 
			
		||||
                ->where(DB::raw('DATE(start_date)'), '>=', $start_date->toDateString())
 | 
			
		||||
                ->where(DB::raw('DATE(end_date)'), '<=', $end_date->toDateString())
 | 
			
		||||
                ->get();
 | 
			
		||||
| 
						 | 
				
			
			@ -288,7 +287,7 @@ class TicketController extends Controller
 | 
			
		|||
            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!');
 | 
			
		||||
| 
						 | 
				
			
			@ -298,7 +297,6 @@ class TicketController extends Controller
 | 
			
		|||
            $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
 | 
			
		||||
| 
						 | 
				
			
			@ -466,8 +464,12 @@ class TicketController extends Controller
 | 
			
		|||
            $usedDaysInMonthWithoutPay = $this->getUsedLeaveDaysInMonth($user, $monthData['year'], $monthData['month'], 'LEAVE_WITHOUT_PAY');
 | 
			
		||||
 | 
			
		||||
            // Tính tổng giới hạn ngày nghỉ có phép tối đa trong tháng
 | 
			
		||||
 | 
			
		||||
            $maxDaysPerMonth = $this->getMaxLeaveDaysPerMonth();
 | 
			
		||||
 | 
			
		||||
            $days_will_use = 0;
 | 
			
		||||
            $days_will_use_without_pay = 0;
 | 
			
		||||
 | 
			
		||||
            // Tính tổng số ngày nghỉ trong tháng
 | 
			
		||||
            $totalDaysInMonth = $usedDaysInMonth + $usedDaysInMonthWithoutPay + $monthData['days_requested'];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -487,14 +489,19 @@ class TicketController extends Controller
 | 
			
		|||
                $month_data['status'] = 'no_days_left';
 | 
			
		||||
                $monthMessage = "* Hiện tại bạn đã hết phép nghỉ trong tháng {$monthData['month']}/{$monthData['year']}\n - Bạn sẽ nộp: " . $monthData['days_requested'] . " ngày không phép.";
 | 
			
		||||
                $errorMessage .= $errorMessage ? "\n\n" . $monthMessage : $monthMessage;
 | 
			
		||||
 | 
			
		||||
                $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 đó
 | 
			
		||||
 | 
			
		||||
                $days_will_use = $remainingDaysInMonthRemaining;
 | 
			
		||||
                $days_will_use_without_pay = $daysNotEnough;
 | 
			
		||||
            } 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
 | 
			
		||||
| 
						 | 
				
			
			@ -504,20 +511,31 @@ class TicketController extends Controller
 | 
			
		|||
                    $daysWithoutPermission = $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 - 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;
 | 
			
		||||
 | 
			
		||||
                    $days_will_use = $maxDaysPerMonth;
 | 
			
		||||
                    $days_will_use_without_pay = $daysWithoutPermission;
 | 
			
		||||
                } else {
 | 
			
		||||
                    $days_will_use = $monthData['days_requested'];
 | 
			
		||||
                    $days_will_use_without_pay = 0;
 | 
			
		||||
                }
 | 
			
		||||
                $remainingDaysInMonthRemaining = $monthData['days_requested'];
 | 
			
		||||
            } else {
 | 
			
		||||
                $days_will_use = $monthData['days_requested'];
 | 
			
		||||
                $days_will_use_without_pay = 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $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
 | 
			
		||||
                'total_leave_days_in_month_to_month' => $totalLeaveDaysInMonthToMonth, //tổng ngày nghỉ có phép đã nghỉ
 | 
			
		||||
                'remaining_days_in_month' => $remainingDaysInMonth, //số ngày phép còn lại
 | 
			
		||||
                'days_used' => $usedDaysInMonth, //tổng số ngày nghỉ có phép đã nghỉ ở tháng hiện tại
 | 
			
		||||
                'days_used_without_pay' => $usedDaysInMonthWithoutPay, //tổng số ngày nghỉ không phép đã nghỉ ở 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,
 | 
			
		||||
                'days_will_use' => $days_will_use, //Số ngày phép sẽ sử dụng
 | 
			
		||||
                'days_will_use_without_pay' => $days_will_use_without_pay, //Số ngày không phép sẽ sử dụng
 | 
			
		||||
                'status' => 'ok', // mặc định là ok
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -660,18 +678,12 @@ class TicketController extends Controller
 | 
			
		|||
        if (!$ticket || $ticket->status !== "WAITING") {
 | 
			
		||||
            return response()->json(['message' => "Ticket not found", 'status' => false]);
 | 
			
		||||
        }
 | 
			
		||||
        $results = $this->getAllPeriod($ticket->start_date, $ticket->start_period, $ticket->end_date, $ticket->end_period);
 | 
			
		||||
 | 
			
		||||
        // $admin->id != user_id of ticket ---> continue
 | 
			
		||||
        // Confirm
 | 
			
		||||
        // Add records to the notes table like function Timekeeping.addNoteForUser() based on the $results array
 | 
			
		||||
 | 
			
		||||
        // Update updated_by and admin_note in tickets table
 | 
			
		||||
        // Refuse
 | 
			
		||||
        // Update updated_by and admin_note in tickets table
 | 
			
		||||
 | 
			
		||||
        // Send notification email to users
 | 
			
		||||
 | 
			
		||||
        // Refuse
 | 
			
		||||
        // Update updated_by and admin_note in tickets table
 | 
			
		||||
        $startDate = $ticket->start_date; //Start day
 | 
			
		||||
        $startPeriod = $ticket->start_period; //The session begins
 | 
			
		||||
        $endDate = $ticket->end_date; //End date
 | 
			
		||||
| 
						 | 
				
			
			@ -682,25 +694,171 @@ class TicketController extends Controller
 | 
			
		|||
        $dataMasterEndPeriod = CategoryController::getListMasterByCodeAndType("TIME_TYPE", $endPeriod);
 | 
			
		||||
        $dataMasterType = CategoryController::getListMasterByCodeAndType("REASON", $type);
 | 
			
		||||
 | 
			
		||||
        $dataMasterTypeNotes = CategoryController::getListMasterByType("REASON_NOTES");
 | 
			
		||||
        $onleave = null;
 | 
			
		||||
        $leaveWithoutPay = null;
 | 
			
		||||
 | 
			
		||||
        if ($dataMasterTypeNotes) {
 | 
			
		||||
            // get nghỉ phép, nghỉ không phép
 | 
			
		||||
            $onleave = optional($dataMasterTypeNotes->where('c_code', 'ONLEAVE')->first())->c_code;
 | 
			
		||||
            $leaveWithoutPay = optional($dataMasterTypeNotes->where('c_code', 'LEAVE_WITHOUT_PAY')->first())->c_code;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $formattedStartDate = Carbon::createFromFormat('Y-m-d', $startDate)->format('d/m/Y');
 | 
			
		||||
        $formattedEndDate = Carbon::createFromFormat('Y-m-d', $endDate)->format('d/m/Y');
 | 
			
		||||
 | 
			
		||||
        $user = Admin::find($ticket->user_id);
 | 
			
		||||
 | 
			
		||||
        if ($action == "confirm") {
 | 
			
		||||
            foreach ($results 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
 | 
			
		||||
                ]);
 | 
			
		||||
        if ($onleave == null || $leaveWithoutPay == null) {
 | 
			
		||||
            return response()->json(['message' => "Data reason notes not found", 'status' => false]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
                if ($ticket->type == "WFH") {
 | 
			
		||||
        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);
 | 
			
		||||
                if ($balanceCheckResult['success'] == false) {
 | 
			
		||||
                    if ($balanceCheckResult['months_info']) {
 | 
			
		||||
                        foreach ($balanceCheckResult['months_info'] as $monthInfo) {
 | 
			
		||||
                            // Lọc các ngày thuộc đúng tháng/năm này
 | 
			
		||||
                            $daysInMonth = array_filter($dataListPeriod, function ($item) use ($monthInfo) {
 | 
			
		||||
                                $date = \Carbon\Carbon::parse($item['date']);
 | 
			
		||||
                                return $date->year == $monthInfo['year'] && $date->month == $monthInfo['month'];
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
                            $daysWillUse = $monthInfo['days_will_use'] ?? 0;
 | 
			
		||||
                            $daysWillUseWithoutPay = $monthInfo['days_will_use_without_pay'] ?? 0;
 | 
			
		||||
                            // dd($daysWillUse,$daysWillUseWithoutPay,$daysInMonth);
 | 
			
		||||
                            foreach ($daysInMonth as $item) {
 | 
			
		||||
                                list($year, $month, $day) = explode('-', $item['date']);
 | 
			
		||||
                                $period = $item['period'];
 | 
			
		||||
                                $value = ($period === 'ALL') ? 1.0 : 0.5;
 | 
			
		||||
 | 
			
		||||
                                if ($period === 'ALL' && $daysWillUse == 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' => $ticket->user_id,
 | 
			
		||||
                                        'n_day' => $day,
 | 
			
		||||
                                        'n_month' => $month,
 | 
			
		||||
                                        'n_year' => $year,
 | 
			
		||||
                                        'n_time_type' => 'S',
 | 
			
		||||
                                        'n_reason' => $onleave,
 | 
			
		||||
                                        'n_note' => $ticket->reason
 | 
			
		||||
                                    ]);
 | 
			
		||||
                                    Notes::create([
 | 
			
		||||
                                        'n_user_id' => $ticket->user_id,
 | 
			
		||||
                                        'n_day' => $day,
 | 
			
		||||
                                        'n_month' => $month,
 | 
			
		||||
                                        'n_year' => $year,
 | 
			
		||||
                                        'n_time_type' => 'C',
 | 
			
		||||
                                        'n_reason' => $leaveWithoutPay,
 | 
			
		||||
                                        'n_note' => $ticket->reason
 | 
			
		||||
                                    ]);
 | 
			
		||||
                                    $daysWillUse = 0;
 | 
			
		||||
                                    $daysWillUseWithoutPay -= 0.5;
 | 
			
		||||
                                } elseif ($daysWillUse > 0) {
 | 
			
		||||
                                    // Dùng ngày phép trước
 | 
			
		||||
                                    $use = min($daysWillUse, $value);
 | 
			
		||||
                                    Notes::create([
 | 
			
		||||
                                        'n_user_id' => $ticket->user_id,
 | 
			
		||||
                                        'n_day' => $day,
 | 
			
		||||
                                        'n_month' => $month,
 | 
			
		||||
                                        'n_year' => $year,
 | 
			
		||||
                                        'n_time_type' => $period,
 | 
			
		||||
                                        'n_reason' => $onleave,
 | 
			
		||||
                                        'n_note' => $ticket->reason
 | 
			
		||||
                                    ]);
 | 
			
		||||
                                    $daysWillUse -= $use;
 | 
			
		||||
                                } elseif ($daysWillUseWithoutPay > 0) {
 | 
			
		||||
                                    // Hết phép, chuyển sang không phép
 | 
			
		||||
                                    $use = min($daysWillUseWithoutPay, $value);
 | 
			
		||||
                                    Notes::create([
 | 
			
		||||
                                        'n_user_id' => $ticket->user_id,
 | 
			
		||||
                                        'n_day' => $day,
 | 
			
		||||
                                        'n_month' => $month,
 | 
			
		||||
                                        'n_year' => $year,
 | 
			
		||||
                                        'n_time_type' => $period,
 | 
			
		||||
                                        'n_reason' => $leaveWithoutPay,
 | 
			
		||||
                                        'n_note' => $ticket->reason
 | 
			
		||||
                                    ]);
 | 
			
		||||
                                    $daysWillUseWithoutPay -= $use;
 | 
			
		||||
                                }
 | 
			
		||||
                                // Nếu cả hai đều hết thì thôi, không tạo nữa
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    //Đủ phép
 | 
			
		||||
                    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' => $onleave, // có phép
 | 
			
		||||
                            'n_note' => $ticket->reason
 | 
			
		||||
                        ]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $yearCheck = Carbon::parse($endDate)->year;
 | 
			
		||||
                // Check giá trị ld_day_total của bảng leave_days thuộc user id đó với giá trị của list item note trong bảng notes của user id đó
 | 
			
		||||
                $leaveDaysInfo = LeaveDays::where('ld_user_id', $ticket->user_id)
 | 
			
		||||
                    ->where('ld_year', $yearCheck)
 | 
			
		||||
                    ->first();
 | 
			
		||||
                if ($leaveDaysInfo) {
 | 
			
		||||
                    // Tính tổng số ngày nghỉ có phép đã sử dụng trong năm
 | 
			
		||||
                    $totalUsedLeaveDays = Notes::join('categories', function ($join) {
 | 
			
		||||
                        $join->on('notes.n_time_type', '=', 'categories.c_code')
 | 
			
		||||
                            ->where('categories.c_type', 'TIME_TYPE');
 | 
			
		||||
                    })
 | 
			
		||||
                        ->where('n_user_id', $ticket->user_id)
 | 
			
		||||
                        ->where('n_year', $yearCheck)
 | 
			
		||||
                        ->where('n_reason', 'ONLEAVE')
 | 
			
		||||
                        ->sum('categories.c_value');
 | 
			
		||||
 | 
			
		||||
                    // Tính tổng số ngày phép được cấp
 | 
			
		||||
                    $totalAllocatedDays = $leaveDaysInfo->ld_day_total +
 | 
			
		||||
                        $leaveDaysInfo->ld_additional_day +
 | 
			
		||||
                        $leaveDaysInfo->ld_special_leave_day;
 | 
			
		||||
 | 
			
		||||
                    // Tính số ngày vượt quá và làm tròn lên
 | 
			
		||||
                    $excessDays = $totalUsedLeaveDays - $totalAllocatedDays;
 | 
			
		||||
                    $roundedExcessDays = ceil($excessDays); // Làm tròn lên số nguyên gần nhất
 | 
			
		||||
 | 
			
		||||
                    // Kiểm tra nếu số ngày đã sử dụng vượt quá số ngày được cấp
 | 
			
		||||
                    if ($roundedExcessDays > 0) {
 | 
			
		||||
                        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();
 | 
			
		||||
 | 
			
		||||
                            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
 | 
			
		||||
                    ]);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    //WFH - start tracking
 | 
			
		||||
                    $type =  $result['period'];
 | 
			
		||||
                    $date = Carbon::create($year, $month, $day)->setTimezone(env('TIME_ZONE'));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -730,6 +888,7 @@ class TicketController extends Controller
 | 
			
		|||
                            'created_at' => $end->setTimezone('UTC')
 | 
			
		||||
                        ]
 | 
			
		||||
                    ]);
 | 
			
		||||
                    //WFH - end tracking
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -814,6 +973,13 @@ class TicketController extends Controller
 | 
			
		|||
                // Parse the date string from c_code to a Carbon instance for proper comparison
 | 
			
		||||
                return Carbon::createFromFormat('d-m-Y', $item->c_code);
 | 
			
		||||
            });
 | 
			
		||||
        // get day work special
 | 
			
		||||
        $day_work_special = Category::where('c_type', 'DAY_WORK_SPECIAL')
 | 
			
		||||
            ->get()
 | 
			
		||||
            ->sortByDesc(function ($item) {
 | 
			
		||||
                return Carbon::createFromFormat('d-m-Y', $item->c_code);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Get the most recent schedule date (first item after sorting)
 | 
			
		||||
        $latest_schedule = $saturday_work_schedules->first();
 | 
			
		||||
| 
						 | 
				
			
			@ -825,26 +991,33 @@ class TicketController extends Controller
 | 
			
		|||
            return []; // Return empty or throw exception
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $special_dates = [];
 | 
			
		||||
        foreach ($day_work_special as $item) {
 | 
			
		||||
            $special_dates[] = Carbon::createFromFormat('d-m-Y', $item->c_code)->toDateString();
 | 
			
		||||
        }
 | 
			
		||||
        foreach ($period as $date) {
 | 
			
		||||
            // Check if the current day is a Saturday
 | 
			
		||||
            if ($date->dayOfWeek === Carbon::SATURDAY) {
 | 
			
		||||
            // Check phải ngày thứ 7 đặc biệt thì tính như ngày bình thường
 | 
			
		||||
            if (in_array($date->toDateString(), $special_dates)) {
 | 
			
		||||
            } else {
 | 
			
		||||
                // Check if the current day is a Saturday
 | 
			
		||||
                if ($date->dayOfWeek === Carbon::SATURDAY) {
 | 
			
		||||
                    if ($latest_schedule) {
 | 
			
		||||
                        $weeksDifference = $latestScheduleDate->startOfDay()->diffInWeeks($date->copy()->startOfDay());
 | 
			
		||||
                        $isSaturdayWorkDay = ($weeksDifference % 2 === 0);
 | 
			
		||||
 | 
			
		||||
                if ($latest_schedule) {
 | 
			
		||||
                    $weeksDifference = $latestScheduleDate->startOfDay()->diffInWeeks($date->copy()->startOfDay());
 | 
			
		||||
                    $isSaturdayWorkDay = ($weeksDifference % 2 === 0);
 | 
			
		||||
                        // echo $date->toDateString() . ' - ' . ($isSaturdayWorkDay ? 'Làm việc' : 'Nghỉ') . "<br>";
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // echo $date->toDateString() . ' - ' . ($isSaturdayWorkDay ? 'Làm việc' : 'Nghỉ') . "<br>";
 | 
			
		||||
                    if ($isSaturdayWorkDay) {
 | 
			
		||||
                        $results[] = ['date' => $date->toDateString(), 'period' => "S"];
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if ($isSaturdayWorkDay) {
 | 
			
		||||
                    $results[] = ['date' => $date->toDateString(), 'period' => "S"];
 | 
			
		||||
                // Skip Sundays entirely
 | 
			
		||||
                else if ($date->dayOfWeek === Carbon::SUNDAY) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            // Skip Sundays entirely
 | 
			
		||||
            else if ($date->dayOfWeek === Carbon::SUNDAY) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($date->isSameDay($startDate)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -152,8 +152,6 @@ class TimekeepingController extends Controller
 | 
			
		|||
        return response()->json(['status' => true, 'message' => 'Add successfully']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function updateCacheMonth(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        $month = $request->month;
 | 
			
		||||
| 
						 | 
				
			
			@ -180,6 +178,71 @@ class TimekeepingController extends Controller
 | 
			
		|||
 | 
			
		||||
        $note = Notes::find($id);
 | 
			
		||||
        if ($note) {
 | 
			
		||||
            $n_month = $note->n_month;
 | 
			
		||||
            $n_year = $note->n_year;
 | 
			
		||||
 | 
			
		||||
            if ($note->n_reason == "ONLEAVE") {
 | 
			
		||||
                // Get note reason ONLEAVE by $n_month, $n_year not include $note->id & include $note->n_user_id
 | 
			
		||||
                // $onleave = Notes::getNotesByMonthAndYearAndUserId($n_month, $n_year, $note->n_user_id, $note->id);
 | 
			
		||||
 | 
			
		||||
                // Get note reason LEAVE_WITHOUT_PAY by $n_month, $n_year & include $note->n_user_id
 | 
			
		||||
                $leaveWithoutPay = Notes::getNotesByMonthAndYearAndUserIdAndReason($n_month, $n_year, $note->n_user_id, 'LEAVE_WITHOUT_PAY');
 | 
			
		||||
 | 
			
		||||
                if (count($leaveWithoutPay) > 0) {
 | 
			
		||||
                    $deletedValue = ($note->n_time_type === 'ALL') ? 1.0 : 0.5;
 | 
			
		||||
                    $needUpdate = $deletedValue;
 | 
			
		||||
                    // dd($needUpdate, $leaveWithoutPay);
 | 
			
		||||
                    foreach ($leaveWithoutPay as $lwNote) {
 | 
			
		||||
                        if ($needUpdate <= 0) break;
 | 
			
		||||
 | 
			
		||||
                        if ($lwNote->n_time_type === 'ALL') {
 | 
			
		||||
                            if ($needUpdate == 1.0) {
 | 
			
		||||
                                // Chuyển cả note ALL thành phép
 | 
			
		||||
                                $lwNote->update(['n_reason' => 'ONLEAVE']);
 | 
			
		||||
                                $needUpdate = 0;
 | 
			
		||||
                                break;
 | 
			
		||||
                            } else { // $needUpdate == 0.5
 | 
			
		||||
                                // Tách ALL thành 2 note S và C, chuyển S thành phép, C giữ không phép
 | 
			
		||||
                                Notes::create([
 | 
			
		||||
                                    'n_user_id' => $lwNote->n_user_id,
 | 
			
		||||
                                    'n_day' => $lwNote->n_day,
 | 
			
		||||
                                    'n_month' => $lwNote->n_month,
 | 
			
		||||
                                    'n_year' => $lwNote->n_year,
 | 
			
		||||
                                    'n_time_type' => 'S',
 | 
			
		||||
                                    'n_reason' => 'ONLEAVE',
 | 
			
		||||
                                    'n_note' => $lwNote->n_note
 | 
			
		||||
                                ]);
 | 
			
		||||
                                Notes::create([
 | 
			
		||||
                                    'n_user_id' => $lwNote->n_user_id,
 | 
			
		||||
                                    'n_day' => $lwNote->n_day,
 | 
			
		||||
                                    'n_month' => $lwNote->n_month,
 | 
			
		||||
                                    'n_year' => $lwNote->n_year,
 | 
			
		||||
                                    'n_time_type' => 'C',
 | 
			
		||||
                                    'n_reason' => 'LEAVE_WITHOUT_PAY',
 | 
			
		||||
                                    'n_note' => $lwNote->n_note
 | 
			
		||||
                                ]);
 | 
			
		||||
                                $lwNote->delete();
 | 
			
		||||
                                $needUpdate = 0;
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            // Nếu $lwNote->n_time_type == 'S' hoặc 'C' => 0.5
 | 
			
		||||
                            if ($needUpdate == 1.0) {
 | 
			
		||||
                                // Chuyển cả note ALL thành phép
 | 
			
		||||
                                $lwNote->update(['n_reason' => 'ONLEAVE']);
 | 
			
		||||
                                $needUpdate -= 0.5;
 | 
			
		||||
                            } else { // $needUpdate == 0.5
 | 
			
		||||
                                // S hoặc C, chỉ cần chuyển đúng 0.5 ngày
 | 
			
		||||
                                $lwNote->update(['n_reason' => 'ONLEAVE']);
 | 
			
		||||
                                $needUpdate = 0;
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Khi note phép và k tồn tại nghỉ không phép => phép + dồn cho tháng sau
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $note->delete();
 | 
			
		||||
            $this->createOrUpdateRecordForCurrentMonth($month, $year);
 | 
			
		||||
            return response()->json(['message' => 'Delete success', 'status' => true]);
 | 
			
		||||
| 
						 | 
				
			
			@ -206,10 +269,10 @@ class TimekeepingController extends Controller
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // Lọc chỉ lấy user có permission bao gồm staff
 | 
			
		||||
        $staffData = array_filter($responseData['data'], function($user) {
 | 
			
		||||
        $staffData = array_filter($responseData['data'], function ($user) {
 | 
			
		||||
            return isset($user['user']['permission']) && strpos($user['user']['permission'], 'staff') !== false;
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        $currentDate = date('d_His');
 | 
			
		||||
        return Excel::download(
 | 
			
		||||
            new TimekeepingExport(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,13 @@ class Notes extends Model
 | 
			
		|||
    use HasFactory;
 | 
			
		||||
 | 
			
		||||
    protected $fillable = [
 | 
			
		||||
        'n_user_id', 'n_day', 'n_month', 'n_year', 'n_time_type', 'n_reason', 'n_note',
 | 
			
		||||
        'n_user_id',
 | 
			
		||||
        'n_day',
 | 
			
		||||
        'n_month',
 | 
			
		||||
        'n_year',
 | 
			
		||||
        'n_time_type',
 | 
			
		||||
        'n_reason',
 | 
			
		||||
        'n_note',
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +31,7 @@ class Notes extends Model
 | 
			
		|||
    {
 | 
			
		||||
        return self::leftJoin("categories as reason", function ($join) {
 | 
			
		||||
            $join->on('n_reason', '=', 'reason.c_code');
 | 
			
		||||
            $join->on('reason.c_type', DB::raw("CONCAT('REASON')"));
 | 
			
		||||
            $join->on('reason.c_type', DB::raw("CONCAT('REASON_NOTES')"));
 | 
			
		||||
        })
 | 
			
		||||
            ->leftJoin("categories as timeTypes", function ($join) {
 | 
			
		||||
                $join->on('n_time_type', '=', 'timeTypes.c_code');
 | 
			
		||||
| 
						 | 
				
			
			@ -47,4 +53,18 @@ class Notes extends Model
 | 
			
		|||
            )
 | 
			
		||||
            ->get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function getNotesByMonthAndYearAndUserId($month, $year, $userId, $idNote)
 | 
			
		||||
    {
 | 
			
		||||
        return self::where('n_reason', 'ONLEAVE')->where('n_month', $month)->where('n_year', $year)
 | 
			
		||||
            ->where('n_user_id', $userId)
 | 
			
		||||
            ->where('id', '!=', $idNote)->get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function getNotesByMonthAndYearAndUserIdAndReason($month, $year, $userId, $reason)
 | 
			
		||||
    {
 | 
			
		||||
        return self::where('n_reason', $reason)->where('n_month', $month)->where('n_year', $year)
 | 
			
		||||
            ->where('n_user_id', $userId)
 | 
			
		||||
            ->orderBy('n_day', 'asc')->orderBy('n_time_type', 'desc')->get();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Migrations\Migration;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
 | 
			
		||||
class UpdateLeaveCategories extends Migration
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function up()
 | 
			
		||||
    {
 | 
			
		||||
        // Xóa item với type REASON và code LEAVE_WITHOUT_PAY
 | 
			
		||||
        DB::table('categories')
 | 
			
		||||
            ->where('c_type', 'REASON')
 | 
			
		||||
            ->where('c_code', 'LEAVE_WITHOUT_PAY')
 | 
			
		||||
            ->delete();
 | 
			
		||||
 | 
			
		||||
        // Cập nhật tên "Nghỉ phép năm" thành "Nghỉ phép"
 | 
			
		||||
        DB::table('categories')
 | 
			
		||||
            ->where('c_name', 'Nghỉ phép năm')
 | 
			
		||||
            ->update(['c_name' => 'Nghỉ phép']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function down()
 | 
			
		||||
    {
 | 
			
		||||
        // Khôi phục item đã xóa
 | 
			
		||||
        DB::table('categories')->insert([
 | 
			
		||||
            'c_code' => 'LEAVE_WITHOUT_PAY',
 | 
			
		||||
            'c_name' => 'Không phép',
 | 
			
		||||
            'c_type' => 'REASON',
 | 
			
		||||
            'c_value' => "",
 | 
			
		||||
            'c_active' => 1,
 | 
			
		||||
            'created_at' => now(),
 | 
			
		||||
            'updated_at' => now(),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        // Khôi phục tên cũ
 | 
			
		||||
        DB::table('categories')
 | 
			
		||||
            ->where('c_name', 'Nghỉ phép')
 | 
			
		||||
            ->update(['c_name' => 'Nghỉ phép năm']);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Migrations\Migration;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
 | 
			
		||||
class AddLimitLeaveMonthCategory extends Migration
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function up()
 | 
			
		||||
    {
 | 
			
		||||
        DB::table('categories')->insert([
 | 
			
		||||
            'c_code' => 'LIMIT',
 | 
			
		||||
            'c_name' => 'Giới hạn số ngày nghỉ có phép/tháng',
 | 
			
		||||
            'c_type' => 'LIMIT_LEAVE_MONTH',
 | 
			
		||||
            'c_value' => '3',
 | 
			
		||||
            'c_active' => 1,
 | 
			
		||||
            'created_at' => now(),
 | 
			
		||||
            'updated_at' => now(),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function down()
 | 
			
		||||
    {
 | 
			
		||||
        DB::table('categories')
 | 
			
		||||
            ->where('c_code', 'LIMIT')
 | 
			
		||||
            ->where('c_type', 'LIMIT_LEAVE_MONTH')
 | 
			
		||||
            ->delete();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Migrations\Migration;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
 | 
			
		||||
class AddSaturdayWorkScheduleCategory extends Migration
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function up()
 | 
			
		||||
    {
 | 
			
		||||
        DB::table('categories')->insert([
 | 
			
		||||
            'c_code' => '10-05-2025',
 | 
			
		||||
            'c_name' => 'Ngày bắt đầu làm việc thứ 7 trong năm',
 | 
			
		||||
            'c_type' => 'SATURDAY_WORK_SCHEDULE',
 | 
			
		||||
            'c_value' => '2025',
 | 
			
		||||
            'c_active' => 1,
 | 
			
		||||
            'created_at' => now(),
 | 
			
		||||
            'updated_at' => now(),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function down()
 | 
			
		||||
    {
 | 
			
		||||
        DB::table('categories')
 | 
			
		||||
            ->where('c_code', '10-05-2025')
 | 
			
		||||
            ->where('c_type', 'SATURDAY_WORK_SCHEDULE')
 | 
			
		||||
            ->delete();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Migrations\Migration;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
use Illuminate\Support\Facades\DB;
 | 
			
		||||
 | 
			
		||||
class AddLeaveCategories extends Migration
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function up()
 | 
			
		||||
    {
 | 
			
		||||
        DB::table('categories')->insert([
 | 
			
		||||
            [
 | 
			
		||||
                'c_code' => 'LEAVE_WITHOUT_PAY',
 | 
			
		||||
                'c_name' => 'Không phép',
 | 
			
		||||
                'c_type' => 'REASON_NOTES',
 | 
			
		||||
                'c_value' => "",
 | 
			
		||||
                'c_active' => 1,
 | 
			
		||||
                'created_at' => now(),
 | 
			
		||||
                'updated_at' => now(),
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
                'c_code' => 'WFH',
 | 
			
		||||
                'c_name' => 'Work From Home',
 | 
			
		||||
                'c_type' => 'REASON_NOTES',
 | 
			
		||||
                'c_value' => "",
 | 
			
		||||
                'c_active' => 1,
 | 
			
		||||
                'created_at' => now(),
 | 
			
		||||
                'updated_at' => now(),
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
                'c_code' => 'ONLEAVE',
 | 
			
		||||
                'c_name' => 'Nghỉ phép',
 | 
			
		||||
                'c_type' => 'REASON_NOTES',
 | 
			
		||||
                'c_value' => "",
 | 
			
		||||
                'c_active' => 1,
 | 
			
		||||
                'created_at' => now(),
 | 
			
		||||
                'updated_at' => now(),
 | 
			
		||||
            ],
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function down()
 | 
			
		||||
    {
 | 
			
		||||
        DB::table('categories')
 | 
			
		||||
            ->whereIn('c_code', ['LEAVE_WITHOUT_PAY', 'WFH', 'ONLEAVE'])
 | 
			
		||||
            ->where('c_type', 'REASON_NOTES')
 | 
			
		||||
            ->delete();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +114,10 @@ const LeaveManagement = () => {
 | 
			
		|||
  const [dataTimeType, setDataTimeType] = useState<DataTimeType[]>([])
 | 
			
		||||
  const [dataReason, setDataReason] = useState<DataReason[]>([])
 | 
			
		||||
 | 
			
		||||
  const now = new Date()
 | 
			
		||||
  const currentMonth = now.getMonth() + 1 // getMonth() trả về 0-11
 | 
			
		||||
  const currentYear = now.getFullYear()
 | 
			
		||||
 | 
			
		||||
  const getListMasterByType = async (type: string) => {
 | 
			
		||||
    try {
 | 
			
		||||
      const params = {
 | 
			
		||||
| 
						 | 
				
			
			@ -361,8 +365,8 @@ const LeaveManagement = () => {
 | 
			
		|||
              })
 | 
			
		||||
            }
 | 
			
		||||
          }}
 | 
			
		||||
          label={'Total Leave'}
 | 
			
		||||
          placeholder="Input total leave days"
 | 
			
		||||
          label={'Phép năm'}
 | 
			
		||||
          placeholder="Nhập số ngày phép năm"
 | 
			
		||||
        />
 | 
			
		||||
        <TextInput
 | 
			
		||||
          mb={'md'}
 | 
			
		||||
| 
						 | 
				
			
			@ -388,8 +392,8 @@ const LeaveManagement = () => {
 | 
			
		|||
              })
 | 
			
		||||
            }
 | 
			
		||||
          }}
 | 
			
		||||
          label={'Day additional leave'}
 | 
			
		||||
          placeholder="Input additional leave days"
 | 
			
		||||
          label={'Phép năm cũ'}
 | 
			
		||||
          placeholder="Nhập số ngày phép năm cũ"
 | 
			
		||||
        />
 | 
			
		||||
        <TextInput
 | 
			
		||||
          mb={'md'}
 | 
			
		||||
| 
						 | 
				
			
			@ -415,8 +419,8 @@ const LeaveManagement = () => {
 | 
			
		|||
              })
 | 
			
		||||
            }
 | 
			
		||||
          }}
 | 
			
		||||
          label={'Day special leave'}
 | 
			
		||||
          placeholder="Input special leave days"
 | 
			
		||||
          label={'Phép đặc biệt'}
 | 
			
		||||
          placeholder="Nhập số ngày phép đặc biệt"
 | 
			
		||||
        />
 | 
			
		||||
        <Textarea
 | 
			
		||||
          mb={'md'}
 | 
			
		||||
| 
						 | 
				
			
			@ -525,12 +529,20 @@ const LeaveManagement = () => {
 | 
			
		|||
              <Table.Th ta={'center'} style={{ width: '40px' }}></Table.Th>
 | 
			
		||||
              <Table.Th>User</Table.Th>
 | 
			
		||||
              {monthInYear.map((d) => {
 | 
			
		||||
                const isCurrentMonth =
 | 
			
		||||
                  Number(date.year) === currentYear && d.value === currentMonth
 | 
			
		||||
                return (
 | 
			
		||||
                  <Menu width={200} shadow="md" key={d.value}>
 | 
			
		||||
                    <Menu.Target>
 | 
			
		||||
                      <Table.Th
 | 
			
		||||
                        ta={'center'}
 | 
			
		||||
                        style={{ cursor: 'pointer', width: '40px' }}
 | 
			
		||||
                        style={{
 | 
			
		||||
                          cursor: 'pointer',
 | 
			
		||||
                          width: '40px',
 | 
			
		||||
                          backgroundColor: isCurrentMonth ? '#ffe066' : undefined,
 | 
			
		||||
                          color: isCurrentMonth ? '#000' : undefined,
 | 
			
		||||
                          fontWeight: isCurrentMonth ? 'bold' : undefined,
 | 
			
		||||
                        }}
 | 
			
		||||
                      >
 | 
			
		||||
                        <span>{d.name}</span>
 | 
			
		||||
                      </Table.Th>
 | 
			
		||||
| 
						 | 
				
			
			@ -590,6 +602,8 @@ const LeaveManagement = () => {
 | 
			
		|||
                  </Table.Td>
 | 
			
		||||
 | 
			
		||||
                  {monthInYear.map((d, i) => {
 | 
			
		||||
                    const isCurrentMonth =
 | 
			
		||||
                      Number(date.year) === currentYear && d.value === currentMonth
 | 
			
		||||
                    let leaveDataByMonth = getDetailLeaveDay(
 | 
			
		||||
                      user.monthlyLeaveDays,
 | 
			
		||||
                    )
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue