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:
richardtekula
2026-01-17 18:45:01 +01:00
parent b542d1d635
commit 514b6c8a92
13 changed files with 866 additions and 11 deletions

View File

@@ -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;