fix email issues, add company,project,todos

This commit is contained in:
richardtekula
2025-11-21 13:56:02 +01:00
parent bb851639b8
commit ca93b6f2d2
30 changed files with 4860 additions and 1066 deletions

View File

@@ -0,0 +1,95 @@
import express from 'express';
import * as companyController from '../controllers/company.controller.js';
import { authenticate } from '../middlewares/auth/authMiddleware.js';
import { validateBody, validateParams } from '../middlewares/security/validateInput.js';
import { createCompanySchema, updateCompanySchema } from '../validators/crm.validators.js';
import { z } from 'zod';
const router = express.Router();
// All company routes require authentication
router.use(authenticate);
/**
* Company management
*/
// Get all companies
router.get('/', companyController.getAllCompanies);
// Get company by ID
router.get(
'/:companyId',
validateParams(z.object({ companyId: z.string().uuid() })),
companyController.getCompanyById
);
// Get company with relations (projects, todos, notes)
router.get(
'/:companyId/details',
validateParams(z.object({ companyId: z.string().uuid() })),
companyController.getCompanyWithRelations
);
// Create new company
router.post(
'/',
validateBody(createCompanySchema),
companyController.createCompany
);
// Update company
router.patch(
'/:companyId',
validateParams(z.object({ companyId: z.string().uuid() })),
validateBody(updateCompanySchema),
companyController.updateCompany
);
// Delete company
router.delete(
'/:companyId',
validateParams(z.object({ companyId: z.string().uuid() })),
companyController.deleteCompany
);
// Company Notes (nested resources)
router.get(
'/:companyId/notes',
validateParams(z.object({ companyId: z.string().uuid() })),
companyController.getCompanyNotes
);
router.post(
'/:companyId/notes',
validateParams(z.object({ companyId: z.string().uuid() })),
validateBody(z.object({
content: z.string().min(1),
reminderAt: z.string().optional().or(z.literal('')),
})),
companyController.addCompanyNote
);
router.patch(
'/:companyId/notes/:noteId',
validateParams(z.object({
companyId: z.string().uuid(),
noteId: z.string().uuid()
})),
validateBody(z.object({
content: z.string().min(1).optional(),
reminderAt: z.string().optional().or(z.literal('').or(z.null())),
})),
companyController.updateCompanyNote
);
router.delete(
'/:companyId/notes/:noteId',
validateParams(z.object({
companyId: z.string().uuid(),
noteId: z.string().uuid()
})),
companyController.deleteCompanyNote
);
export default router;

View File

@@ -53,4 +53,38 @@ router.delete(
contactController.removeContact
);
// Link company to contact
router.post(
'/:contactId/link-company',
validateParams(z.object({ contactId: z.string().uuid() })),
validateBody(z.object({ companyId: z.string().uuid() })),
contactController.linkCompanyToContact
);
// Unlink company from contact
router.post(
'/:contactId/unlink-company',
validateParams(z.object({ contactId: z.string().uuid() })),
contactController.unlinkCompanyFromContact
);
// Create company from contact
router.post(
'/:contactId/create-company',
validateParams(z.object({ contactId: z.string().uuid() })),
validateBody(
z.object({
name: z.string().optional(),
email: z.string().email().optional(),
phone: z.string().optional(),
address: z.string().optional(),
city: z.string().optional(),
country: z.string().optional(),
website: z.string().url().optional(),
description: z.string().optional(),
})
),
contactController.createCompanyFromContact
);
export default router;

59
src/routes/note.routes.js Normal file
View File

@@ -0,0 +1,59 @@
import express from 'express';
import * as noteController from '../controllers/note.controller.js';
import { authenticate } from '../middlewares/auth/authMiddleware.js';
import { validateBody, validateParams } from '../middlewares/security/validateInput.js';
import { createNoteSchema, updateNoteSchema } from '../validators/crm.validators.js';
import { z } from 'zod';
const router = express.Router();
// All note routes require authentication
router.use(authenticate);
/**
* Note management
*/
// Get all notes
router.get('/', noteController.getAllNotes);
// Get my reminders (must be before /:noteId to avoid route conflict)
router.get('/my-reminders', noteController.getMyReminders);
// Get note by ID
router.get(
'/:noteId',
validateParams(z.object({ noteId: z.string().uuid() })),
noteController.getNoteById
);
// Create new note
router.post(
'/',
validateBody(createNoteSchema),
noteController.createNote
);
// Update note
router.patch(
'/:noteId',
validateParams(z.object({ noteId: z.string().uuid() })),
validateBody(updateNoteSchema),
noteController.updateNote
);
// Delete note
router.delete(
'/:noteId',
validateParams(z.object({ noteId: z.string().uuid() })),
noteController.deleteNote
);
// Mark reminder as sent
router.post(
'/:noteId/mark-reminder-sent',
validateParams(z.object({ noteId: z.string().uuid() })),
noteController.markReminderSent
);
export default router;

