Files
zerp/backend/src/modules/hr/hr.routes.ts
2026-05-03 10:30:03 +03:00

206 lines
8.3 KiB
TypeScript

import { Router } from 'express';
import { hrController } from './hr.controller';
import { portalController } from './portal.controller';
import { authenticate, authorize } from '../../shared/middleware/auth';
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import crypto from 'crypto';
import { config } from '../../config';
const router = Router();
const expenseClaimsUploadDir = path.join(config.upload.path, 'expense-claims');
if (!fs.existsSync(expenseClaimsUploadDir)) {
fs.mkdirSync(expenseClaimsUploadDir, { recursive: true });
}
const expenseClaimStorage = multer.diskStorage({
destination: (_req, _file, cb) => cb(null, expenseClaimsUploadDir),
filename: (_req, file, cb) => {
const safeName = (file.originalname || 'file').replace(/[^a-zA-Z0-9.-]/g, '_');
cb(null, `${crypto.randomUUID()}-${safeName}`);
},
});
const expenseClaimUpload = multer({
storage: expenseClaimStorage,
limits: { fileSize: config.upload.maxFileSize },
fileFilter: (_req, file, cb) => {
const allowedTypes = [
'image/jpeg',
'image/png',
'image/webp',
'image/gif',
'application/pdf',
];
if (!allowedTypes.includes(file.mimetype)) {
return cb(
new Error('نوع الملف غير مدعوم. يرجى رفع صورة أو ملف PDF.')
);
}
cb(null, true);
},
});
router.use(authenticate);
// ========== EMPLOYEE PORTAL (authenticate only, scoped by employeeId) ==========
router.get('/portal/me', portalController.getMe);
router.get('/portal/loans', portalController.getMyLoans);
router.post('/portal/loans', portalController.submitLoanRequest);
router.get('/portal/leave-balance', portalController.getMyLeaveBalance);
router.get('/portal/leaves', portalController.getMyLeaves);
router.post('/portal/leaves', portalController.submitLeaveRequest);
router.get(
'/portal/managed-leaves',
authorize('department_leave_requests', '*', 'read'),
portalController.getManagedLeaves
);
router.post(
'/portal/managed-leaves/:id/approve',
authorize('department_leave_requests', '*', 'approve'),
portalController.approveManagedLeave
);
router.post(
'/portal/managed-leaves/:id/reject',
authorize('department_leave_requests', '*', 'approve'),
portalController.rejectManagedLeave
);
router.get('/portal/overtime-requests', portalController.getMyOvertimeRequests);
router.post('/portal/overtime-requests', portalController.submitOvertimeRequest);
router.get(
'/portal/managed-overtime-requests',
authorize('department_overtime_requests', '*', 'view'),
portalController.getManagedOvertimeRequests
);
router.post(
'/portal/managed-overtime-requests/:attendanceId/approve',
authorize('department_overtime_requests', '*', 'approve'),
portalController.approveManagedOvertimeRequest
);
router.post(
'/portal/managed-overtime-requests/:attendanceId/reject',
authorize('department_overtime_requests', '*', 'approve'),
portalController.rejectManagedOvertimeRequest
);
router.get('/portal/purchase-requests', portalController.getMyPurchaseRequests);
router.post('/portal/purchase-requests', portalController.submitPurchaseRequest);
router.get('/portal/attendance', portalController.getMyAttendance);
router.get('/portal/salaries', portalController.getMySalaries);
router.get('/portal/expense-claims', portalController.getMyExpenseClaims);
router.post(
'/portal/expense-claims',
(req, res, next) => {
expenseClaimUpload.single('attachment')(req, res, (error: any) => {
if (error) {
return res.status(400).json({
success: false,
message: error.message || 'تعذر رفع المرفق',
});
}
next();
});
},
portalController.submitExpenseClaim
);
router.get(
'/portal/expense-claims/attachments/:attachmentId/view',
portalController.viewExpenseClaimAttachment
);
router.get('/portal/managed-expense-claims', authorize('department_expense_claims', '*', 'read'), portalController.getManagedExpenseClaims);
router.post(
'/portal/managed-expense-claims/:id/approve',
authorize('department_expense_claims', '*', 'approve'),
portalController.approveManagedExpenseClaim
);
router.post(
'/portal/managed-expense-claims/:id/reject',
authorize('department_expense_claims', '*', 'approve'),
portalController.rejectManagedExpenseClaim
);
// ========== EMPLOYEES ==========
router.get('/employees', authorize('hr', 'employees', 'read'), hrController.findAllEmployees);
router.get('/employees/:id', authorize('hr', 'employees', 'read'), hrController.findEmployeeById);
router.post('/employees', authorize('hr', 'employees', 'create'), hrController.createEmployee);
router.put('/employees/:id', authorize('hr', 'employees', 'update'), hrController.updateEmployee);
router.post('/employees/:id/terminate', authorize('hr', 'employees', 'terminate'), hrController.terminateEmployee);
// ========== ATTENDANCE ==========
router.post('/attendance', authorize('hr', 'attendance', 'create'), hrController.recordAttendance);
router.get('/attendance/:employeeId', authorize('hr', 'attendance', 'read'), hrController.getAttendance);
router.post('/attendance/sync', authorize('hr', 'attendance', 'create'), hrController.bulkSyncAttendance);
// ========== LEAVES ==========
router.get('/leaves', authorize('hr', 'leaves', 'read'), hrController.findAllLeaves);
router.post('/leaves', authorize('hr', 'leaves', 'create'), hrController.createLeaveRequest);
router.post('/leaves/:id/approve', authorize('hr', 'leaves', 'approve'), hrController.approveLeave);
router.post('/leaves/:id/reject', authorize('hr', 'leaves', 'approve'), hrController.rejectLeave);
// ========== SALARIES ==========
router.post('/salaries/process', authorize('hr', 'salaries', 'process'), hrController.processSalary);
// ========== DEPARTMENTS ==========
router.get('/departments', authorize('hr', 'all', 'read'), hrController.findAllDepartments);
router.get('/departments/hierarchy', authorize('hr', 'all', 'read'), hrController.getDepartmentsHierarchy);
router.post('/departments', authorize('hr', 'all', 'create'), hrController.createDepartment);
router.put('/departments/:id', authorize('hr', 'all', 'update'), hrController.updateDepartment);
router.delete('/departments/:id', authorize('hr', 'all', 'delete'), hrController.deleteDepartment);
// ========== POSITIONS ==========
router.get('/positions', authorize('hr', 'all', 'read'), hrController.findAllPositions);
// ========== LOANS ==========
router.get('/loans', authorize('hr', 'all', 'read'), hrController.findAllLoans);
router.get('/loans/:id', authorize('hr', 'all', 'read'), hrController.findLoanById);
router.post('/loans', authorize('hr', 'all', 'create'), hrController.createLoan);
router.post('/loans/:id/approve', authorize('hr', 'all', 'approve'), hrController.approveLoan);
router.post('/loans/:id/reject', authorize('hr', 'all', 'approve'), hrController.rejectLoan);
router.post('/loans/:id/pay-installment', authorize('hr', 'all', 'update'), hrController.recordLoanInstallmentPayment);
// ========== PURCHASE REQUESTS ==========
router.get('/purchase-requests', authorize('hr', 'all', 'read'), hrController.findAllPurchaseRequests);
router.get('/purchase-requests/:id', authorize('hr', 'all', 'read'), hrController.findPurchaseRequestById);
router.post('/purchase-requests', authorize('hr', 'all', 'create'), hrController.createPurchaseRequest);
router.post('/purchase-requests/:id/approve', authorize('hr', 'all', 'approve'), hrController.approvePurchaseRequest);
router.post('/purchase-requests/:id/reject', authorize('hr', 'all', 'approve'), hrController.rejectPurchaseRequest);
// ========== LEAVE ENTITLEMENTS ==========
router.get('/leave-balance/:employeeId', authorize('hr', 'all', 'read'), hrController.getLeaveBalance);
router.get('/leave-entitlements', authorize('hr', 'all', 'read'), hrController.findAllLeaveEntitlements);
router.post('/leave-entitlements', authorize('hr', 'all', 'create'), hrController.upsertLeaveEntitlement);
// ========== EMPLOYEE CONTRACTS ==========
router.get('/contracts', authorize('hr', 'all', 'read'), hrController.findAllEmployeeContracts);
router.get('/contracts/:id', authorize('hr', 'all', 'read'), hrController.findEmployeeContractById);
router.post('/contracts', authorize('hr', 'all', 'create'), hrController.createEmployeeContract);
router.put('/contracts/:id', authorize('hr', 'all', 'update'), hrController.updateEmployeeContract);
export default router;