Files
helpdesk-texnet/backend/src/controllers/projects.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

289 lines
8.7 KiB
TypeScript

import { Response } from 'express';
import prisma from '../config/database';
import { successResponse, errorResponse, paginatedResponse, parseQueryInt, getParam, getQueryString } from '../utils/helpers';
import { AuthRequest } from '../middleware/auth.middleware';
import { configService } from '../services/config.service';
export const getProjects = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const page = parseQueryInt(req.query.page, 1);
const limit = parseQueryInt(req.query.limit, 20);
const skip = (page - 1) * limit;
const search = getQueryString(req, 'search');
const statusId = getQueryString(req, 'statusId');
const customerId = getQueryString(req, 'customerId');
const ownerId = getQueryString(req, 'ownerId');
const where = {
...(statusId && { statusId }),
...(customerId && { customerId }),
...(ownerId && { ownerId }),
...(search && {
OR: [
{ name: { contains: search, mode: 'insensitive' as const } },
{ description: { contains: search, mode: 'insensitive' as const } },
],
}),
};
const [projects, total] = await Promise.all([
prisma.project.findMany({
where,
skip,
take: limit,
orderBy: { createdAt: 'desc' },
include: {
status: true,
customer: { select: { id: true, name: true } },
owner: { select: { id: true, name: true, email: true } },
_count: { select: { tasks: true, members: true } },
},
}),
prisma.project.count({ where }),
]);
paginatedResponse(res, projects, total, page, limit);
} catch (error) {
console.error('Error fetching projects:', error);
errorResponse(res, 'Chyba pri načítaní projektov.', 500);
}
};
export const getProject = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const id = getParam(req, 'id');
const project = await prisma.project.findUnique({
where: { id },
include: {
status: true,
customer: true,
owner: { select: { id: true, name: true, email: true } },
members: {
include: {
user: { select: { id: true, name: true, email: true } },
},
},
tags: { include: { tag: true } },
_count: { select: { tasks: true } },
},
});
if (!project) {
errorResponse(res, 'Projekt nebol nájdený.', 404);
return;
}
successResponse(res, project);
} catch (error) {
console.error('Error fetching project:', error);
errorResponse(res, 'Chyba pri načítaní projektu.', 500);
}
};
export const createProject = async (req: AuthRequest, res: Response): Promise<void> => {
try {
let { statusId } = req.body;
// Get initial status if not provided
if (!statusId) {
const initialStatus = await configService.getInitialTaskStatus();
if (initialStatus) {
statusId = initialStatus.id;
} else {
// Fallback: vezmi prvý aktívny status
const allStatuses = await configService.getTaskStatuses();
const statuses = allStatuses as { id: string }[];
if (statuses.length > 0) {
statusId = statuses[0].id;
} else {
errorResponse(res, 'Žiadny status nie je nakonfigurovaný. Spustite seed.', 500);
return;
}
}
}
const project = await prisma.project.create({
data: {
name: req.body.name,
description: req.body.description,
customerId: req.body.customerId || null,
ownerId: req.user!.userId,
statusId,
softDeadline: req.body.softDeadline ? new Date(req.body.softDeadline) : null,
hardDeadline: req.body.hardDeadline ? new Date(req.body.hardDeadline) : null,
},
include: {
status: true,
customer: { select: { id: true, name: true } },
owner: { select: { id: true, name: true } },
},
});
if (req.logActivity) {
await req.logActivity('CREATE', 'Project', project.id, { name: project.name });
}
successResponse(res, project, 'Projekt bol vytvorený.', 201);
} catch (error) {
console.error('Error creating project:', error);
errorResponse(res, 'Chyba pri vytváraní projektu.', 500);
}
};
export const updateProject = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const id = getParam(req, 'id');
const existing = await prisma.project.findUnique({ where: { id } });
if (!existing) {
errorResponse(res, 'Projekt nebol nájdený.', 404);
return;
}
const updateData: Record<string, unknown> = {};
if (req.body.name) updateData.name = req.body.name;
if (req.body.description !== undefined) updateData.description = req.body.description;
if (req.body.customerId !== undefined) updateData.customerId = req.body.customerId || null;
if (req.body.statusId) updateData.statusId = req.body.statusId;
if (req.body.softDeadline !== undefined) {
updateData.softDeadline = req.body.softDeadline ? new Date(req.body.softDeadline) : null;
}
if (req.body.hardDeadline !== undefined) {
updateData.hardDeadline = req.body.hardDeadline ? new Date(req.body.hardDeadline) : null;
}
const project = await prisma.project.update({
where: { id },
data: updateData,
include: {
status: true,
customer: { select: { id: true, name: true } },
owner: { select: { id: true, name: true } },
},
});
if (req.logActivity) {
await req.logActivity('UPDATE', 'Project', id, updateData);
}
successResponse(res, project, 'Projekt bol aktualizovaný.');
} catch (error) {
console.error('Error updating project:', error);
errorResponse(res, 'Chyba pri aktualizácii projektu.', 500);
}
};
export const deleteProject = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const id = getParam(req, 'id');
const project = await prisma.project.findUnique({ where: { id } });
if (!project) {
errorResponse(res, 'Projekt nebol nájdený.', 404);
return;
}
await prisma.project.delete({ where: { id } });
if (req.logActivity) {
await req.logActivity('DELETE', 'Project', id);
}
successResponse(res, null, 'Projekt bol vymazaný.');
} catch (error) {
console.error('Error deleting project:', error);
errorResponse(res, 'Chyba pri mazaní projektu.', 500);
}
};
export const updateProjectStatus = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const id = getParam(req, 'id');
const { statusId } = req.body;
const project = await prisma.project.update({
where: { id },
data: { statusId },
include: { status: true },
});
if (req.logActivity) {
await req.logActivity('STATUS_CHANGE', 'Project', id, { statusId });
}
successResponse(res, project, 'Status projektu bol zmenený.');
} catch (error) {
console.error('Error updating project status:', error);
errorResponse(res, 'Chyba pri zmene statusu.', 500);
}
};
export const getProjectTasks = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const id = getParam(req, 'id');
const tasks = await prisma.task.findMany({
where: { projectId: id },
include: {
status: true,
priority: true,
assignees: {
include: { user: { select: { id: true, name: true } } },
},
},
orderBy: [{ priority: { level: 'desc' } }, { createdAt: 'desc' }],
});
successResponse(res, tasks);
} catch (error) {
console.error('Error fetching project tasks:', error);
errorResponse(res, 'Chyba pri načítaní úloh.', 500);
}
};
export const addProjectMember = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const id = getParam(req, 'id');
const { userId } = req.body;
const member = await prisma.projectMember.create({
data: {
projectId: id,
userId,
},
include: {
user: { select: { id: true, name: true, email: true } },
},
});
successResponse(res, member, 'Člen bol pridaný.', 201);
} catch (error) {
console.error('Error adding project member:', error);
errorResponse(res, 'Chyba pri pridávaní člena.', 500);
}
};
export const removeProjectMember = async (req: AuthRequest, res: Response): Promise<void> => {
try {
const id = getParam(req, 'id');
const userId = getParam(req, 'userId');
await prisma.projectMember.delete({
where: {
projectId_userId: {
projectId: id,
userId,
},
},
});
successResponse(res, null, 'Člen bol odstránený.');
} catch (error) {
console.error('Error removing project member:', error);
errorResponse(res, 'Chyba pri odstraňovaní člena.', 500);
}
};