import { query, queryOne } from '../../../../utils/db' /** * 주간보고 상세 조회 * GET /api/report/weekly/[id]/detail */ export default defineEventHandler(async (event) => { const userId = getCookie(event, 'user_id') if (!userId) { throw createError({ statusCode: 401, message: '로그인이 필요합니다.' }) } const reportId = getRouterParam(event, 'id') // 마스터 조회 const report = await queryOne(` SELECT r.*, e.employee_name as author_name, e.employee_email as author_email FROM wr_weekly_report r JOIN wr_employee_info e ON r.author_id = e.employee_id WHERE r.report_id = $1 `, [reportId]) if (!report) { throw createError({ statusCode: 404, message: '보고서를 찾을 수 없습니다.' }) } // 같은 주차의 이전/다음 보고서 조회 const prevReport = await queryOne(` SELECT r.report_id, e.employee_name FROM wr_weekly_report r JOIN wr_employee_info e ON r.author_id = e.employee_id WHERE r.report_year = $1 AND r.report_week = $2 AND r.report_id < $3 ORDER BY r.report_id DESC LIMIT 1 `, [report.report_year, report.report_week, reportId]) const nextReport = await queryOne(` SELECT r.report_id, e.employee_name FROM wr_weekly_report r JOIN wr_employee_info e ON r.author_id = e.employee_id WHERE r.report_year = $1 AND r.report_week = $2 AND r.report_id > $3 ORDER BY r.report_id ASC LIMIT 1 `, [report.report_year, report.report_week, reportId]) // Task 조회 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 FROM wr_weekly_report_task t JOIN wr_project_info p ON t.project_id = p.project_id WHERE t.report_id = $1 ORDER BY t.project_id, t.task_type, t.task_id `, [reportId]) // 프로젝트별로 그룹핑 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: [] }) } 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 } if (task.task_type === 'WORK') { proj.workTasks.push(taskItem) } else { proj.planTasks.push(taskItem) } } return { report: { reportId: report.report_id, authorId: report.author_id, authorName: report.author_name, authorEmail: report.author_email, reportYear: report.report_year, reportWeek: report.report_week, weekStartDate: formatDateOnly(report.week_start_date), weekEndDate: formatDateOnly(report.week_end_date), issueDescription: report.issue_description, vacationDescription: report.vacation_description, remarkDescription: report.remark_description, reportStatus: report.report_status, submittedAt: report.submitted_at, createdAt: report.created_at, updatedAt: report.updated_at, aiReview: report.ai_review, aiReviewAt: report.ai_review_at }, prevReport: prevReport ? { reportId: prevReport.report_id, authorName: prevReport.employee_name } : null, nextReport: nextReport ? { reportId: nextReport.report_id, authorName: nextReport.employee_name } : null, projects: Array.from(projectMap.values()), tasks: tasks.map((t: any) => ({ taskId: t.task_id, projectId: t.project_id, projectCode: t.project_code, projectName: t.project_name, taskType: t.task_type, taskDescription: t.task_description, taskHours: parseFloat(t.task_hours) || 0, isCompleted: t.is_completed })) } }) // 날짜를 YYYY-MM-DD 형식으로 변환 (타임존 보정) function formatDateOnly(date: Date | string | null): string { if (!date) return '' const d = new Date(date) const kstOffset = 9 * 60 * 60 * 1000 const kstDate = new Date(d.getTime() + kstOffset) return kstDate.toISOString().split('T')[0] }