/** * vacationRequestModel.js * 휴가 신청 관련 데이터베이스 쿼리 모델 */ const { getDb } = require('../dbPool'); const vacationRequestModel = { /** * 휴가 신청 생성 */ async create(requestData) { const db = await getDb(); const [result] = await db.query(`INSERT INTO vacation_requests SET ?`, requestData); return result; }, /** * 휴가 신청 목록 조회 (필터링 지원) */ 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 `; 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); return rows; }, /** * 특정 휴가 신청 조회 */ 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) { const db = await getDb(); const [result] = await db.query(`UPDATE vacation_requests SET ? WHERE request_id = ?`, [updateData, requestId]); return result; }, /** * 휴가 신청 삭제 */ 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) { 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) { 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) { 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) { 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); return rows; }, /** * 모든 대기 중인 휴가 신청 (관리자용) */ 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; } }; module.exports = vacationRequestModel;