import { query, execute, insertReturning } from './db' import { getLastWeekInfo, formatDate } from './week-calc' let isRunning = false /** * 주간보고 취합 실행 */ export async function aggregateWeeklyReports(targetYear?: number, targetWeek?: number) { const weekInfo = targetYear && targetWeek ? { year: targetYear, week: targetWeek } : getLastWeekInfo() console.log(`[Aggregator] 취합 시작: ${weekInfo.year}-W${weekInfo.week}`) // 해당 주차에 제출된 보고서가 있는 프로젝트 조회 const projects = await query(` SELECT DISTINCT project_id FROM wr_weekly_report_detail WHERE report_year = $1 AND report_week = $2 AND report_status = 'SUBMITTED' `, [weekInfo.year, weekInfo.week]) let aggregatedCount = 0 for (const { project_id } of projects) { // 해당 프로젝트의 제출된 보고서들 const reports = await query(` SELECT report_id, work_hours FROM wr_weekly_report_detail WHERE project_id = $1 AND report_year = $2 AND report_week = $3 AND report_status = 'SUBMITTED' `, [project_id, weekInfo.year, weekInfo.week]) const reportIds = reports.map((r: any) => r.report_id) const totalHours = reports.reduce((sum: number, r: any) => sum + (parseFloat(r.work_hours) || 0), 0) // 주차 날짜 계산 const jan4 = new Date(weekInfo.year, 0, 4) const firstMonday = new Date(jan4) firstMonday.setDate(jan4.getDate() - ((jan4.getDay() + 6) % 7)) const targetMonday = new Date(firstMonday) targetMonday.setDate(firstMonday.getDate() + (weekInfo.week - 1) * 7) const targetSunday = new Date(targetMonday) targetSunday.setDate(targetMonday.getDate() + 6) // UPSERT 취합 보고서 await execute(` INSERT INTO wr_aggregated_report_summary ( project_id, report_year, report_week, week_start_date, week_end_date, report_ids, member_count, total_work_hours ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (project_id, report_year, report_week) DO UPDATE SET report_ids = $6, member_count = $7, total_work_hours = $8, aggregated_at = NOW(), updated_at = NOW() `, [ project_id, weekInfo.year, weekInfo.week, formatDate(targetMonday), formatDate(targetSunday), reportIds, reportIds.length, totalHours || null ]) // 개별 보고서 상태 변경 await execute(` UPDATE wr_weekly_report_detail SET report_status = 'AGGREGATED', updated_at = NOW() WHERE report_id = ANY($1) `, [reportIds]) aggregatedCount++ console.log(`[Aggregator] 프로젝트 ${project_id}: ${reportIds.length}건 취합`) } console.log(`[Aggregator] 취합 완료: ${aggregatedCount}개 프로젝트`) return { year: weekInfo.year, week: weekInfo.week, projectCount: aggregatedCount } } /** * 스케줄러 상태 */ export function getSchedulerStatus() { return { isRunning } }