Files
helpdesk-texnet/backend/src/controllers/dashboard.controller.ts
pettrop e4f63a135e Initial commit: Helpdesk application setup
- Backend: Node.js/TypeScript with Prisma ORM
- Frontend: Vite + TypeScript
- Project configuration and documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 08:53:22 +01:00

334 lines
8.7 KiB
TypeScript

import { Response } from 'express';
import prisma from '../config/database';
import { successResponse, errorResponse } from '../utils/helpers';
import { AuthRequest } from '../middleware/auth.middleware';
// Hlavný dashboard endpoint - štatistiky pre karty
export const getDashboard = async (_req: AuthRequest, res: Response): Promise<void> => {
try {
const today = new Date();
const nextMonth = new Date(today);
nextMonth.setDate(nextMonth.getDate() + 30);
const [
totalProjects,
activeProjects,
totalTasks,
pendingTasks,
inProgressTasks,
totalCustomers,
activeCustomers,
totalEquipment,
upcomingRevisions,
totalRMAs,
pendingRMAs,
] = await Promise.all([
prisma.project.count(),
prisma.project.count({ where: { status: { isFinal: false } } }),
prisma.task.count(),
prisma.task.count({ where: { status: { code: 'NEW' } } }),
prisma.task.count({ where: { status: { code: 'IN_PROGRESS' } } }),
prisma.customer.count(),
prisma.customer.count({ where: { active: true } }),
prisma.equipment.count({ where: { active: true } }),
prisma.revision.count({
where: {
nextDueDate: {
gte: today,
lte: nextMonth,
},
},
}),
prisma.rMA.count(),
prisma.rMA.count({ where: { status: { isFinal: false } } }),
]);
successResponse(res, {
projects: {
total: totalProjects,
active: activeProjects,
},
tasks: {
total: totalTasks,
pending: pendingTasks,
inProgress: inProgressTasks,
},
customers: {
total: totalCustomers,
active: activeCustomers,
},
equipment: {
total: totalEquipment,
upcomingRevisions,
},
rma: {
total: totalRMAs,
pending: pendingRMAs,
},
});
} catch (error) {
console.error('Error fetching dashboard:', error);
errorResponse(res, 'Chyba pri načítaní dashboardu.', 500);
}
};
export const getDashboardToday = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const today = new Date();
today.setHours(0, 0, 0, 0);
const tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
const userId = req.user!.userId;
const [myTasks, myProjects, recentRMAs] = await Promise.all([
// Tasks assigned to me that are not completed
prisma.task.findMany({
where: {
assignees: { some: { userId } },
status: { isFinal: false },
},
include: {
status: true,
priority: true,
project: { select: { id: true, name: true } },
createdBy: { select: { id: true, name: true } },
assignees: { include: { user: { select: { id: true, name: true } } } },
},
orderBy: [{ priority: { level: 'desc' } }, { deadline: 'asc' }],
take: 10,
}),
// My active projects
prisma.project.findMany({
where: {
OR: [
{ ownerId: userId },
{ members: { some: { userId } } },
],
status: { isFinal: false },
},
include: {
status: true,
_count: { select: { tasks: true } },
},
take: 5,
}),
// Recent RMAs
prisma.rMA.findMany({
where: {
OR: [
{ assignedToId: userId },
{ createdById: userId },
],
},
include: {
status: true,
},
orderBy: { createdAt: 'desc' },
take: 5,
}),
]);
successResponse(res, {
myTasks,
myProjects,
recentRMAs,
});
} catch (error) {
console.error('Error fetching dashboard today:', error);
errorResponse(res, 'Chyba pri načítaní dashboardu.', 500);
}
};
export const getDashboardWeek = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const today = new Date();
today.setHours(0, 0, 0, 0);
const nextWeek = new Date(today);
nextWeek.setDate(nextWeek.getDate() + 7);
const userId = req.user!.userId;
const [tasksDeadlineThisWeek, upcomingRevisions] = await Promise.all([
// Tasks with deadline this week
prisma.task.findMany({
where: {
deadline: {
gte: today,
lte: nextWeek,
},
status: { isFinal: false },
OR: [
{ createdById: userId },
{ assignees: { some: { userId } } },
],
},
include: {
status: true,
priority: true,
project: { select: { id: true, name: true } },
assignees: { include: { user: { select: { id: true, name: true } } } },
},
orderBy: { deadline: 'asc' },
}),
// Upcoming equipment revisions
prisma.revision.findMany({
where: {
nextDueDate: {
gte: today,
lte: nextWeek,
},
},
include: {
equipment: {
include: {
type: true,
customer: { select: { id: true, name: true } },
},
},
type: true,
},
orderBy: { nextDueDate: 'asc' },
}),
]);
successResponse(res, {
tasksDeadlineThisWeek,
upcomingRevisions,
});
} catch (error) {
console.error('Error fetching dashboard week:', error);
errorResponse(res, 'Chyba pri načítaní týždenného prehľadu.', 500);
}
};
export const getDashboardStats = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const [
totalProjects,
activeProjects,
totalTasks,
completedTasks,
totalCustomers,
totalEquipment,
totalRMAs,
openRMAs,
] = await Promise.all([
prisma.project.count(),
prisma.project.count({ where: { status: { isFinal: false } } }),
prisma.task.count(),
prisma.task.count({ where: { status: { isFinal: true } } }),
prisma.customer.count({ where: { active: true } }),
prisma.equipment.count({ where: { active: true } }),
prisma.rMA.count(),
prisma.rMA.count({ where: { status: { isFinal: false } } }),
]);
successResponse(res, {
projects: {
total: totalProjects,
active: activeProjects,
},
tasks: {
total: totalTasks,
completed: completedTasks,
completionRate: totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0,
},
customers: {
total: totalCustomers,
},
equipment: {
total: totalEquipment,
},
rmas: {
total: totalRMAs,
open: openRMAs,
},
});
} catch (error) {
console.error('Error fetching dashboard stats:', error);
errorResponse(res, 'Chyba pri načítaní štatistík.', 500);
}
};
export const getDashboardReminders = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const today = new Date();
const nextMonth = new Date(today);
nextMonth.setDate(nextMonth.getDate() + 30);
const userId = req.user!.userId;
const [taskReminders, equipmentRevisions, overdueRMAs] = await Promise.all([
// Task reminders
prisma.reminder.findMany({
where: {
userId,
dismissed: false,
remindAt: {
lte: nextMonth,
},
},
include: {
task: {
include: {
status: true,
project: { select: { id: true, name: true } },
},
},
},
orderBy: { remindAt: 'asc' },
}),
// Equipment revision reminders
prisma.revision.findMany({
where: {
nextDueDate: {
gte: today,
lte: nextMonth,
},
},
include: {
equipment: {
include: {
type: true,
customer: { select: { id: true, name: true } },
},
},
type: true,
},
orderBy: { nextDueDate: 'asc' },
take: 10,
}),
// Overdue or old RMAs
prisma.rMA.findMany({
where: {
status: { isFinal: false },
createdAt: {
lte: new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000), // Older than 7 days
},
},
include: {
status: true,
customer: { select: { id: true, name: true } },
},
orderBy: { createdAt: 'asc' },
take: 10,
}),
]);
successResponse(res, {
taskReminders,
equipmentRevisions,
overdueRMAs,
});
} catch (error) {
console.error('Error fetching dashboard reminders:', error);
errorResponse(res, 'Chyba pri načítaní upomienok.', 500);
}
};