feat(tksupport): 휴가 보정 관리 페이지 추가 — 캘린더 기반 추가/삭제

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-25 14:12:14 +09:00
parent 05c9f22bdf
commit d663b9bfa6
13 changed files with 396 additions and 15 deletions

View File

@@ -343,6 +343,80 @@ const vacationController = {
console.error('사용자 목록 조회 오류:', error);
res.status(500).json({ success: false, error: '서버 오류가 발생했습니다' });
}
},
// ─── 관리자 보정 ───
async adminCreateRequest(req, res) {
const db = getPool();
const conn = await db.getConnection();
try {
const { user_id, vacation_type_id, start_date, end_date, days_used, reason } = req.body;
if (!user_id || !vacation_type_id || !start_date || !end_date || !days_used) {
return res.status(400).json({ success: false, error: '필수 필드가 누락되었습니다' });
}
const daysVal = parseFloat(days_used);
if (daysVal <= 0 || daysVal > 30) {
return res.status(400).json({ success: false, error: '일수는 0 초과 30 이하여야 합니다' });
}
if (new Date(start_date).getFullYear() !== new Date(end_date).getFullYear()) {
return res.status(400).json({ success: false, error: '연도를 걸친 휴가는 연도별로 분리하여 입력해주세요' });
}
const adminId = req.user.user_id || req.user.id;
const year = new Date(start_date).getFullYear();
await conn.beginTransaction();
const result = await vacationRequestModel.create({
user_id, vacation_type_id, start_date, end_date,
days_used: daysVal, reason: reason || null,
status: 'approved', reviewed_by: adminId, review_note: '관리자 보정 추가'
}, conn);
await vacationBalanceModel.deductDays(user_id, vacation_type_id, year, daysVal, conn);
await conn.commit();
res.status(201).json({ success: true, message: '휴가가 등록되었습니다', data: { request_id: result.insertId } });
} catch (error) {
await conn.rollback();
console.error('관리자 보정 추가 오류:', error);
res.status(500).json({ success: false, error: '서버 오류가 발생했습니다' });
} finally {
conn.release();
}
},
async adminDeleteRequest(req, res) {
const db = getPool();
const conn = await db.getConnection();
try {
const { id } = req.params;
const results = await vacationRequestModel.getById(id);
if (results.length === 0) {
return res.status(404).json({ success: false, error: '해당 휴가 기록을 찾을 수 없습니다' });
}
const existing = results[0];
if (existing.status !== 'approved') {
return res.status(400).json({ success: false, error: '승인된 기록만 삭제할 수 있습니다' });
}
const adminId = req.user.user_id || req.user.id;
const year = new Date(existing.start_date).getFullYear();
await conn.beginTransaction();
await vacationBalanceModel.restoreDays(existing.user_id, existing.vacation_type_id, year, parseFloat(existing.days_used), conn);
await vacationRequestModel.updateStatus(id, {
status: 'cancelled', reviewed_by: adminId, review_note: '관리자 보정 삭제'
}, conn);
await conn.commit();
res.json({ success: true, message: '휴가가 삭제되었습니다' });
} catch (error) {
await conn.rollback();
console.error('관리자 보정 삭제 오류:', error);
res.status(500).json({ success: false, error: '서버 오류가 발생했습니다' });
} finally {
conn.release();
}
}
};