1ㅊㅏ완료
This commit is contained in:
131
backend/api/report/weekly/aggregate.get.ts
Normal file
131
backend/api/report/weekly/aggregate.get.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
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<number, {
|
||||
projectId: number
|
||||
projectCode: string
|
||||
projectName: string
|
||||
workTasks: any[]
|
||||
planTasks: any[]
|
||||
totalWorkHours: number
|
||||
totalPlanHours: number
|
||||
}>()
|
||||
|
||||
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())
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user