305 lines
7.1 KiB
JavaScript
305 lines
7.1 KiB
JavaScript
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));
|
|
};
|