diff --git a/system1-factory/api/controllers/dashboardController.js b/system1-factory/api/controllers/dashboardController.js index a43eaa3..c38de64 100644 --- a/system1-factory/api/controllers/dashboardController.js +++ b/system1-factory/api/controllers/dashboardController.js @@ -44,9 +44,11 @@ const DashboardController = { remaining: parseFloat(v.remaining_days) || 0 })); - // 모든 balance_type 합산 - const totalDays = vacationRows.reduce((s, v) => s + (parseFloat(v.total_days) || 0), 0); - const usedDays = vacationRows.reduce((s, v) => s + (parseFloat(v.used_days) || 0), 0); + // 만료되지 않은 balance만 합산 (만료된 이월연차 제외) + const today = new Date().toISOString().substring(0, 10); + const activeRows = vacationRows.filter(v => !v.expires_at || v.expires_at >= today); + const totalDays = activeRows.reduce((s, v) => s + (parseFloat(v.total_days) || 0), 0); + const usedDays = activeRows.reduce((s, v) => s + (parseFloat(v.used_days) || 0), 0); const remainingDays = totalDays - usedDays; res.json({ diff --git a/system1-factory/api/models/vacationBalanceModel.js b/system1-factory/api/models/vacationBalanceModel.js index 230bb25..f6babec 100644 --- a/system1-factory/api/models/vacationBalanceModel.js +++ b/system1-factory/api/models/vacationBalanceModel.js @@ -223,6 +223,7 @@ const vacationBalanceModel = { INNER JOIN vacation_types vt ON svb.vacation_type_id = vt.id WHERE svb.user_id = ? AND svb.year = ? AND (svb.total_days - svb.used_days) > 0 + AND (svb.expires_at IS NULL OR svb.expires_at >= CURDATE()) ORDER BY vt.priority ASC, FIELD(svb.balance_type, 'CARRY_OVER', 'AUTO', 'MANUAL', 'LONG_SERVICE', 'COMPANY_GRANT') FOR UPDATE `, [userId, year]); diff --git a/tksupport/api/models/vacationBalanceModel.js b/tksupport/api/models/vacationBalanceModel.js index 66fbe7c..12a2c19 100644 --- a/tksupport/api/models/vacationBalanceModel.js +++ b/tksupport/api/models/vacationBalanceModel.js @@ -97,7 +97,8 @@ const vacationBalanceModel = { const [balances] = await c.query(` SELECT id, total_days, used_days, (total_days - used_days) AS remaining_days, balance_type FROM sp_vacation_balances - WHERE user_id = ? AND year = ? AND (total_days - used_days) > 0 ${excludeClause} + WHERE user_id = ? AND year = ? AND (total_days - used_days) > 0 + AND (expires_at IS NULL OR expires_at >= CURDATE()) ${excludeClause} ORDER BY FIELD(balance_type, 'CARRY_OVER', 'AUTO', 'MANUAL', 'LONG_SERVICE', 'COMPANY_GRANT') FOR UPDATE `, queryParams); diff --git a/user-management/api/models/vacationModel.js b/user-management/api/models/vacationModel.js index 833a6d8..f5f7341 100644 --- a/user-management/api/models/vacationModel.js +++ b/user-management/api/models/vacationModel.js @@ -131,6 +131,14 @@ async function getBalanceById(id) { async function createBalance({ user_id, vacation_type_id, year, total_days, used_days, notes, created_by, balance_type, expires_at }) { const db = getPool(); + // CARRY_OVER일 때 expires_at 미설정이면 자동 계산 + if (balance_type === 'CARRY_OVER' && !expires_at) { + const vacationSettingsModel = require('./vacationSettingsModel'); + const settings = await vacationSettingsModel.loadAsObject(); + const expiryMonth = parseInt(settings.carry_over_expiry_month) || 2; + const lastDay = new Date(year, expiryMonth, 0); // 해당 월 말일 + expires_at = lastDay.toISOString().substring(0, 10); + } 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 (?, ?, ?, ?, ?, ?, ?, ?, ?) @@ -160,13 +168,21 @@ async function deleteBalance(id) { async function bulkUpsertBalances(balances) { const db = getPool(); + const vacationSettingsModel = require('./vacationSettingsModel'); + const settings = await vacationSettingsModel.loadAsObject(); + const expiryMonth = parseInt(settings.carry_over_expiry_month) || 2; let count = 0; for (const b of balances) { + let expiresAt = b.expires_at || null; + if (b.balance_type === 'CARRY_OVER' && !expiresAt) { + const lastDay = new Date(b.year, expiryMonth, 0); + expiresAt = lastDay.toISOString().substring(0, 10); + } 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 (?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE total_days = VALUES(total_days), notes = VALUES(notes)`, - [b.user_id, b.vacation_type_id, b.year, b.total_days ?? 0, b.used_days ?? 0, b.notes || null, b.created_by, b.balance_type || 'AUTO', b.expires_at || null] + [b.user_id, b.vacation_type_id, b.year, b.total_days ?? 0, b.used_days ?? 0, b.notes || null, b.created_by, b.balance_type || 'AUTO', expiresAt] ); count++; }