truong-leave-day #116
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -304,7 +304,7 @@ class TicketController extends Controller
 | 
			
		|||
        // 1. Tính tổng ngày phép được cấp
 | 
			
		||||
        $totalAllocated = $this->getTotalAllocatedDays($user, $year);
 | 
			
		||||
 | 
			
		||||
        // 2. Tính số ngày đã nghỉ trong năm
 | 
			
		||||
        // 2. Tính số ngày đã nghỉ có phép trong năm
 | 
			
		||||
        $usedDays = $this->getUsedLeaveDays($user, $year);
 | 
			
		||||
 | 
			
		||||
        // 3. Tính số ngày còn lại
 | 
			
		||||
| 
						 | 
				
			
			@ -371,39 +371,137 @@ class TicketController extends Controller
 | 
			
		|||
            ->sum('categories.c_value');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Tính tổng giới hạn ngày nghỉ có phép tối đa trong tháng
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function checkMonthlyLeaveLimit($user, array $dataListPeriod): array
 | 
			
		||||
    {
 | 
			
		||||
        // Danh sách ngày nghỉ theo tháng
 | 
			
		||||
        $requestMonths = $this->groupLeaveRequestsByMonth($dataListPeriod);
 | 
			
		||||
        $monthsInfo = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($requestMonths as $monthKey => $monthData) {
 | 
			
		||||
            $usedDaysInMonth = $this->getUsedLeaveDaysInMonth($user, $monthData['year'], $monthData['month']);
 | 
			
		||||
            dd($usedDaysInMonth);
 | 
			
		||||
            $requestMonths[$monthKey]['days_used'] = $usedDaysInMonth;
 | 
			
		||||
 | 
			
		||||
            // Kiểm tra giới hạn ngày nghỉ trong tháng
 | 
			
		||||
            $maxDaysPerMonth = 3; // Có thể điều chỉnh theo quy định công ty
 | 
			
		||||
            $totalDaysInMonth = $usedDaysInMonth + $monthData['days_requested'];
 | 
			
		||||
            // Tính tổng số ngày nghỉ có phép trong tháng
 | 
			
		||||
            $usedDaysInMonth = $this->getUsedLeaveDaysInMonth($user, $monthData['year'], $monthData['month'], 'ONLEAVE');
 | 
			
		||||
 | 
			
		||||
            if ($totalDaysInMonth > $maxDaysPerMonth) {
 | 
			
		||||
                return $this->exceedMonthlyLimitResponse($monthData, $usedDaysInMonth, $maxDaysPerMonth);
 | 
			
		||||
            }
 | 
			
		||||
            // Tính tổng số ngày nghỉ không phép trong tháng
 | 
			
		||||
            $usedDaysInMonthWithoutPay = $this->getUsedLeaveDaysInMonth($user, $monthData['year'], $monthData['month'], 'LEAVE_WITHOUT_PAY');
 | 
			
		||||
 | 
			
		||||
            $monthsInfo[] = [
 | 
			
		||||
            // Tính tổng giới hạn ngày nghỉ có phép tối đa trong tháng
 | 
			
		||||
            $maxDaysPerMonth = $this->getMaxLeaveDaysPerMonth();
 | 
			
		||||
 | 
			
		||||
            // Tính tổng số ngày nghỉ trong tháng
 | 
			
		||||
            $totalDaysInMonth = $usedDaysInMonth + $usedDaysInMonthWithoutPay + $monthData['days_requested'];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            // Tính tổng phép có trong tháng
 | 
			
		||||
            $totalLeaveDaysInMonth = $this->getTotalLeaveDaysInMonth($user, $monthData['year'], $monthData['month']);
 | 
			
		||||
 | 
			
		||||
            // 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']);
 | 
			
		||||
 | 
			
		||||
            //Ngày phép còn lại trong tháng
 | 
			
		||||
            $remainingDaysInMonth = $totalLeaveDaysInMonth - $totalLeaveDaysInMonthToMonth;
 | 
			
		||||
            // dd($remainingDaysInMonth, $totalLeaveDaysInMonth, $totalLeaveDaysInMonthToMonth);
 | 
			
		||||
 | 
			
		||||
            $month_data = [
 | 
			
		||||
                'year' => $monthData['year'],
 | 
			
		||||
                'month' => $monthData['month'],
 | 
			
		||||
                'days_used' => $usedDaysInMonth,
 | 
			
		||||
                'days_requested' => $monthData['days_requested'],
 | 
			
		||||
                'total_days' => $totalDaysInMonth
 | 
			
		||||
                'total_leave_days_in_month' => $totalLeaveDaysInMonth, //tổng số ngày phép
 | 
			
		||||
                'total_leave_days_in_month_to_month' => $totalLeaveDaysInMonthToMonth, // tổng ngày nghỉ có phép
 | 
			
		||||
                'remaining_days_in_month' => $remainingDaysInMonth, //ngày phép còn lại
 | 
			
		||||
                'days_used' => $usedDaysInMonth, //tổng số ngày nghỉ có phép ở tháng hiện tại
 | 
			
		||||
                'days_used_without_pay' => $usedDaysInMonthWithoutPay, //tổng số ngày nghỉ không phép ở tháng hiện tại
 | 
			
		||||
                'days_requested' => $monthData['days_requested'], //số ngày yêu cầu nghỉ của tháng
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
            if ($remainingDaysInMonth <= 0) { //hết phép
 | 
			
		||||
                return [
 | 
			
		||||
                    'success' => false,
 | 
			
		||||
                    'message' => "Hiện tại bạn đã hết phép nghỉ trong tháng {$monthData['month']}/{$monthData['year']}\nBạn có chấp nhận nộp: " . $monthData['days_requested'] . " ngày không phép không?",
 | 
			
		||||
                    'warning_type' => 'exceed_monthly_limit',
 | 
			
		||||
                    'month_data' => $month_data
 | 
			
		||||
                ];
 | 
			
		||||
            } else {
 | 
			
		||||
                // Còn phép
 | 
			
		||||
                if ($remainingDaysInMonth >= $monthData['days_requested']) {
 | 
			
		||||
                    return [
 | 
			
		||||
                        'success' => true,
 | 
			
		||||
                        'message' => "Đủ ngày phép",
 | 
			
		||||
                        'warning_type' => 'exceed_monthly_limit',
 | 
			
		||||
                        'month_data' => $month_data
 | 
			
		||||
                    ];
 | 
			
		||||
                } else {
 | 
			
		||||
                    return $this->exceedMonthlyLimitResponse($remainingDaysInMonth, $monthData, $usedDaysInMonth, $usedDaysInMonthWithoutPay, $month_data);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
            'success' => true,
 | 
			
		||||
            'success' => false,
 | 
			
		||||
            'message' => "Không tìm được mảng danh sách ngày nghỉ",
 | 
			
		||||
            'warning_type' => 'exceed_monthly_limit',
 | 
			
		||||
            'months_info' => $monthsInfo
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Trả về thông báo vượt quá giới hạn ngày nghỉ có phép trong tháng
 | 
			
		||||
    private function exceedMonthlyLimitResponse(float $remainingDaysInMonth, array $monthData, float $usedDaysInMonth, float $usedDaysInMonthWithoutPay, array $month_data): array
 | 
			
		||||
    {
 | 
			
		||||
        $daysNotEnough = $monthData['days_requested'] - $remainingDaysInMonth;
 | 
			
		||||
        $message = "Số ngày phép còn lại: {$remainingDaysInMonth}, Số ngày yêu cầu: {$monthData['days_requested']}.\n\nBạn có chấp nhận nộp: {$remainingDaysInMonth} ngày phép và {$daysNotEnough} ngày không phép không?";
 | 
			
		||||
        return [
 | 
			
		||||
            'success' => false,
 | 
			
		||||
            'message' => "Bạn không đủ ngày phép.\n\nTrong tháng {$monthData['month']}/{$monthData['year']}:\n\nBạn đã nghỉ: {$usedDaysInMonth} ngày phép, {$usedDaysInMonthWithoutPay} ngày không phép. \n\n{$message}",
 | 
			
		||||
            'warning_type' => 'exceed_monthly_limit',
 | 
			
		||||
            'month_data' => $month_data
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //Tính tổng số ngày nghỉ có phép đến tháng hiện tại
 | 
			
		||||
    private function getTotalLeaveDaysInMonthToMonth($user, int $year, int $month): float
 | 
			
		||||
    {
 | 
			
		||||
        return 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', $year)
 | 
			
		||||
            ->where('n_month', "<=", $month)
 | 
			
		||||
            ->where('n_reason', 'ONLEAVE')
 | 
			
		||||
            ->sum('categories.c_value');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getTotalLeaveDaysInMonth($user, int $year, int $month): float
 | 
			
		||||
    {
 | 
			
		||||
        $leaveDaysInfo = LeaveDays::where('ld_user_id', $user->id)
 | 
			
		||||
            ->where('ld_year', $year)
 | 
			
		||||
            ->first();
 | 
			
		||||
 | 
			
		||||
        $totalAllocated = 0;
 | 
			
		||||
        if ($leaveDaysInfo) {
 | 
			
		||||
            if ($leaveDaysInfo->ld_day_total > $month) {
 | 
			
		||||
                $totalAllocated = $month;
 | 
			
		||||
            } else {
 | 
			
		||||
                $totalAllocated = $leaveDaysInfo->ld_day_total;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            Log::warning("No LeaveDays record found for user ID: {$user->id}, year: {$year}. Assuming 0 allocated days.");
 | 
			
		||||
        }
 | 
			
		||||
        $totalAllocated = $totalAllocated + $leaveDaysInfo->ld_additional_day + $leaveDaysInfo->ld_special_leave_day;
 | 
			
		||||
        return $totalAllocated;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function groupLeaveRequestsByMonth(array $dataListPeriod): array
 | 
			
		||||
    {
 | 
			
		||||
        $requestMonths = [];
 | 
			
		||||
| 
						 | 
				
			
			@ -428,7 +526,7 @@ class TicketController extends Controller
 | 
			
		|||
        return $requestMonths;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getUsedLeaveDaysInMonth($user, int $year, int $month): float
 | 
			
		||||
    private function getUsedLeaveDaysInMonth($user, int $year, int $month, string $reason): float
 | 
			
		||||
    {
 | 
			
		||||
        return Notes::join('categories', function ($join) {
 | 
			
		||||
            $join->on('notes.n_time_type', '=', 'categories.c_code')
 | 
			
		||||
| 
						 | 
				
			
			@ -437,29 +535,10 @@ class TicketController extends Controller
 | 
			
		|||
            ->where('n_user_id', $user->id)
 | 
			
		||||
            ->where('n_year', $year)
 | 
			
		||||
            ->where('n_month', $month)
 | 
			
		||||
            ->where('n_reason', 'ONLEAVE')
 | 
			
		||||
            ->where('n_reason', $reason)
 | 
			
		||||
            ->sum('categories.c_value');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function exceedMonthlyLimitResponse(array $monthData, float $usedDaysInMonth, int $maxDaysPerMonth): array
 | 
			
		||||
    {
 | 
			
		||||
        $exceedDays = ($usedDaysInMonth + $monthData['days_requested']) - $maxDaysPerMonth;
 | 
			
		||||
 | 
			
		||||
        return [
 | 
			
		||||
            'success' => false,
 | 
			
		||||
            'message' => "Trong tháng {$monthData['month']}/{$monthData['year']}, bạn đã nghỉ {$usedDaysInMonth} ngày và xin nghỉ thêm {$monthData['days_requested']} ngày, vượt quá giới hạn {$maxDaysPerMonth} ngày/tháng. Vui lòng điều chỉnh lại.",
 | 
			
		||||
            'warning_type' => 'exceed_monthly_limit',
 | 
			
		||||
            'month_data' => [
 | 
			
		||||
                'year' => $monthData['year'],
 | 
			
		||||
                'month' => $monthData['month'],
 | 
			
		||||
                'days_used' => $usedDaysInMonth,
 | 
			
		||||
                'days_requested' => $monthData['days_requested'],
 | 
			
		||||
                'max_days' => $maxDaysPerMonth,
 | 
			
		||||
                'exceed_days' => $exceedDays
 | 
			
		||||
            ]
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function insufficientLeaveDaysResponse($user, float $remainingDays, float $daysRequested): array
 | 
			
		||||
    {
 | 
			
		||||
        $daysNotEnough = $daysRequested - $remainingDays;
 | 
			
		||||
| 
						 | 
				
			
			@ -467,7 +546,9 @@ class TicketController extends Controller
 | 
			
		|||
 | 
			
		||||
        return [
 | 
			
		||||
            'success' => false,
 | 
			
		||||
            'message' => "Bạn không đủ ngày phép. Số ngày phép còn lại: {$remainingDays}, Số ngày yêu cầu: {$daysRequested}. Bạn có chấp nhận nộp: {$daysNotEnough} ngày không phép không?"
 | 
			
		||||
            'message' => "Bạn không đủ ngày phép. Số ngày phép còn lại: {$remainingDays}, Số ngày yêu cầu: {$daysRequested}. Bạn có chấp nhận nộp: {$daysNotEnough} ngày không phép không?",
 | 
			
		||||
            'warning_type' => 'insufficient_leave_days',
 | 
			
		||||
            'month_data' => []
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -522,7 +522,7 @@ const LeaveManagement = () => {
 | 
			
		|||
        >
 | 
			
		||||
          <Table.Thead>
 | 
			
		||||
            <Table.Tr bg={'#228be66b'}>
 | 
			
		||||
              <Table.Th></Table.Th>
 | 
			
		||||
              <Table.Th ta={'center'} style={{ width: '40px' }}></Table.Th>
 | 
			
		||||
              <Table.Th>User</Table.Th>
 | 
			
		||||
              {monthInYear.map((d) => {
 | 
			
		||||
                return (
 | 
			
		||||
| 
						 | 
				
			
			@ -530,7 +530,7 @@ const LeaveManagement = () => {
 | 
			
		|||
                    <Menu.Target>
 | 
			
		||||
                      <Table.Th
 | 
			
		||||
                        ta={'center'}
 | 
			
		||||
                        style={{ cursor: 'pointer', width: '60px' }}
 | 
			
		||||
                        style={{ cursor: 'pointer', width: '40px' }}
 | 
			
		||||
                      >
 | 
			
		||||
                        <span>{d.name}</span>
 | 
			
		||||
                      </Table.Th>
 | 
			
		||||
| 
						 | 
				
			
			@ -538,10 +538,10 @@ const LeaveManagement = () => {
 | 
			
		|||
                  </Menu>
 | 
			
		||||
                )
 | 
			
		||||
              })}
 | 
			
		||||
              <Table.Th ta={'center'} style={{ width: '80px' }}>
 | 
			
		||||
              <Table.Th ta={'center'} style={{ width: '150px' }}>
 | 
			
		||||
                Total
 | 
			
		||||
              </Table.Th>
 | 
			
		||||
              <Table.Th ta={'center'} style={{ width: '80px' }}>
 | 
			
		||||
              <Table.Th ta={'center'} style={{ width: '130px' }}>
 | 
			
		||||
                Off
 | 
			
		||||
              </Table.Th>
 | 
			
		||||
              <Table.Th ta={'center'} style={{ width: '80px' }}>
 | 
			
		||||
| 
						 | 
				
			
			@ -642,27 +642,59 @@ const LeaveManagement = () => {
 | 
			
		|||
                  >
 | 
			
		||||
                    <p
 | 
			
		||||
                      style={{
 | 
			
		||||
                        backgroundColor: '#c3ffc3',
 | 
			
		||||
                        // backgroundColor: '#c3ffc3',
 | 
			
		||||
                        display: ld_day_total > 0 ? 'block' : 'none',
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      {'Phép năm:'}{' '}
 | 
			
		||||
                      <span
 | 
			
		||||
                        style={{
 | 
			
		||||
                          backgroundColor: '#c3ffc3',
 | 
			
		||||
                          padding: '5px',
 | 
			
		||||
                          borderRadius: '5px',
 | 
			
		||||
                          fontWeight: 'bold',
 | 
			
		||||
                          color: 'black',
 | 
			
		||||
                        }}
 | 
			
		||||
                      >
 | 
			
		||||
                        {ld_day_total}
 | 
			
		||||
                      </span>
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p
 | 
			
		||||
                      style={{
 | 
			
		||||
                        backgroundColor: '#92e6f2',
 | 
			
		||||
                        // backgroundColor: '#92e6f2',
 | 
			
		||||
                        display: ld_additional_day > 0 ? 'block' : 'none',
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      {'Phép năm cũ:'}{' '}
 | 
			
		||||
                      <span
 | 
			
		||||
                        style={{
 | 
			
		||||
                          backgroundColor: '#92e6f2',
 | 
			
		||||
                          padding: '5px',
 | 
			
		||||
                          borderRadius: '5px',
 | 
			
		||||
                          fontWeight: 'bold',
 | 
			
		||||
                          color: 'black',
 | 
			
		||||
                        }}
 | 
			
		||||
                      >
 | 
			
		||||
                        {ld_additional_day}
 | 
			
		||||
                      </span>
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p
 | 
			
		||||
                      style={{
 | 
			
		||||
                        backgroundColor: '#b5cafb',
 | 
			
		||||
                        display: ld_special_leave_day > 0 ? 'block' : 'none',
 | 
			
		||||
                      }}
 | 
			
		||||
                    >
 | 
			
		||||
                      {'Phép đặc biệt:'}{' '}
 | 
			
		||||
                      <span
 | 
			
		||||
                        style={{
 | 
			
		||||
                          backgroundColor: '#b5cafb',
 | 
			
		||||
                          padding: '5px',
 | 
			
		||||
                          borderRadius: '5px',
 | 
			
		||||
                          fontWeight: 'bold',
 | 
			
		||||
                          color: 'black',
 | 
			
		||||
                        }}
 | 
			
		||||
                      >
 | 
			
		||||
                        {ld_special_leave_day}
 | 
			
		||||
                      </span>
 | 
			
		||||
                    </p>
 | 
			
		||||
                  </Table.Td>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -674,11 +706,37 @@ const LeaveManagement = () => {
 | 
			
		|||
                        label={showAllOff(user.monthlyLeaveDays)}
 | 
			
		||||
                      >
 | 
			
		||||
                        <div>
 | 
			
		||||
                          <p style={{ backgroundColor: '#c3ffc3' }}>
 | 
			
		||||
                          <p
 | 
			
		||||
                          // style={{ backgroundColor: '#c3ffc3' }}
 | 
			
		||||
                          >
 | 
			
		||||
                            {'Nghỉ phép:'}{' '}
 | 
			
		||||
                            <span
 | 
			
		||||
                              style={{
 | 
			
		||||
                                fontWeight: 'bold',
 | 
			
		||||
                                color: 'black',
 | 
			
		||||
                                backgroundColor: '#c3ffc3',
 | 
			
		||||
                                padding: '5px',
 | 
			
		||||
                                borderRadius: '5px',
 | 
			
		||||
                              }}
 | 
			
		||||
                            >
 | 
			
		||||
                              {totalOnLeave}
 | 
			
		||||
                            </span>
 | 
			
		||||
                          </p>
 | 
			
		||||
                          <p style={{ backgroundColor: '#ffb5b5' }}>
 | 
			
		||||
                          <p
 | 
			
		||||
                          //  style={{ backgroundColor: '#ffb5b5' }}
 | 
			
		||||
                          >
 | 
			
		||||
                            {'Không phép:'}{' '}
 | 
			
		||||
                            <span
 | 
			
		||||
                              style={{
 | 
			
		||||
                                fontWeight: 'bold',
 | 
			
		||||
                                color: 'black',
 | 
			
		||||
                                backgroundColor: '#ffb5b5',
 | 
			
		||||
                                padding: '5px',
 | 
			
		||||
                                borderRadius: '5px',
 | 
			
		||||
                              }}
 | 
			
		||||
                            >
 | 
			
		||||
                              {totalLeaveWithoutPay}
 | 
			
		||||
                            </span>
 | 
			
		||||
                          </p>
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </Tooltip>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue