feat: Add services, company documents, company timesheet export
- Add services table and CRUD endpoints (/api/services) - Add company documents upload/download functionality - Add company timesheet XLSX export endpoint - Remove admin requirement from event routes (all authenticated users can manage events) - Add service validators Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import express from 'express';
|
||||
import multer from 'multer';
|
||||
import * as companyController from '../controllers/company.controller.js';
|
||||
import * as personalContactController from '../controllers/personal-contact.controller.js';
|
||||
import * as companyDocumentController from '../controllers/company-document.controller.js';
|
||||
import { authenticate } from '../middlewares/auth/authMiddleware.js';
|
||||
import { requireAdmin } from '../middlewares/auth/roleMiddleware.js';
|
||||
import { checkCompanyAccess } from '../middlewares/auth/resourceAccessMiddleware.js';
|
||||
@@ -8,6 +10,14 @@ import { validateBody, validateParams } from '../middlewares/security/validateIn
|
||||
import { createCompanySchema, updateCompanySchema, createCompanyReminderSchema, updateCompanyReminderSchema } from '../validators/crm.validators.js';
|
||||
import { z } from 'zod';
|
||||
|
||||
// Configure multer for file uploads (memory storage)
|
||||
const upload = multer({
|
||||
storage: multer.memoryStorage(),
|
||||
limits: {
|
||||
fileSize: 50 * 1024 * 1024, // 50MB max
|
||||
},
|
||||
});
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// All company routes require authentication
|
||||
@@ -198,4 +208,40 @@ router.get(
|
||||
personalContactController.getContactsByCompany
|
||||
);
|
||||
|
||||
// Company Documents
|
||||
router.get(
|
||||
'/:companyId/documents',
|
||||
validateParams(z.object({ companyId: z.string().uuid() })),
|
||||
checkCompanyAccess,
|
||||
companyDocumentController.getDocuments
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/:companyId/documents',
|
||||
validateParams(z.object({ companyId: z.string().uuid() })),
|
||||
checkCompanyAccess,
|
||||
upload.single('file'),
|
||||
companyDocumentController.uploadDocument
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/:companyId/documents/:docId/download',
|
||||
validateParams(z.object({
|
||||
companyId: z.string().uuid(),
|
||||
docId: z.string().uuid()
|
||||
})),
|
||||
checkCompanyAccess,
|
||||
companyDocumentController.downloadDocument
|
||||
);
|
||||
|
||||
router.delete(
|
||||
'/:companyId/documents/:docId',
|
||||
requireAdmin,
|
||||
validateParams(z.object({
|
||||
companyId: z.string().uuid(),
|
||||
docId: z.string().uuid()
|
||||
})),
|
||||
companyDocumentController.deleteDocument
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import express from 'express';
|
||||
import * as eventController from '../controllers/event.controller.js';
|
||||
import { authenticate } from '../middlewares/auth/authMiddleware.js';
|
||||
import { requireAdmin } from '../middlewares/auth/roleMiddleware.js';
|
||||
import { validateBody, validateParams, validateQuery } from '../middlewares/security/validateInput.js';
|
||||
import { createEventSchema, updateEventSchema } from '../validators/crm.validators.js';
|
||||
import { z } from 'zod';
|
||||
@@ -39,42 +38,38 @@ router.get(
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /api/events - Vytvoriť event (iba admin)
|
||||
* POST /api/events - Vytvoriť event (všetci autentifikovaní používatelia)
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
requireAdmin,
|
||||
validateBody(createEventSchema),
|
||||
eventController.createEvent
|
||||
);
|
||||
|
||||
/**
|
||||
* PUT /api/events/:eventId - Upraviť event (iba admin)
|
||||
* PUT /api/events/:eventId - Upraviť event (všetci autentifikovaní používatelia)
|
||||
*/
|
||||
router.put(
|
||||
'/:eventId',
|
||||
requireAdmin,
|
||||
validateParams(eventIdSchema),
|
||||
validateBody(updateEventSchema),
|
||||
eventController.updateEvent
|
||||
);
|
||||
|
||||
/**
|
||||
* DELETE /api/events/:eventId - Zmazať event (iba admin)
|
||||
* DELETE /api/events/:eventId - Zmazať event (všetci autentifikovaní používatelia)
|
||||
*/
|
||||
router.delete(
|
||||
'/:eventId',
|
||||
requireAdmin,
|
||||
validateParams(eventIdSchema),
|
||||
eventController.deleteEvent
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /api/events/:eventId/notify - Odoslať notifikácie priradeným používateľom (iba admin)
|
||||
* POST /api/events/:eventId/notify - Odoslať notifikácie priradeným používateľom (všetci autentifikovaní používatelia)
|
||||
*/
|
||||
router.post(
|
||||
'/:eventId/notify',
|
||||
requireAdmin,
|
||||
validateParams(eventIdSchema),
|
||||
eventController.sendEventNotification
|
||||
);
|
||||
|
||||
63
src/routes/service.routes.js
Normal file
63
src/routes/service.routes.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import express from 'express';
|
||||
import * as serviceController from '../controllers/service.controller.js';
|
||||
import { authenticate } from '../middlewares/auth/authMiddleware.js';
|
||||
import { requireAdmin } from '../middlewares/auth/roleMiddleware.js';
|
||||
import { validateBody, validateParams } from '../middlewares/security/validateInput.js';
|
||||
import { createServiceSchema, updateServiceSchema } from '../validators/crm.validators.js';
|
||||
import { z } from 'zod';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const serviceIdSchema = z.object({
|
||||
serviceId: z.string().uuid(),
|
||||
});
|
||||
|
||||
// All service routes require authentication
|
||||
router.use(authenticate);
|
||||
|
||||
/**
|
||||
* GET /api/services - Get all services (all authenticated users)
|
||||
*/
|
||||
router.get('/', serviceController.getAllServices);
|
||||
|
||||
/**
|
||||
* GET /api/services/:serviceId - Get service by ID (all authenticated users)
|
||||
*/
|
||||
router.get(
|
||||
'/:serviceId',
|
||||
validateParams(serviceIdSchema),
|
||||
serviceController.getServiceById
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /api/services - Create new service (admin only)
|
||||
*/
|
||||
router.post(
|
||||
'/',
|
||||
requireAdmin,
|
||||
validateBody(createServiceSchema),
|
||||
serviceController.createService
|
||||
);
|
||||
|
||||
/**
|
||||
* PUT /api/services/:serviceId - Update service (admin only)
|
||||
*/
|
||||
router.put(
|
||||
'/:serviceId',
|
||||
requireAdmin,
|
||||
validateParams(serviceIdSchema),
|
||||
validateBody(updateServiceSchema),
|
||||
serviceController.updateService
|
||||
);
|
||||
|
||||
/**
|
||||
* DELETE /api/services/:serviceId - Delete service (admin only)
|
||||
*/
|
||||
router.delete(
|
||||
'/:serviceId',
|
||||
requireAdmin,
|
||||
validateParams(serviceIdSchema),
|
||||
serviceController.deleteService
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -63,6 +63,19 @@ router.post(
|
||||
timeTrackingController.generateMonthlyTimesheet
|
||||
);
|
||||
|
||||
// Generate company timesheet (XLSX)
|
||||
router.post(
|
||||
'/generate-company-timesheet',
|
||||
validateBody(
|
||||
z.object({
|
||||
year: z.number().int().min(2000).max(2100),
|
||||
month: z.number().int().min(1).max(12),
|
||||
companyId: z.string().uuid('Neplatný formát company ID'),
|
||||
})
|
||||
),
|
||||
timeTrackingController.generateCompanyTimesheet
|
||||
);
|
||||
|
||||
// Get monthly statistics
|
||||
router.get(
|
||||
'/stats/monthly/:year/:month',
|
||||
|
||||
Reference in New Issue
Block a user