const { getPool } = require('../middleware/auth'); const vacationBalanceModel = { async getByUserAndYear(userId, year) { const db = getPool(); const [rows] = await db.query(` SELECT vb.*, vb.balance_type, vb.expires_at, vt.type_name, vt.type_code, vt.priority, vt.is_special, (vb.total_days - vb.used_days) as remaining_days FROM sp_vacation_balances vb INNER JOIN vacation_types vt ON vb.vacation_type_id = vt.id WHERE vb.user_id = ? AND (vb.year = ? OR (vb.balance_type = 'LONG_SERVICE' AND vb.expires_at IS NULL)) ORDER BY vt.priority ASC, vt.type_name ASC `, [userId, year]); return rows; }, async getAllByYear(year) { const db = getPool(); const [rows] = await db.query(` SELECT vb.*, vb.balance_type, su.name as user_name, su.username, su.hire_date, su.department_id, COALESCE(d.department_name, '미배정') as department_name, vt.type_name, vt.type_code, vt.priority, (vb.total_days - vb.used_days) as remaining_days FROM sp_vacation_balances vb INNER JOIN sso_users su ON vb.user_id = su.user_id INNER JOIN vacation_types vt ON vb.vacation_type_id = vt.id LEFT JOIN departments d ON su.department_id = d.department_id WHERE (vb.year = ? OR (vb.balance_type = 'LONG_SERVICE' AND vb.expires_at IS NULL)) AND su.is_active = 1 ORDER BY su.name ASC, vt.priority ASC `, [year]); return rows; }, async allocate(data) { const db = getPool(); const balanceType = data.balance_type || 'AUTO'; const expiresAt = data.expires_at || null; const [result] = await db.query(` INSERT INTO sp_vacation_balances (user_id, vacation_type_id, year, total_days, used_days, notes, created_by, balance_type, expires_at) VALUES (?, ?, ?, ?, 0, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE total_days = VALUES(total_days), notes = VALUES(notes), updated_at = NOW() `, [data.user_id, data.vacation_type_id, data.year, data.total_days, data.notes || null, data.created_by, balanceType, expiresAt]); return result; }, 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() WHERE user_id = ? AND vacation_type_id = ? AND year = ? `, [daysToDeduct, userId, vacationTypeId, year]); return result; }, 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() WHERE user_id = ? AND vacation_type_id = ? AND year = ? `, [daysToRestore, userId, vacationTypeId, year]); return result; }, calculateAnnualLeaveDays(hireDate, targetYear) { const hire = new Date(hireDate); const targetDate = new Date(targetYear, 0, 1); const monthsDiff = (targetDate.getFullYear() - hire.getFullYear()) * 12 + (targetDate.getMonth() - hire.getMonth()); if (monthsDiff < 12) { return Math.floor(monthsDiff); } const yearsWorked = Math.floor(monthsDiff / 12); const additionalDays = Math.floor((yearsWorked - 1) / 2); return Math.min(15 + additionalDays, 25); }, async getUserHireDate(userId) { const db = getPool(); const [rows] = await db.query('SELECT hire_date FROM sso_users WHERE user_id = ?', [userId]); return rows.length > 0 ? rows[0].hire_date : null; } }; module.exports = vacationBalanceModel;