diff --git a/tksupport/api/controllers/vacationController.js b/tksupport/api/controllers/vacationController.js index 23bf2c8..d61b2c8 100644 --- a/tksupport/api/controllers/vacationController.js +++ b/tksupport/api/controllers/vacationController.js @@ -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(); + } } }; diff --git a/tksupport/api/models/vacationBalanceModel.js b/tksupport/api/models/vacationBalanceModel.js index d7a0a66..444aa82 100644 --- a/tksupport/api/models/vacationBalanceModel.js +++ b/tksupport/api/models/vacationBalanceModel.js @@ -61,8 +61,8 @@ const vacationBalanceModel = { return result; }, - async deductDays(userId, vacationTypeId, year, daysToDeduct) { - const db = getPool(); + async deductDays(userId, vacationTypeId, year, daysToDeduct, conn) { + const db = conn || getPool(); const [result] = await db.query(` UPDATE sp_vacation_balances SET used_days = used_days + ?, updated_at = NOW() @@ -71,8 +71,8 @@ const vacationBalanceModel = { return result; }, - async restoreDays(userId, vacationTypeId, year, daysToRestore) { - const db = getPool(); + async restoreDays(userId, vacationTypeId, year, daysToRestore, conn) { + const db = conn || getPool(); const [result] = await db.query(` UPDATE sp_vacation_balances SET used_days = GREATEST(0, used_days - ?), updated_at = NOW() diff --git a/tksupport/api/models/vacationDashboardModel.js b/tksupport/api/models/vacationDashboardModel.js index 059853c..664f88b 100644 --- a/tksupport/api/models/vacationDashboardModel.js +++ b/tksupport/api/models/vacationDashboardModel.js @@ -90,7 +90,7 @@ const vacationDashboardModel = { const [rows] = await db.query(` SELECT su.user_id, su.name, su.username, - vr.start_date, vr.end_date, vr.days_used, + vr.request_id, vr.start_date, vr.end_date, vr.days_used, vt.type_code, vt.type_name FROM sso_users su LEFT JOIN sp_vacation_requests vr diff --git a/tksupport/api/models/vacationRequestModel.js b/tksupport/api/models/vacationRequestModel.js index 71c388e..dd5a013 100644 --- a/tksupport/api/models/vacationRequestModel.js +++ b/tksupport/api/models/vacationRequestModel.js @@ -1,8 +1,8 @@ const { getPool } = require('../middleware/auth'); const vacationRequestModel = { - async create(data) { - const db = getPool(); + async create(data, conn) { + const db = conn || getPool(); const [result] = await db.query('INSERT INTO sp_vacation_requests SET ?', data); return result; }, @@ -85,8 +85,8 @@ const vacationRequestModel = { return result; }, - async updateStatus(requestId, statusData) { - const db = getPool(); + async updateStatus(requestId, statusData, conn) { + const db = conn || getPool(); const [result] = await db.query(` UPDATE sp_vacation_requests SET status = ?, reviewed_by = ?, reviewed_at = NOW(), review_note = ? diff --git a/tksupport/api/routes/vacationRoutes.js b/tksupport/api/routes/vacationRoutes.js index fca3432..eb48825 100644 --- a/tksupport/api/routes/vacationRoutes.js +++ b/tksupport/api/routes/vacationRoutes.js @@ -29,6 +29,10 @@ router.get('/balance/all', requireAdmin, ctrl.getAllBalances); router.get('/balance/:userId', requireAdmin, ctrl.getUserBalance); router.post('/balance/allocate', requireAdmin, ctrl.allocateBalance); +// 관리자 보정 +router.post('/admin/correct', requireAdmin, ctrl.adminCreateRequest); +router.delete('/admin/requests/:id', requireAdmin, ctrl.adminDeleteRequest); + // 사용자 목록 (관리자) router.get('/users', requireAdmin, ctrl.getUsers); diff --git a/tksupport/web/company-holidays.html b/tksupport/web/company-holidays.html index 6d704b9..fbebe3a 100644 --- a/tksupport/web/company-holidays.html +++ b/tksupport/web/company-holidays.html @@ -108,7 +108,7 @@ - + + + + + + +
+