import { PrismaClient } from '@prisma/client'; // Initialize Prisma client const prisma = new PrismaClient(); export default defineEventHandler(async (event) => { try { // Get query parameters for filtering (optional) const query = getQuery(event); const { startDate, endDate, category, status } = query; // Build date filter const dateFilter = {}; if (startDate && endDate) { dateFilter.processCreatedDate = { gte: new Date(startDate), lte: new Date(endDate) }; } // Build process filter const processFilter = { ...dateFilter }; if (category) { processFilter.processCategory = category; } if (status) { processFilter.processStatus = status; } // Get process statistics const [ totalProcesses, publishedProcesses, draftProcesses, archivedProcesses, deletedProcesses, processCategories ] = await Promise.all([ // Total processes prisma.process.count({ where: processFilter }), // Published processes prisma.process.count({ where: { ...processFilter, processStatus: 'published' } }), // Draft processes prisma.process.count({ where: { ...processFilter, processStatus: 'draft' } }), // Archived processes prisma.process.count({ where: { ...processFilter, processStatus: 'archived' } }), // Deleted processes prisma.process.count({ where: { ...processFilter, processStatus: 'deleted' } }), // Process categories distribution prisma.process.groupBy({ by: ['processCategory'], where: processFilter, _count: { processCategory: true } }) ]); // Get case instance statistics const [ totalCases, activeCases, completedCases, casesByStatus ] = await Promise.all([ // Total case instances prisma.caseInstance.count(), // Active cases prisma.caseInstance.count({ where: { caseStatus: 'active' } }), // Completed cases prisma.caseInstance.count({ where: { caseStatus: 'completed' } }), // Cases by status prisma.caseInstance.groupBy({ by: ['caseStatus'], _count: { caseStatus: true } }) ]); // Get task statistics const [ totalTasks, pendingTasks, completedTasks, overdueTasks ] = await Promise.all([ // Total tasks prisma.task.count(), // Pending tasks prisma.task.count({ where: { taskStatus: 'pending' } }), // Completed tasks prisma.task.count({ where: { taskStatus: 'completed' } }), // Overdue tasks (pending tasks created more than 3 days ago) prisma.task.count({ where: { taskStatus: 'pending', taskCreatedDate: { lt: new Date(Date.now() - 3 * 24 * 60 * 60 * 1000) // 3 days ago } } }) ]); // Calculate average completion time for completed cases const completedCasesWithTime = await prisma.caseInstance.findMany({ where: { caseStatus: 'completed', caseCompletedDate: { not: null } }, select: { caseCreatedDate: true, caseCompletedDate: true } }); let averageCompletionTime = 0; if (completedCasesWithTime.length > 0) { const totalCompletionTime = completedCasesWithTime.reduce((sum, case_) => { const diffMs = new Date(case_.caseCompletedDate) - new Date(case_.caseCreatedDate); const diffHours = diffMs / (1000 * 60 * 60); return sum + diffHours; }, 0); averageCompletionTime = Math.round((totalCompletionTime / completedCasesWithTime.length) * 10) / 10; } // Calculate success rate (completed cases / total cases * 100) const successRate = totalCases > 0 ? Math.round((completedCases / totalCases) * 1000) / 10 : 0; // Get recent activity (latest case instances and process updates) const recentCases = await prisma.caseInstance.findMany({ take: 5, orderBy: { caseCreatedDate: 'desc' }, include: { process: { select: { processName: true } }, startedBy: { select: { userFullName: true, userUsername: true } } } }); const recentProcessUpdates = await prisma.process.findMany({ take: 5, orderBy: { processModifiedDate: 'desc' }, where: { processModifiedDate: { not: null } }, include: { creator: { select: { userFullName: true, userUsername: true } } } }); // Format recent activity const recentActivity = []; // Add recent cases recentCases.forEach(case_ => { recentActivity.push({ id: `case-${case_.caseID}`, type: case_.caseStatus === 'completed' ? 'case_completed' : 'case_started', message: `${case_.process.processName} case ${case_.caseStatus === 'completed' ? 'completed' : 'started'}`, user: case_.startedBy?.userFullName || case_.startedBy?.userUsername || 'Unknown', timestamp: case_.caseStatus === 'completed' ? case_.caseCompletedDate : case_.caseCreatedDate }); }); // Add recent process updates recentProcessUpdates.forEach(process => { recentActivity.push({ id: `process-${process.processID}`, type: process.processStatus === 'published' ? 'process_published' : 'process_updated', message: `${process.processName} process ${process.processStatus === 'published' ? 'published' : 'updated'}`, user: process.creator?.userFullName || process.creator?.userUsername || 'Unknown', timestamp: process.processModifiedDate }); }); // Sort recent activity by timestamp and take the latest 10 recentActivity.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp)); const latestActivity = recentActivity.slice(0, 10); // Get monthly statistics for the last 6 months const sixMonthsAgo = new Date(); sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6); const monthlyCases = await prisma.caseInstance.groupBy({ by: ['caseCreatedDate'], where: { caseCreatedDate: { gte: sixMonthsAgo } }, _count: { caseID: true } }); // Process monthly data const monthlyStats = []; for (let i = 5; i >= 0; i--) { const date = new Date(); date.setMonth(date.getMonth() - i); const monthKey = date.toISOString().substring(0, 7); // YYYY-MM format const monthData = monthlyCases.filter(item => item.caseCreatedDate.toISOString().substring(0, 7) === monthKey ); monthlyStats.push({ month: date.toLocaleString('default', { month: 'short' }), year: date.getFullYear(), cases: monthData.length, completed: 0 // Would need additional query to get completed cases for the month }); } // Prepare response const summary = { overview: { totalProcesses, publishedProcesses, draftProcesses, archivedProcesses, deletedProcesses, totalCases, activeCases, completedCases, totalTasks, pendingTasks, completedTasks, overdueTasks, averageCompletionTime, successRate }, charts: { processDistribution: [ { label: 'Published', value: publishedProcesses, color: '#10B981' }, { label: 'Draft', value: draftProcesses, color: '#F59E0B' }, { label: 'Archived', value: archivedProcesses, color: '#6B7280' }, { label: 'Deleted', value: deletedProcesses, color: '#EF4444' } ], caseStatus: casesByStatus.map(item => ({ label: item.caseStatus, value: item._count.caseStatus, color: item.caseStatus === 'active' ? '#3B82F6' : item.caseStatus === 'completed' ? '#10B981' : '#6B7280' })), categoryDistribution: processCategories.map(item => ({ label: item.processCategory || 'Uncategorized', value: item._count.processCategory })), monthlyTrend: monthlyStats }, recentActivity: latestActivity, lastUpdated: new Date().toISOString() }; return { success: true, data: summary }; } catch (error) { console.error('Error fetching dashboard summary:', error); return { success: false, error: 'Failed to fetch dashboard summary', details: process.env.NODE_ENV === 'development' ? error.message : undefined }; } finally { await prisma.$disconnect(); } });