View File

@@ -0,0 +1,133 @@
import express from 'express';
import * as projectController from '../controllers/project.controller.js';
import { authenticate } from '../middlewares/auth/authMiddleware.js';
import { validateBody, validateParams } from '../middlewares/security/validateInput.js';
import { createProjectSchema, updateProjectSchema } from '../validators/crm.validators.js';
import { z } from 'zod';
const router = express.Router();
// All project routes require authentication
router.use(authenticate);
/**
* Project management
*/
// Get all projects
router.get('/', projectController.getAllProjects);
// Get project by ID
router.get(
'/:projectId',
validateParams(z.object({ projectId: z.string().uuid() })),
projectController.getProjectById
);
// Get project with relations (company, todos, notes, timesheets)
router.get(
'/:projectId/details',
validateParams(z.object({ projectId: z.string().uuid() })),
projectController.getProjectWithRelations
);
// Create new project
router.post(
'/',
validateBody(createProjectSchema),
projectController.createProject
);
// Update project
router.patch(
'/:projectId',
validateParams(z.object({ projectId: z.string().uuid() })),
validateBody(updateProjectSchema),
projectController.updateProject
);
// Delete project
router.delete(
'/:projectId',
validateParams(z.object({ projectId: z.string().uuid() })),
projectController.deleteProject
);
// Project Notes (nested resources)
router.get(
'/:projectId/notes',
validateParams(z.object({ projectId: z.string().uuid() })),
projectController.getProjectNotes
);
router.post(
'/:projectId/notes',
validateParams(z.object({ projectId: z.string().uuid() })),
validateBody(z.object({
content: z.string().min(1),
reminderAt: z.string().optional().or(z.literal('')),
})),
projectController.addProjectNote
);
router.patch(
'/:projectId/notes/:noteId',
validateParams(z.object({
projectId: z.string().uuid(),
noteId: z.string().uuid()
})),
validateBody(z.object({
content: z.string().min(1).optional(),
reminderAt: z.string().optional().or(z.literal('').or(z.null())),
})),
projectController.updateProjectNote
);
router.delete(
'/:projectId/notes/:noteId',
validateParams(z.object({
projectId: z.string().uuid(),
noteId: z.string().uuid()
})),
projectController.deleteProjectNote
);
// Project Users (team members)
router.get(
'/:projectId/users',
validateParams(z.object({ projectId: z.string().uuid() })),
projectController.getProjectUsers
);
router.post(
'/:projectId/users',
validateParams(z.object({ projectId: z.string().uuid() })),
validateBody(z.object({
userId: z.string().uuid('Neplatný formát user ID'),
role: z.string().max(50).optional().or(z.literal('')),
})),
projectController.assignUserToProject
);
router.patch(
'/:projectId/users/:userId',
validateParams(z.object({
projectId: z.string().uuid(),
userId: z.string().uuid()
})),
validateBody(z.object({
role: z.string().max(50).optional().or(z.literal('').or(z.null())),
})),
projectController.updateUserRoleOnProject
);
router.delete(
'/:projectId/users/:userId',
validateParams(z.object({
projectId: z.string().uuid(),
userId: z.string().uuid()
})),
projectController.removeUserFromProject
);
export default router;

66
src/routes/todo.routes.js Normal file
View File

@@ -0,0 +1,66 @@
import express from 'express';
import * as todoController from '../controllers/todo.controller.js';
import { authenticate } from '../middlewares/auth/authMiddleware.js';
import { validateBody, validateParams } from '../middlewares/security/validateInput.js';
import { createTodoSchema, updateTodoSchema } from '../validators/crm.validators.js';
import { z } from 'zod';
const router = express.Router();
// All todo routes require authentication
router.use(authenticate);
/**
* Todo management
*/
// Get all todos
router.get('/', todoController.getAllTodos);
// Get my todos (assigned to current user)
router.get('/my', todoController.getMyTodos);
// Get todo by ID
router.get(
'/:todoId',
validateParams(z.object({ todoId: z.string().uuid() })),
todoController.getTodoById
);
// Get todo with relations (project, company, assigned user, notes)
router.get(
'/:todoId/details',
validateParams(z.object({ todoId: z.string().uuid() })),
todoController.getTodoWithRelations
);
// Create new todo
router.post(
'/',
validateBody(createTodoSchema),
todoController.createTodo
);
// Update todo
router.patch(
'/:todoId',
validateParams(z.object({ todoId: z.string().uuid() })),
validateBody(updateTodoSchema),
todoController.updateTodo
);
// Delete todo
router.delete(
'/:todoId',
validateParams(z.object({ todoId: z.string().uuid() })),
todoController.deleteTodo
);
// Toggle todo completion status
router.patch(
'/:todoId/toggle',
validateParams(z.object({ todoId: z.string().uuid() })),
todoController.toggleTodo
);
export default router;