feat(vacation): 이월연차 만료 시스템 + 대시보드 합산 개선

- createBalance/bulkUpsert에서 CARRY_OVER expires_at 자동 설정
  (carry_over_expiry_month 설정 기반, 기본값 2월말)
- deductByPriority/deductDays 쿼리에 만료 필터 추가
  (expires_at >= CURDATE() 조건, 만료된 이월 차감 제외)
- 대시보드 합산에서 만료된 잔액 제외
- DB 보정 완료: CARRY_OVER 8건 expires_at 설정,
  황인용/최광욱 소급 재계산 (이월 우선 차감 반영)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-04-01 12:27:17 +09:00
parent 58b756d973
commit ba2e3481e9
4 changed files with 25 additions and 5 deletions

View File

@@ -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++;
}