feat(vacation): 조퇴 연차 차감 처리 (0.75일 = 반차+반반차)
- EARLY_LEAVE vacation type 추가 (deduct_days=0.75) - work-status: isLeave=true + 동적 vacation_type_id 조회 + 실패 보호 - annual-overview: 월별 요약 테이블에 조퇴 컬럼 추가 + 편집 드롭다운 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -308,13 +308,14 @@
|
||||
let hasCheckinData = false;
|
||||
let isAlreadySaved = false;
|
||||
let isSaving = false;
|
||||
let earlyLeaveTypeId = null;
|
||||
|
||||
const attendanceTypes = [
|
||||
{ value: 'normal', label: '정시근무', hours: 8, isLeave: false },
|
||||
{ value: 'annual', label: '연차', hours: 0, isLeave: true },
|
||||
{ value: 'half', label: '반차', hours: 4, isLeave: true },
|
||||
{ value: 'quarter', label: '반반차', hours: 6, isLeave: true },
|
||||
{ value: 'early', label: '조퇴', hours: 2, isLeave: false },
|
||||
{ value: 'early', label: '조퇴', hours: 2, isLeave: true },
|
||||
{ value: 'overtime', label: '연장근로', hours: 8, isLeave: false }
|
||||
];
|
||||
|
||||
@@ -347,6 +348,15 @@
|
||||
if (!selectedDate) return alert('날짜를 선택해주세요.');
|
||||
|
||||
try {
|
||||
// EARLY_LEAVE 유형 ID 조회 (최초 1회)
|
||||
if (!earlyLeaveTypeId) {
|
||||
try {
|
||||
const vtRes = await axios.get('/attendance/vacation-types');
|
||||
const earlyType = (vtRes.data.data || []).find(t => t.type_code === 'EARLY_LEAVE');
|
||||
earlyLeaveTypeId = earlyType?.id || null;
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
const [workersRes, recordsRes] = await Promise.all([
|
||||
axios.get('/workers?limit=100'),
|
||||
axios.get(`/attendance/daily-records?date=${selectedDate}`).catch(() => ({ data: { data: [] } }))
|
||||
@@ -743,13 +753,27 @@
|
||||
'overtime': 1 // NORMAL (시간으로 구분)
|
||||
};
|
||||
|
||||
// vacation_types: 1=ANNUAL_FULL, 2=ANNUAL_HALF, 3=ANNUAL_QUARTER
|
||||
// vacation_types: 1=ANNUAL_FULL, 2=ANNUAL_HALF, 3=ANNUAL_QUARTER, EARLY_LEAVE=동적
|
||||
const vacationTypeIdMap = {
|
||||
'annual': 1,
|
||||
'half': 2,
|
||||
'quarter': 3,
|
||||
'early': earlyLeaveTypeId,
|
||||
};
|
||||
|
||||
// 조퇴가 있는데 vacation_type_id가 없으면 저장 차단
|
||||
const hasEarlyWithoutType = workers.some(w => {
|
||||
const s = workStatus[w.user_id];
|
||||
return s && s.type === 'early' && !earlyLeaveTypeId;
|
||||
});
|
||||
if (hasEarlyWithoutType) {
|
||||
alert('조퇴 휴가 유형이 등록되지 않았습니다. 관리자에게 문의해주세요.');
|
||||
isSaving = false;
|
||||
saveBtn.disabled = false;
|
||||
saveBtn.textContent = '저장';
|
||||
return;
|
||||
}
|
||||
|
||||
// 미입사자 제외하고 저장할 데이터 생성
|
||||
const recordsToSave = workers
|
||||
.filter(w => !workStatus[w.user_id]?.isNotHired)
|
||||
|
||||
Reference in New Issue
Block a user