feat: [hr] 연차촉진 관리에 1차/2차 촉진기간 컬럼 추가

- 근로기준법 제61조 기준 입사일 기반 촉진기간 자동 계산
- 1차 촉진기간: 연차만료 6개월 전 ~ +10일
- 2차 촉진기간 마감: 연차만료 2개월 전
- 잔여일수 다음에 촉진기간 표시
This commit is contained in:
김보곤
2026-03-10 00:37:10 +09:00
parent 694646158d
commit 0ef6b72d8e
2 changed files with 38 additions and 3 deletions

View File

@@ -845,10 +845,10 @@ public function getPromotionCandidates(int $year): Collection
}
}
// 4. 잔여일수 > 0 필터링 + 통지 상태 결합
// 4. 잔여일수 > 0 필터링 + 통지 상태 결합 + 촉진기간 계산
return $balances
->filter(fn ($b) => ($b->total_days - $b->used_days) > 0)
->map(function ($balance) use ($sentMap) {
->map(function ($balance) use ($sentMap, $year) {
$userId = $balance->user_id;
$sent = $sentMap[$userId] ?? ['1st' => null, '2nd' => null];
@@ -860,6 +860,25 @@ public function getPromotionCandidates(int $year): Collection
default => 'not_sent',
};
// 촉진기간 계산 (근로기준법 제61조 — 입사일 기준)
$hireDate = $balance->employee?->hire_date;
if ($hireDate) {
$hire = Carbon::parse($hireDate);
// 연차 만료일: 입사기념일(year+1) 전날
$anniversary = $hire->copy()->setYear($year + 1);
$expiryDate = $anniversary->copy()->subDay();
// 1차 촉진기간: 만료 6개월 전 ~ +10일
$balance->first_promotion_start = $expiryDate->copy()->subMonths(6);
$balance->first_promotion_end = $expiryDate->copy()->subMonths(6)->addDays(10);
// 2차 촉진 마감: 만료 2개월 전
$balance->second_promotion_deadline = $expiryDate->copy()->subMonths(2);
} else {
$balance->first_promotion_start = null;
$balance->first_promotion_end = null;
$balance->second_promotion_deadline = null;
}
return $balance;
})
->values();

View File

@@ -87,6 +87,8 @@ class="inline-flex items-center gap-2 px-4 py-2 bg-red-500 hover:bg-red-600 text
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">발생일수</th>
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">사용일수</th>
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">잔여일수</th>
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">1 촉진기간</th>
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">2 촉진기간</th>
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">사용률</th>
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">상태</th>
<th class="px-3 py-2 text-center text-xs font-medium text-gray-500 uppercase">1 통지</th>
@@ -110,6 +112,20 @@ class="employee-checkbox rounded border-gray-300 text-blue-600"
<td class="px-3 py-2 text-center">{{ $candidate->total_days }}</td>
<td class="px-3 py-2 text-center">{{ $candidate->used_days }}</td>
<td class="px-3 py-2 text-center font-bold {{ $remaining >= 5 ? 'text-red-600' : 'text-orange-600' }}">{{ $remaining }}</td>
<td class="px-3 py-2 text-center text-xs whitespace-nowrap">
@if($candidate->first_promotion_start)
<span class="text-orange-600 font-medium">{{ $candidate->first_promotion_start->format('m/d') }} ~ {{ $candidate->first_promotion_end->format('m/d') }}</span>
@else
<span class="text-gray-400">-</span>
@endif
</td>
<td class="px-3 py-2 text-center text-xs whitespace-nowrap">
@if($candidate->second_promotion_deadline)
<span class="text-red-600 font-medium">~ {{ $candidate->second_promotion_deadline->format('m/d') }}</span>
@else
<span class="text-gray-400">-</span>
@endif
</td>
<td class="px-3 py-2 text-center">
<div class="flex items-center justify-center gap-1">
<div class="w-12 h-1.5 bg-gray-200 rounded-full overflow-hidden">
@@ -152,7 +168,7 @@ class="employee-checkbox rounded border-gray-300 text-blue-600"
</tr>
@empty
<tr>
<td colspan="10" class="px-4 py-12 text-center text-gray-400">
<td colspan="12" class="px-4 py-12 text-center text-gray-400">
잔여 연차가 있는 대상자가 없습니다.
</td>
</tr>