feat(attendance): 주말+회사 휴무일 통합 처리

- monthlyComparisonModel: getCompanyHolidays 추가
- monthlyComparisonController: isHoliday에 company_holidays 포함 + holiday_name
- proxyInputModel: getDailyStatus에 is_holiday/holiday_name 추가
- proxy-input.js: 휴무일 배너 + both_missing 작업자 비활성화 (특근자는 활성 유지)
- 마이그레이션: 2026년 공휴일 16건 일괄 INSERT

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-31 13:29:37 +09:00
parent 5054398f4f
commit f728f84117
7 changed files with 107 additions and 12 deletions

View File

@@ -2,6 +2,26 @@
const { getDb } = require('../dbPool');
const MonthlyComparisonModel = {
// 0. 해당 월의 회사 휴무일 조회
async getCompanyHolidays(year, month) {
const db = await getDb();
const [rows] = await db.query(
`SELECT holiday_date, holiday_name FROM company_holidays
WHERE YEAR(holiday_date) = ? AND MONTH(holiday_date) = ?`,
[year, month]
);
const dateSet = new Set();
const nameMap = {};
rows.forEach(r => {
const d = r.holiday_date instanceof Date
? r.holiday_date.toISOString().split('T')[0]
: String(r.holiday_date).split('T')[0];
dateSet.add(d);
nameMap[d] = r.holiday_name;
});
return { dateSet, nameMap };
},
// 1. 작업보고서 일별 합산
async getWorkReports(userId, year, month) {
const db = await getDb();

View File

@@ -110,6 +110,16 @@ const ProxyInputModel = {
WHERE dar.record_date = ? AND dar.vacation_type_id IS NOT NULL
`, [date]);
// 5. 해당 날짜가 회사 휴무일인지 확인
const [holidayRows] = await db.query(
`SELECT holiday_date, holiday_name FROM company_holidays WHERE holiday_date = ?`,
[date]
);
const isCompanyHoliday = holidayRows.length > 0;
const holidayName = isCompanyHoliday ? holidayRows[0].holiday_name : null;
const dateObj = new Date(date);
const isWeekend = dateObj.getDay() === 0 || dateObj.getDay() === 6;
// 메모리에서 조합
const tbmMap = {};
tbmAssignments.forEach(ta => {
@@ -158,6 +168,8 @@ const ProxyInputModel = {
return {
date,
is_holiday: isWeekend || isCompanyHoliday,
holiday_name: isCompanyHoliday ? holidayName : (isWeekend ? '주말' : null),
summary: {
total_active_workers: workers.length,
tbm_completed: tbmCompleted,