fix(tkuser): 장기근속 5년 정확 경과 체크 + 수동부여 연도 입력
- autoGrantLongServiceLeave: 연도 차이 → 정확한 기념일 경과 확인 (today < anniversaryDate이면 스킵) - 수동 배정 모달에 "배정 연도" 필드 추가 (탭 연도 의존 제거) - 장기근속 만료일 = null 유지 (기존 동작 그대로) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -264,15 +264,17 @@ async function autoGrantLongServiceLeave(users, year, createdBy, settings) {
|
|||||||
if (!u.hire_date) continue;
|
if (!u.hire_date) continue;
|
||||||
|
|
||||||
const hire = new Date(u.hire_date);
|
const hire = new Date(u.hire_date);
|
||||||
const yearsWorked = year - hire.getFullYear();
|
// 정확한 5년 기념일 계산
|
||||||
// 해당 연도 내 threshold 도래 건만 (소급 없음)
|
|
||||||
if (yearsWorked !== thresholdYears) continue;
|
|
||||||
|
|
||||||
// 기념일이 해당 연도인지 확인
|
|
||||||
const anniversaryDate = new Date(hire);
|
const anniversaryDate = new Date(hire);
|
||||||
anniversaryDate.setFullYear(hire.getFullYear() + thresholdYears);
|
anniversaryDate.setFullYear(hire.getFullYear() + thresholdYears);
|
||||||
|
|
||||||
|
// 기념일이 해당 연도가 아니면 스킵
|
||||||
if (anniversaryDate.getFullYear() !== year) continue;
|
if (anniversaryDate.getFullYear() !== year) continue;
|
||||||
|
|
||||||
|
// 기념일이 아직 도래하지 않았으면 스킵 (정확히 5년 경과 필요)
|
||||||
|
const today = new Date();
|
||||||
|
if (today < anniversaryDate) continue;
|
||||||
|
|
||||||
// long_service_excluded 체크
|
// long_service_excluded 체크
|
||||||
const [userRows] = await db.query(
|
const [userRows] = await db.query(
|
||||||
'SELECT long_service_excluded FROM sso_users WHERE user_id = ?',
|
'SELECT long_service_excluded FROM sso_users WHERE user_id = ?',
|
||||||
|
|||||||
@@ -904,6 +904,7 @@
|
|||||||
<option value="">선택</option>
|
<option value="">선택</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid grid-cols-2 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-xs font-medium text-gray-600 mb-1">배정 유형</label>
|
<label class="block text-xs font-medium text-gray-600 mb-1">배정 유형</label>
|
||||||
<select id="vbBalanceType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" onchange="onBalanceTypeChange()">
|
<select id="vbBalanceType" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" onchange="onBalanceTypeChange()">
|
||||||
@@ -914,6 +915,11 @@
|
|||||||
<option value="COMPANY_GRANT">회사부여</option>
|
<option value="COMPANY_GRANT">회사부여</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-xs font-medium text-gray-600 mb-1">배정 연도 <span class="text-red-400">*</span></label>
|
||||||
|
<input type="number" id="vbYear" class="input-field w-full px-3 py-1.5 rounded-lg text-sm" min="2020" max="2035" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="grid grid-cols-2 gap-3">
|
<div class="grid grid-cols-2 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-xs font-medium text-gray-600 mb-1">배정 일수</label>
|
<label class="block text-xs font-medium text-gray-600 mb-1">배정 일수</label>
|
||||||
@@ -2410,7 +2416,7 @@
|
|||||||
<script src="/static/js/tkuser-issue-types.js?v=2026031401"></script>
|
<script src="/static/js/tkuser-issue-types.js?v=2026031401"></script>
|
||||||
<script src="/static/js/tkuser-workplaces.js?v=2026031401"></script>
|
<script src="/static/js/tkuser-workplaces.js?v=2026031401"></script>
|
||||||
<script src="/static/js/tkuser-tasks.js?v=2026031401"></script>
|
<script src="/static/js/tkuser-tasks.js?v=2026031401"></script>
|
||||||
<script src="/static/js/tkuser-vacations.js?v=2026032301"></script>
|
<script src="/static/js/tkuser-vacations.js?v=2026033101"></script>
|
||||||
<script src="/static/js/tkuser-vacation-settings.js?v=2026032501"></script>
|
<script src="/static/js/tkuser-vacation-settings.js?v=2026032501"></script>
|
||||||
<script src="/static/js/tkuser-layout-map.js?v=2026031401"></script>
|
<script src="/static/js/tkuser-layout-map.js?v=2026031401"></script>
|
||||||
<script src="/static/js/tkuser-partners.js?v=2026031601"></script>
|
<script src="/static/js/tkuser-partners.js?v=2026031601"></script>
|
||||||
|
|||||||
@@ -353,6 +353,7 @@ function openVacBalanceModal(editId) {
|
|||||||
document.getElementById('vacBalModalTitle').textContent = '연차 배정';
|
document.getElementById('vacBalModalTitle').textContent = '연차 배정';
|
||||||
|
|
||||||
const year = document.getElementById('vacYear')?.value || new Date().getFullYear();
|
const year = document.getElementById('vacYear')?.value || new Date().getFullYear();
|
||||||
|
document.getElementById('vbYear').value = year;
|
||||||
document.getElementById('vbExpiresAt').value = `${year}-12-31`;
|
document.getElementById('vbExpiresAt').value = `${year}-12-31`;
|
||||||
|
|
||||||
// 사용자 셀렉트 (부서별 optgroup)
|
// 사용자 셀렉트 (부서별 optgroup)
|
||||||
@@ -422,11 +423,10 @@ document.getElementById('vacBalanceForm').addEventListener('submit', async e =>
|
|||||||
})});
|
})});
|
||||||
showToast('수정되었습니다.');
|
showToast('수정되었습니다.');
|
||||||
} else {
|
} else {
|
||||||
const year = document.getElementById('vacYear')?.value || new Date().getFullYear();
|
|
||||||
await api('/vacations/balances', { method: 'POST', body: JSON.stringify({
|
await api('/vacations/balances', { method: 'POST', body: JSON.stringify({
|
||||||
user_id: parseInt(document.getElementById('vbUser').value),
|
user_id: parseInt(document.getElementById('vbUser').value),
|
||||||
vacation_type_id: parseInt(document.getElementById('vbType').value),
|
vacation_type_id: parseInt(document.getElementById('vbType').value),
|
||||||
year: parseInt(year),
|
year: parseInt(document.getElementById('vbYear').value),
|
||||||
total_days: parseFloat(document.getElementById('vbTotalDays').value) || 0,
|
total_days: parseFloat(document.getElementById('vbTotalDays').value) || 0,
|
||||||
used_days: parseFloat(document.getElementById('vbUsedDays').value) || 0,
|
used_days: parseFloat(document.getElementById('vbUsedDays').value) || 0,
|
||||||
balance_type: document.getElementById('vbBalanceType').value,
|
balance_type: document.getElementById('vbBalanceType').value,
|
||||||
|
|||||||
Reference in New Issue
Block a user