import { defineEventHandler, getQuery, createError } from 'h3' import { query } from '../../../utils/db' const ADMIN_EMAIL = 'admin@turbosoft.co.kr' export default defineEventHandler(async (event) => { const userEmail = event.node.req.headers['x-user-email'] as string if (!userEmail) { throw createError({ statusCode: 401, message: '로그인이 필요합니다.' }) } // 관리자만 취합 가능 if (userEmail !== ADMIN_EMAIL) { throw createError({ statusCode: 403, message: '관리자만 취합할 수 있습니다.' }) } const { year, week, projectIds } = getQuery(event) if (!year || !week) { throw createError({ statusCode: 400, message: '연도와 주차를 지정해주세요.' }) } // 프로젝트 ID 파싱 let projectIdList: number[] = [] if (projectIds) { projectIdList = String(projectIds).split(',').map(Number).filter(n => !isNaN(n)) } // 해당 주차의 모든 프로젝트별 Task 조회 let projectFilter = '' const params: any[] = [Number(year), Number(week)] if (projectIdList.length > 0) { projectFilter = `AND t.project_id = ANY($3)` params.push(projectIdList) } const tasks = await query(` SELECT t.task_id, t.project_id, p.project_code, p.project_name, t.task_type, t.task_description, t.task_hours, t.is_completed, r.report_id, r.author_id, e.employee_name as author_name FROM wr_weekly_report r JOIN wr_weekly_report_task t ON r.report_id = t.report_id JOIN wr_project_info p ON t.project_id = p.project_id JOIN wr_employee_info e ON r.author_id = e.employee_id WHERE r.report_year = $1 AND r.report_week = $2 ${projectFilter} ORDER BY p.project_name, t.task_type, e.employee_name `, params) // 프로젝트별로 그룹핑 const projectMap = new Map() for (const task of tasks) { if (!projectMap.has(task.project_id)) { projectMap.set(task.project_id, { projectId: task.project_id, projectCode: task.project_code, projectName: task.project_name, workTasks: [], planTasks: [], totalWorkHours: 0, totalPlanHours: 0 }) } const proj = projectMap.get(task.project_id)! const taskItem = { taskId: task.task_id, description: task.task_description, hours: parseFloat(task.task_hours) || 0, isCompleted: task.is_completed, authorName: task.author_name } if (task.task_type === 'WORK') { proj.workTasks.push(taskItem) proj.totalWorkHours += taskItem.hours } else { proj.planTasks.push(taskItem) proj.totalPlanHours += taskItem.hours } } // 해당 주차에 보고서가 있는 모든 프로젝트 목록 const allProjects = await query(` SELECT DISTINCT p.project_id, p.project_code, p.project_name FROM wr_weekly_report r JOIN wr_weekly_report_task t ON r.report_id = t.report_id JOIN wr_project_info p ON t.project_id = p.project_id WHERE r.report_year = $1 AND r.report_week = $2 ORDER BY p.project_name `, [Number(year), Number(week)]) // 해당 주차 보고서 수 const reportCount = await query(` SELECT COUNT(DISTINCT report_id) as cnt FROM wr_weekly_report WHERE report_year = $1 AND report_week = $2 `, [Number(year), Number(week)]) return { year: Number(year), week: Number(week), reportCount: parseInt(reportCount[0]?.cnt || '0'), availableProjects: allProjects.map((p: any) => ({ projectId: p.project_id, projectCode: p.project_code, projectName: p.project_name })), projects: Array.from(projectMap.values()) } })