diff --git a/system1-factory/api/controllers/vacationRequestController.js b/system1-factory/api/controllers/vacationRequestController.js index 8d4df9f..318af1f 100644 --- a/system1-factory/api/controllers/vacationRequestController.js +++ b/system1-factory/api/controllers/vacationRequestController.js @@ -4,8 +4,7 @@ */ const vacationRequestModel = require('../models/vacationRequestModel'); -// TODO: workerVacationBalanceModel 구현 필요 -// const workerVacationBalanceModel = require('../models/workerVacationBalanceModel'); +const logger = require('../utils/logger'); const vacationRequestController = { /** @@ -16,81 +15,33 @@ const vacationRequestController = { const { worker_id, vacation_type_id, start_date, end_date, days_used, reason } = req.body; const requested_by = req.user.user_id; - // 필수 필드 검증 if (!worker_id || !vacation_type_id || !start_date || !end_date || !days_used) { - return res.status(400).json({ - success: false, - message: '필수 필드가 누락되었습니다' - }); + return res.status(400).json({ success: false, message: '필수 필드가 누락되었습니다' }); } - // 날짜 유효성 검증 - const startDate = new Date(start_date); - const endDate = new Date(end_date); - - if (endDate < startDate) { - return res.status(400).json({ - success: false, - message: '종료일은 시작일보다 이후여야 합니다' - }); + if (new Date(end_date) < new Date(start_date)) { + return res.status(400).json({ success: false, message: '종료일은 시작일보다 이후여야 합니다' }); } // 기간 중복 체크 - vacationRequestModel.checkOverlap(worker_id, start_date, end_date, null, (err, results) => { - if (err) { - console.error('기간 중복 체크 오류:', err); - return res.status(500).json({ - success: false, - message: '기간 중복 체크 중 오류가 발생했습니다' - }); - } + const overlapRows = await vacationRequestModel.checkOverlap(worker_id, start_date, end_date); + if (overlapRows[0].count > 0) { + return res.status(400).json({ success: false, message: '해당 기간에 이미 신청된 휴가가 있습니다' }); + } - if (results[0].count > 0) { - return res.status(400).json({ - success: false, - message: '해당 기간에 이미 신청된 휴가가 있습니다' - }); - } + const result = await vacationRequestModel.create({ + worker_id, vacation_type_id, start_date, end_date, + days_used, reason: reason || null, status: 'pending', requested_by + }); - // TODO: 잔여 연차 확인 로직 구현 필요 - // 현재는 잔여 연차 확인 없이 신청 가능 - - // 휴가 신청 생성 - const requestData = { - worker_id, - vacation_type_id, - start_date, - end_date, - days_used, - reason: reason || null, - status: 'pending', - requested_by - }; - - vacationRequestModel.create(requestData, (err, result) => { - if (err) { - console.error('휴가 신청 생성 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 생성 중 오류가 발생했습니다' - }); - } - - res.status(201).json({ - success: true, - message: '휴가 신청이 완료되었습니다', - data: { - request_id: result.insertId - } - }); - }); + res.status(201).json({ + success: true, + message: '휴가 신청이 완료되었습니다', + data: { request_id: result.insertId } }); } catch (error) { - console.error('휴가 신청 생성 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('휴가 신청 생성 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } }, @@ -112,33 +63,15 @@ const vacationRequestController = { if (req.user.worker_id) { filters.worker_id = req.user.worker_id; } else { - return res.status(403).json({ - success: false, - message: '권한이 없습니다' - }); + return res.status(403).json({ success: false, message: '권한이 없습니다' }); } } - vacationRequestModel.getAll(filters, (err, results) => { - if (err) { - console.error('휴가 신청 목록 조회 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 목록 조회 중 오류가 발생했습니다' - }); - } - - res.json({ - success: true, - data: results - }); - }); + const results = await vacationRequestModel.getAll(filters); + res.json({ success: true, data: results }); } catch (error) { - console.error('휴가 신청 목록 조회 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('휴가 신청 목록 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } }, @@ -147,45 +80,22 @@ const vacationRequestController = { */ async getRequestById(req, res) { try { - const { id } = req.params; + const results = await vacationRequestModel.getById(req.params.id); - vacationRequestModel.getById(id, (err, results) => { - if (err) { - console.error('휴가 신청 조회 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 조회 중 오류가 발생했습니다' - }); - } + if (results.length === 0) { + return res.status(404).json({ success: false, message: '해당 휴가 신청을 찾을 수 없습니다' }); + } - if (results.length === 0) { - return res.status(404).json({ - success: false, - message: '해당 휴가 신청을 찾을 수 없습니다' - }); - } + const request = results[0]; - const request = results[0]; + if (req.user.access_level !== 'system' && req.user.worker_id !== request.worker_id) { + return res.status(403).json({ success: false, message: '권한이 없습니다' }); + } - // 권한 검증: 관리자 또는 본인만 조회 가능 - if (req.user.access_level !== 'system' && req.user.worker_id !== request.worker_id) { - return res.status(403).json({ - success: false, - message: '권한이 없습니다' - }); - } - - res.json({ - success: true, - data: request - }); - }); + res.json({ success: true, data: request }); } catch (error) { - console.error('휴가 신청 조회 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('휴가 신청 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } }, @@ -197,114 +107,45 @@ const vacationRequestController = { const { id } = req.params; const { start_date, end_date, days_used, reason } = req.body; - // 기존 신청 조회 - vacationRequestModel.getById(id, (err, results) => { - if (err) { - console.error('휴가 신청 조회 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 조회 중 오류가 발생했습니다' - }); + const results = await vacationRequestModel.getById(id); + if (results.length === 0) { + return res.status(404).json({ success: false, message: '해당 휴가 신청을 찾을 수 없습니다' }); + } + + const existingRequest = results[0]; + + if (req.user.access_level !== 'system' && req.user.worker_id !== existingRequest.worker_id) { + return res.status(403).json({ success: false, message: '권한이 없습니다' }); + } + + if (existingRequest.status !== 'pending') { + return res.status(400).json({ success: false, message: '승인/거부된 신청은 수정할 수 없습니다' }); + } + + const updateData = {}; + if (start_date) updateData.start_date = start_date; + if (end_date) updateData.end_date = end_date; + if (days_used) updateData.days_used = days_used; + if (reason !== undefined) updateData.reason = reason; + + // 날짜가 변경된 경우 중복 체크 + if (start_date || end_date) { + const newStartDate = start_date || existingRequest.start_date; + const newEndDate = end_date || existingRequest.end_date; + + const overlapRows = await vacationRequestModel.checkOverlap( + existingRequest.worker_id, newStartDate, newEndDate, id + ); + if (overlapRows[0].count > 0) { + return res.status(400).json({ success: false, message: '해당 기간에 이미 신청된 휴가가 있습니다' }); } + } - if (results.length === 0) { - return res.status(404).json({ - success: false, - message: '해당 휴가 신청을 찾을 수 없습니다' - }); - } - - const existingRequest = results[0]; - - // 권한 검증 - if (req.user.access_level !== 'system' && req.user.worker_id !== existingRequest.worker_id) { - return res.status(403).json({ - success: false, - message: '권한이 없습니다' - }); - } - - // 대기 중인 신청만 수정 가능 - if (existingRequest.status !== 'pending') { - return res.status(400).json({ - success: false, - message: '승인/거부된 신청은 수정할 수 없습니다' - }); - } - - const updateData = {}; - if (start_date) updateData.start_date = start_date; - if (end_date) updateData.end_date = end_date; - if (days_used) updateData.days_used = days_used; - if (reason !== undefined) updateData.reason = reason; - - // 날짜가 변경된 경우 중복 체크 - if (start_date || end_date) { - const newStartDate = start_date || existingRequest.start_date; - const newEndDate = end_date || existingRequest.end_date; - - vacationRequestModel.checkOverlap( - existingRequest.worker_id, - newStartDate, - newEndDate, - id, - (err, overlapResults) => { - if (err) { - console.error('기간 중복 체크 오류:', err); - return res.status(500).json({ - success: false, - message: '기간 중복 체크 중 오류가 발생했습니다' - }); - } - - if (overlapResults[0].count > 0) { - return res.status(400).json({ - success: false, - message: '해당 기간에 이미 신청된 휴가가 있습니다' - }); - } - - // 수정 실행 - vacationRequestModel.update(id, updateData, (err, result) => { - if (err) { - console.error('휴가 신청 수정 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 수정 중 오류가 발생했습니다' - }); - } - - res.json({ - success: true, - message: '휴가 신청이 수정되었습니다' - }); - }); - } - ); - } else { - // 날짜 변경 없이 바로 수정 - vacationRequestModel.update(id, updateData, (err, result) => { - if (err) { - console.error('휴가 신청 수정 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 수정 중 오류가 발생했습니다' - }); - } - - res.json({ - success: true, - message: '휴가 신청이 수정되었습니다' - }); - }); - } - }); + await vacationRequestModel.update(id, updateData); + res.json({ success: true, message: '휴가 신청이 수정되었습니다' }); } catch (error) { - console.error('휴가 신청 수정 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('휴가 신청 수정 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } }, @@ -315,62 +156,26 @@ const vacationRequestController = { try { const { id } = req.params; - // 기존 신청 조회 - vacationRequestModel.getById(id, (err, results) => { - if (err) { - console.error('휴가 신청 조회 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 조회 중 오류가 발생했습니다' - }); - } + const results = await vacationRequestModel.getById(id); + if (results.length === 0) { + return res.status(404).json({ success: false, message: '해당 휴가 신청을 찾을 수 없습니다' }); + } - if (results.length === 0) { - return res.status(404).json({ - success: false, - message: '해당 휴가 신청을 찾을 수 없습니다' - }); - } + const existingRequest = results[0]; - const existingRequest = results[0]; + if (req.user.access_level !== 'system' && req.user.worker_id !== existingRequest.worker_id) { + return res.status(403).json({ success: false, message: '권한이 없습니다' }); + } - // 권한 검증 - if (req.user.access_level !== 'system' && req.user.worker_id !== existingRequest.worker_id) { - return res.status(403).json({ - success: false, - message: '권한이 없습니다' - }); - } + if (existingRequest.status !== 'pending') { + return res.status(400).json({ success: false, message: '승인/거부된 신청은 삭제할 수 없습니다' }); + } - // 대기 중인 신청만 삭제 가능 - if (existingRequest.status !== 'pending') { - return res.status(400).json({ - success: false, - message: '승인/거부된 신청은 삭제할 수 없습니다' - }); - } - - vacationRequestModel.delete(id, (err, result) => { - if (err) { - console.error('휴가 신청 삭제 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 삭제 중 오류가 발생했습니다' - }); - } - - res.json({ - success: true, - message: '휴가 신청이 삭제되었습니다' - }); - }); - }); + await vacationRequestModel.delete(id); + res.json({ success: true, message: '휴가 신청이 삭제되었습니다' }); } catch (error) { - console.error('휴가 신청 삭제 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('휴가 신청 삭제 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } }, @@ -383,71 +188,24 @@ const vacationRequestController = { const { review_note } = req.body; const reviewed_by = req.user.user_id; - // 관리자 권한 확인 if (req.user.access_level !== 'system') { - return res.status(403).json({ - success: false, - message: '관리자만 승인할 수 있습니다' - }); + return res.status(403).json({ success: false, message: '관리자만 승인할 수 있습니다' }); } - // 기존 신청 조회 - vacationRequestModel.getById(id, (err, results) => { - if (err) { - console.error('휴가 신청 조회 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 조회 중 오류가 발생했습니다' - }); - } + const results = await vacationRequestModel.getById(id); + if (results.length === 0) { + return res.status(404).json({ success: false, message: '해당 휴가 신청을 찾을 수 없습니다' }); + } - if (results.length === 0) { - return res.status(404).json({ - success: false, - message: '해당 휴가 신청을 찾을 수 없습니다' - }); - } + if (results[0].status !== 'pending') { + return res.status(400).json({ success: false, message: '이미 처리된 신청입니다' }); + } - const request = results[0]; - - if (request.status !== 'pending') { - return res.status(400).json({ - success: false, - message: '이미 처리된 신청입니다' - }); - } - - // 상태 업데이트 - const statusData = { - status: 'approved', - reviewed_by, - review_note - }; - - vacationRequestModel.updateStatus(id, statusData, (err, result) => { - if (err) { - console.error('휴가 승인 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 승인 중 오류가 발생했습니다' - }); - } - - // TODO: 잔여 연차에서 차감 로직 구현 필요 - // 현재는 연차 차감 없이 승인만 처리 - - res.json({ - success: true, - message: '휴가 신청이 승인되었습니다' - }); - }); - }); + await vacationRequestModel.updateStatus(id, { status: 'approved', reviewed_by, review_note }); + res.json({ success: true, message: '휴가 신청이 승인되었습니다' }); } catch (error) { - console.error('휴가 승인 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('휴가 승인 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } }, @@ -460,68 +218,24 @@ const vacationRequestController = { const { review_note } = req.body; const reviewed_by = req.user.user_id; - // 관리자 권한 확인 if (req.user.access_level !== 'system') { - return res.status(403).json({ - success: false, - message: '관리자만 거부할 수 있습니다' - }); + return res.status(403).json({ success: false, message: '관리자만 거부할 수 있습니다' }); } - // 기존 신청 조회 - vacationRequestModel.getById(id, (err, results) => { - if (err) { - console.error('휴가 신청 조회 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 신청 조회 중 오류가 발생했습니다' - }); - } + const results = await vacationRequestModel.getById(id); + if (results.length === 0) { + return res.status(404).json({ success: false, message: '해당 휴가 신청을 찾을 수 없습니다' }); + } - if (results.length === 0) { - return res.status(404).json({ - success: false, - message: '해당 휴가 신청을 찾을 수 없습니다' - }); - } + if (results[0].status !== 'pending') { + return res.status(400).json({ success: false, message: '이미 처리된 신청입니다' }); + } - const request = results[0]; - - if (request.status !== 'pending') { - return res.status(400).json({ - success: false, - message: '이미 처리된 신청입니다' - }); - } - - // 상태 업데이트 - const statusData = { - status: 'rejected', - reviewed_by, - review_note - }; - - vacationRequestModel.updateStatus(id, statusData, (err, result) => { - if (err) { - console.error('휴가 거부 오류:', err); - return res.status(500).json({ - success: false, - message: '휴가 거부 중 오류가 발생했습니다' - }); - } - - res.json({ - success: true, - message: '휴가 신청이 거부되었습니다' - }); - }); - }); + await vacationRequestModel.updateStatus(id, { status: 'rejected', reviewed_by, review_note }); + res.json({ success: true, message: '휴가 신청이 거부되었습니다' }); } catch (error) { - console.error('휴가 거부 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('휴가 거부 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } }, @@ -530,34 +244,15 @@ const vacationRequestController = { */ async getPendingRequests(req, res) { try { - // 관리자 권한 확인 if (req.user.access_level !== 'system') { - return res.status(403).json({ - success: false, - message: '관리자만 조회할 수 있습니다' - }); + return res.status(403).json({ success: false, message: '관리자만 조회할 수 있습니다' }); } - vacationRequestModel.getAllPending((err, results) => { - if (err) { - console.error('대기 중인 휴가 신청 조회 오류:', err); - return res.status(500).json({ - success: false, - message: '대기 중인 휴가 신청 조회 중 오류가 발생했습니다' - }); - } - - res.json({ - success: true, - data: results - }); - }); + const results = await vacationRequestModel.getAllPending(); + res.json({ success: true, data: results }); } catch (error) { - console.error('대기 중인 휴가 신청 조회 오류:', error); - res.status(500).json({ - success: false, - message: '서버 오류가 발생했습니다' - }); + logger.error('대기 중인 휴가 신청 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다' }); } } }; diff --git a/system1-factory/api/models/vacationRequestModel.js b/system1-factory/api/models/vacationRequestModel.js index adee31c..75cae22 100644 --- a/system1-factory/api/models/vacationRequestModel.js +++ b/system1-factory/api/models/vacationRequestModel.js @@ -9,262 +9,191 @@ const vacationRequestModel = { /** * 휴가 신청 생성 */ - async create(requestData, callback) { - try { - const db = await getDb(); - const query = `INSERT INTO vacation_requests SET ?`; - const [result] = await db.query(query, requestData); - callback(null, result); - } catch (error) { - callback(error); - } + async create(requestData) { + const db = await getDb(); + const [result] = await db.query(`INSERT INTO vacation_requests SET ?`, requestData); + return result; }, /** * 휴가 신청 목록 조회 (필터링 지원) */ - async getAll(filters = {}, callback) { - try { - const db = await getDb(); + async getAll(filters = {}) { + const db = await getDb(); - let query = ` - SELECT - vr.*, - w.worker_name, - vt.type_name as vacation_type_name, - vt.deduct_days as vacation_deduct_days, - requester.name as requester_name, - reviewer.name as reviewer_name - FROM vacation_requests vr - INNER JOIN workers w ON vr.worker_id = w.worker_id - INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id - LEFT JOIN users requester ON vr.requested_by = requester.user_id - LEFT JOIN users reviewer ON vr.reviewed_by = reviewer.user_id - WHERE 1=1 - `; + let query = ` + SELECT + vr.*, + w.worker_name, + vt.type_name as vacation_type_name, + vt.deduct_days as vacation_deduct_days, + requester.name as requester_name, + reviewer.name as reviewer_name + FROM vacation_requests vr + INNER JOIN workers w ON vr.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id + LEFT JOIN users requester ON vr.requested_by = requester.user_id + LEFT JOIN users reviewer ON vr.reviewed_by = reviewer.user_id + WHERE 1=1 + `; - const params = []; + const params = []; - // 작업자 필터 - if (filters.worker_id) { - query += ` AND vr.worker_id = ?`; - params.push(filters.worker_id); - } - - // 상태 필터 - if (filters.status) { - query += ` AND vr.status = ?`; - params.push(filters.status); - } - - // 기간 필터 - if (filters.start_date) { - query += ` AND vr.start_date >= ?`; - params.push(filters.start_date); - } - - if (filters.end_date) { - query += ` AND vr.end_date <= ?`; - params.push(filters.end_date); - } - - // 휴가 유형 필터 - if (filters.vacation_type_id) { - query += ` AND vr.vacation_type_id = ?`; - params.push(filters.vacation_type_id); - } - - query += ` ORDER BY vr.created_at DESC`; - - const [rows] = await db.query(query, params); - callback(null, rows); - } catch (error) { - callback(error); + if (filters.worker_id) { + query += ` AND vr.worker_id = ?`; + params.push(filters.worker_id); } + if (filters.status) { + query += ` AND vr.status = ?`; + params.push(filters.status); + } + if (filters.start_date) { + query += ` AND vr.start_date >= ?`; + params.push(filters.start_date); + } + if (filters.end_date) { + query += ` AND vr.end_date <= ?`; + params.push(filters.end_date); + } + if (filters.vacation_type_id) { + query += ` AND vr.vacation_type_id = ?`; + params.push(filters.vacation_type_id); + } + + query += ` ORDER BY vr.created_at DESC`; + + const [rows] = await db.query(query, params); + return rows; }, /** * 특정 휴가 신청 조회 */ - async getById(requestId, callback) { - try { - const db = await getDb(); - const query = ` - SELECT - vr.*, - w.worker_name, - w.phone_number as worker_phone, - w.email as worker_email, - vt.type_name as vacation_type_name, - vt.type_code as vacation_type_code, - vt.deduct_days as vacation_deduct_days, - requester.name as requester_name, - requester.username as requester_username, - reviewer.name as reviewer_name, - reviewer.username as reviewer_username - FROM vacation_requests vr - INNER JOIN workers w ON vr.worker_id = w.worker_id - INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id - LEFT JOIN users requester ON vr.requested_by = requester.user_id - LEFT JOIN users reviewer ON vr.reviewed_by = reviewer.user_id - WHERE vr.request_id = ? - `; - const [rows] = await db.query(query, [requestId]); - callback(null, rows); - } catch (error) { - callback(error); - } + async getById(requestId) { + const db = await getDb(); + const [rows] = await db.query(` + SELECT + vr.*, + w.worker_name, + w.phone_number as worker_phone, + w.email as worker_email, + vt.type_name as vacation_type_name, + vt.type_code as vacation_type_code, + vt.deduct_days as vacation_deduct_days, + requester.name as requester_name, + requester.username as requester_username, + reviewer.name as reviewer_name, + reviewer.username as reviewer_username + FROM vacation_requests vr + INNER JOIN workers w ON vr.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id + LEFT JOIN users requester ON vr.requested_by = requester.user_id + LEFT JOIN users reviewer ON vr.reviewed_by = reviewer.user_id + WHERE vr.request_id = ? + `, [requestId]); + return rows; }, /** * 휴가 신청 수정 */ - async update(requestId, updateData, callback) { - try { - const db = await getDb(); - const query = `UPDATE vacation_requests SET ? WHERE request_id = ?`; - const [result] = await db.query(query, [updateData, requestId]); - callback(null, result); - } catch (error) { - callback(error); - } + async update(requestId, updateData) { + const db = await getDb(); + const [result] = await db.query(`UPDATE vacation_requests SET ? WHERE request_id = ?`, [updateData, requestId]); + return result; }, /** * 휴가 신청 삭제 */ - async delete(requestId, callback) { - try { - const db = await getDb(); - const query = `DELETE FROM vacation_requests WHERE request_id = ?`; - const [result] = await db.query(query, [requestId]); - callback(null, result); - } catch (error) { - callback(error); - } + async delete(requestId) { + const db = await getDb(); + const [result] = await db.query(`DELETE FROM vacation_requests WHERE request_id = ?`, [requestId]); + return result; }, /** * 휴가 신청 승인/거부 */ - async updateStatus(requestId, statusData, callback) { - try { - const db = await getDb(); - const query = ` - UPDATE vacation_requests - SET - status = ?, - reviewed_by = ?, - reviewed_at = NOW(), - review_note = ? - WHERE request_id = ? - `; - const [result] = await db.query(query, [ - statusData.status, - statusData.reviewed_by, - statusData.review_note || null, - requestId - ]); - callback(null, result); - } catch (error) { - callback(error); - } + async updateStatus(requestId, statusData) { + const db = await getDb(); + const [result] = await db.query(` + UPDATE vacation_requests + SET status = ?, reviewed_by = ?, reviewed_at = NOW(), review_note = ? + WHERE request_id = ? + `, [statusData.status, statusData.reviewed_by, statusData.review_note || null, requestId]); + return result; }, /** * 특정 작업자의 대기 중인 휴가 신청 수 */ - async getPendingCount(workerId, callback) { - try { - const db = await getDb(); - const query = ` - SELECT COUNT(*) as count - FROM vacation_requests - WHERE worker_id = ? AND status = 'pending' - `; - const [rows] = await db.query(query, [workerId]); - callback(null, rows); - } catch (error) { - callback(error); - } + async getPendingCount(workerId) { + const db = await getDb(); + const [rows] = await db.query(` + SELECT COUNT(*) as count FROM vacation_requests + WHERE worker_id = ? AND status = 'pending' + `, [workerId]); + return rows; }, /** * 특정 작업자의 승인된 휴가 일수 합계 (특정 기간) */ - async getApprovedDaysInPeriod(workerId, startDate, endDate, callback) { - try { - const db = await getDb(); - const query = ` - SELECT COALESCE(SUM(days_used), 0) as total_days - FROM vacation_requests - WHERE worker_id = ? - AND status = 'approved' - AND start_date >= ? - AND end_date <= ? - `; - const [rows] = await db.query(query, [workerId, startDate, endDate]); - callback(null, rows); - } catch (error) { - callback(error); - } + async getApprovedDaysInPeriod(workerId, startDate, endDate) { + const db = await getDb(); + const [rows] = await db.query(` + SELECT COALESCE(SUM(days_used), 0) as total_days FROM vacation_requests + WHERE worker_id = ? AND status = 'approved' AND start_date >= ? AND end_date <= ? + `, [workerId, startDate, endDate]); + return rows; }, /** * 휴가 기간 중복 체크 */ - async checkOverlap(workerId, startDate, endDate, excludeRequestId = null, callback) { - try { - const db = await getDb(); - let query = ` - SELECT COUNT(*) as count - FROM vacation_requests - WHERE worker_id = ? - AND status IN ('pending', 'approved') - AND ( - (start_date <= ? AND end_date >= ?) OR - (start_date <= ? AND end_date >= ?) OR - (start_date >= ? AND end_date <= ?) - ) - `; - const params = [workerId, startDate, startDate, endDate, endDate, startDate, endDate]; + async checkOverlap(workerId, startDate, endDate, excludeRequestId = null) { + const db = await getDb(); + let query = ` + SELECT COUNT(*) as count FROM vacation_requests + WHERE worker_id = ? + AND status IN ('pending', 'approved') + AND ( + (start_date <= ? AND end_date >= ?) OR + (start_date <= ? AND end_date >= ?) OR + (start_date >= ? AND end_date <= ?) + ) + `; + const params = [workerId, startDate, startDate, endDate, endDate, startDate, endDate]; - if (excludeRequestId) { - query += ` AND request_id != ?`; - params.push(excludeRequestId); - } - - const [rows] = await db.query(query, params); - callback(null, rows); - } catch (error) { - callback(error); + if (excludeRequestId) { + query += ` AND request_id != ?`; + params.push(excludeRequestId); } + + const [rows] = await db.query(query, params); + return rows; }, /** * 모든 대기 중인 휴가 신청 (관리자용) */ - async getAllPending(callback) { - try { - const db = await getDb(); - const query = ` - SELECT - vr.*, - w.worker_name, - vt.type_name as vacation_type_name, - requester.name as requester_name - FROM vacation_requests vr - INNER JOIN workers w ON vr.worker_id = w.worker_id - INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id - LEFT JOIN users requester ON vr.requested_by = requester.user_id - WHERE vr.status = 'pending' - ORDER BY vr.created_at ASC - `; - const [rows] = await db.query(query); - callback(null, rows); - } catch (error) { - callback(error); - } + async getAllPending() { + const db = await getDb(); + const [rows] = await db.query(` + SELECT + vr.*, + w.worker_name, + vt.type_name as vacation_type_name, + requester.name as requester_name + FROM vacation_requests vr + INNER JOIN workers w ON vr.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id + LEFT JOIN users requester ON vr.requested_by = requester.user_id + WHERE vr.status = 'pending' + ORDER BY vr.created_at ASC + `); + return rows; } };