import { db } from '../config/database.js'; import { todos, notes, projects, companies, users } from '../db/schema.js'; import { eq, desc, ilike, or, and } from 'drizzle-orm'; import { NotFoundError } from '../utils/errors.js'; /** * Get all todos * Optionally filter by search, project, company, assigned user, or status */ export const getAllTodos = async (filters = {}) => { const { searchTerm, projectId, companyId, assignedTo, status } = filters; let query = db.select().from(todos); const conditions = []; if (searchTerm) { conditions.push( or( ilike(todos.title, `%${searchTerm}%`), ilike(todos.description, `%${searchTerm}%`) ) ); } if (projectId) { conditions.push(eq(todos.projectId, projectId)); } if (companyId) { conditions.push(eq(todos.companyId, companyId)); } if (assignedTo) { conditions.push(eq(todos.assignedTo, assignedTo)); } if (status) { conditions.push(eq(todos.status, status)); } if (conditions.length > 0) { query = query.where(and(...conditions)); } const result = await query.orderBy(desc(todos.createdAt)); return result; }; /** * Get todo by ID */ export const getTodoById = async (todoId) => { const [todo] = await db .select() .from(todos) .where(eq(todos.id, todoId)) .limit(1); if (!todo) { throw new NotFoundError('Todo nenájdené'); } return todo; }; /** * Create new todo */ export const createTodo = async (userId, data) => { const { title, description, projectId, companyId, assignedTo, status, priority, dueDate } = data; // Verify project exists if provided if (projectId) { const [project] = await db .select() .from(projects) .where(eq(projects.id, projectId)) .limit(1); if (!project) { throw new NotFoundError('Projekt nenájdený'); } } // Verify company exists if provided if (companyId) { const [company] = await db .select() .from(companies) .where(eq(companies.id, companyId)) .limit(1); if (!company) { throw new NotFoundError('Firma nenájdená'); } } // Verify assigned user exists if provided if (assignedTo) { const [user] = await db .select() .from(users) .where(eq(users.id, assignedTo)) .limit(1); if (!user) { throw new NotFoundError('Používateľ nenájdený'); } } const [newTodo] = await db .insert(todos) .values({ title, description: description || null, projectId: projectId || null, companyId: companyId || null, assignedTo: assignedTo || null, status: status || 'pending', priority: priority || 'medium', dueDate: dueDate ? new Date(dueDate) : null, createdBy: userId, }) .returning(); return newTodo; }; /** * Update todo */ export const updateTodo = async (todoId, data) => { const todo = await getTodoById(todoId); const { title, description, projectId, companyId, assignedTo, status, priority, dueDate } = data; // Verify project exists if being changed if (projectId !== undefined && projectId !== null && projectId !== todo.projectId) { const [project] = await db .select() .from(projects) .where(eq(projects.id, projectId)) .limit(1); if (!project) { throw new NotFoundError('Projekt nenájdený'); } } // Verify company exists if being changed if (companyId !== undefined && companyId !== null && companyId !== todo.companyId) { const [company] = await db .select() .from(companies) .where(eq(companies.id, companyId)) .limit(1); if (!company) { throw new NotFoundError('Firma nenájdená'); } } // Verify assigned user exists if being changed if (assignedTo !== undefined && assignedTo !== null && assignedTo !== todo.assignedTo) { const [user] = await db .select() .from(users) .where(eq(users.id, assignedTo)) .limit(1); if (!user) { throw new NotFoundError('Používateľ nenájdený'); } } // Set completedAt when status is changed to 'completed' let completedAt = todo.completedAt; if (status === 'completed' && todo.status !== 'completed') { completedAt = new Date(); } else if (status && status !== 'completed') { completedAt = null; } const [updated] = await db .update(todos) .set({ title: title !== undefined ? title : todo.title, description: description !== undefined ? description : todo.description, projectId: projectId !== undefined ? projectId : todo.projectId, companyId: companyId !== undefined ? companyId : todo.companyId, assignedTo: assignedTo !== undefined ? assignedTo : todo.assignedTo, status: status !== undefined ? status : todo.status, priority: priority !== undefined ? priority : todo.priority, dueDate: dueDate !== undefined ? (dueDate ? new Date(dueDate) : null) : todo.dueDate, completedAt, updatedAt: new Date(), }) .where(eq(todos.id, todoId)) .returning(); return updated; }; /** * Delete todo */ export const deleteTodo = async (todoId) => { await getTodoById(todoId); // Check if exists await db.delete(todos).where(eq(todos.id, todoId)); return { success: true, message: 'Todo bolo odstránené' }; }; /** * Get todo with related data (notes, project, company, assigned user) */ export const getTodoWithRelations = async (todoId) => { const todo = await getTodoById(todoId); // Get project if exists let project = null; if (todo.projectId) { [project] = await db .select() .from(projects) .where(eq(projects.id, todo.projectId)) .limit(1); } // Get company if exists let company = null; if (todo.companyId) { [company] = await db .select() .from(companies) .where(eq(companies.id, todo.companyId)) .limit(1); } // Get assigned user if exists let assignedUser = null; if (todo.assignedTo) { [assignedUser] = await db .select({ id: users.id, username: users.username, firstName: users.firstName, lastName: users.lastName, }) .from(users) .where(eq(users.id, todo.assignedTo)) .limit(1); } // Get related notes const todoNotes = await db .select() .from(notes) .where(eq(notes.todoId, todoId)) .orderBy(desc(notes.createdAt)); return { ...todo, project, company, assignedUser, notes: todoNotes, }; }; /** * Get todos by project ID */ export const getTodosByProjectId = async (projectId) => { return await db .select() .from(todos) .where(eq(todos.projectId, projectId)) .orderBy(desc(todos.createdAt)); }; /** * Get todos by company ID */ export const getTodosByCompanyId = async (companyId) => { return await db .select() .from(todos) .where(eq(todos.companyId, companyId)) .orderBy(desc(todos.createdAt)); }; /** * Get todos assigned to a user */ export const getTodosByUserId = async (userId) => { return await db .select() .from(todos) .where(eq(todos.assignedTo, userId)) .orderBy(desc(todos.createdAt)); };