137 lines
4.2 KiB
TypeScript
137 lines
4.2 KiB
TypeScript
import { query, queryOne } from '../../../../utils/db'
|
|
import { requireAuth } from '../../../../utils/session'
|
|
|
|
/**
|
|
* 주간보고 상세 조회
|
|
* GET /api/report/weekly/[id]/detail
|
|
*/
|
|
export default defineEventHandler(async (event) => {
|
|
const userId = await requireAuth(event)
|
|
|
|
const reportId = getRouterParam(event, 'id')
|
|
|
|
// 마스터 조회
|
|
const report = await queryOne<any>(`
|
|
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<any>(`
|
|
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<any>(`
|
|
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<any>(`
|
|
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<number, any>()
|
|
|
|
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]
|
|
}
|