diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0834567 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,21 @@ +{ + "name": "EMS", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "bcryptjs": "^3.0.3" + } + }, + "node_modules/bcryptjs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", + "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==", + "license": "BSD-3-Clause", + "bin": { + "bcrypt": "bin/bcrypt" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1432103 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "bcryptjs": "^3.0.3" + } +} diff --git a/server/controllers/attendanceController.js b/server/controllers/attendanceController.js index 51a0f5b..20c0911 100644 --- a/server/controllers/attendanceController.js +++ b/server/controllers/attendanceController.js @@ -1,5 +1,5 @@ import Attendance from "../models/Attendance.js"; -import { Employee } from "../models/Employee.js" +import Employee from "../models/Employee.js" //clock in/out for employee @@ -24,7 +24,7 @@ export const clockInOut = async (req, res) => { const today = new Date(); today.setHours(0, 0, 0, 0); - const existing = await getAttendance.findOne({ + const existing = await Attendance.findOne({ employeeId: employee._id, date: today }) diff --git a/server/controllers/authController.js b/server/controllers/authController.js index e48d733..c359852 100644 --- a/server/controllers/authController.js +++ b/server/controllers/authController.js @@ -1,4 +1,4 @@ -import User from "../models/User"; +import User from "../models/User.js"; import bcrypt from "bcryptjs"; import jwt from "jsonwebtoken"; diff --git a/server/controllers/employeeController.js b/server/controllers/employeeController.js index 74c0163..2054900 100644 --- a/server/controllers/employeeController.js +++ b/server/controllers/employeeController.js @@ -39,7 +39,7 @@ export const getEmployee = async (req, res) => { export const createEmployee = async (req, res) => { try { - const { firstName, lastName, email, phone, position, department, basicSalary, allowances, deductions, joinDate, password, role, bio } = req.bod; + const { firstName, lastName, email, phone, position, department, basicSalary, allowances, deductions, joinDate, password, role, bio } = req.body; if (!email || !password || !firstName || !lastName) @@ -88,7 +88,7 @@ export const createEmployee = async (req, res) => { export const updateEmployee = async (req, res) => { try { const { id } = req.params; - const { firstName, lastName, email, phone, position, department, basicSalary, allowances, deductions, password, role, bio, employmentStatus } = req.bod; + const { firstName, lastName, email, phone, position, department, basicSalary, allowances, deductions, password, role, bio, employmentStatus } = req.body; const employee = await Employee.findById(id); diff --git a/server/controllers/leaveController.js b/server/controllers/leaveController.js new file mode 100644 index 0000000..97684e1 --- /dev/null +++ b/server/controllers/leaveController.js @@ -0,0 +1,128 @@ +import Employee from "../models/Employee.js"; +import LeaveApplication from "../models/LeaveApplication.js"; + +//Create leave +//POST /api/leave + +export const createLeave = async (req, res) => { + try { + const session = req.session; + const employee = await Employee.findOne({ userId: session.userId }); + + if (!employee) + return res.status(404).json({ message: "Employee not found" }); + + if (employee.isDeleted) + return res.status(403).json({ message: "Your account id deactivated.You cannot create leave" }); + + const { type, startDate, endDate, reason } = req.body; + + if (!type || !startDate || !endDate || !reason) + return res.status(400).json({ message: "Please provide all the required fields" }); + + const today = new Date(); + today.setHours(0, 0, 0, 0); + + if (new Date(startDate) < today || new Date(endDate) < today) + return res.status(400).json({ message: "Please provide valid dates" }); + + if (new Date(endDate) < today || new Date(startDate) < today) + return res.status(400).json({ message: "end date must be greater than start date" }); + + const leave = await LeaveApplication.create({ + employeeId: employee._id, + type, + startDate: new Date(startDate), + endDate: new Date(endDate), + reason, + status: "PENDING" + }); + + return res.json({ + success: true, + data: leave + }) + + } catch (error) { + console.log(error); + return res.status(500).json({ error: "Failed to create leave" }); + } +} + +//Get leave +//GET /api/leaves +export const getLeaves = async (req, res) => { + try { + const session = req.session; + + + const isAdmin = session.role === "ADMIN"; + + + if (isAdmin) { + const status = req.query.status; + const where = status ? { status } : {} + + const leaves = await LeaveApplication.find(where). + populate("employeeId").sort({ createdAt: -1 }); + + + const data = leaves.map((l) => { + const obj = l.toObject(); + + return { + ...obj, + id: obj._id.toString(), + employee: obj.employeeId, + employeeId: obj.employeeId?._id?.toString() + } + }) + + return res.json({ + data + }) + } else { + const employee = await Employee.findOne({ userId: session.userId }).lean(); + + if (!employee) + return res.status(404).json({ error: "Not Found" }); + + const leaves = await LeaveApplication.find({ + employeeId: employee._id + }).sort({ createdAt: -1 }); + + return res.json({ + data: leaves, + employee: { ...employee, id: employee._id.toString() } + }) + } + + } catch (error) { + console.log(error); + return res.status(500).json({ error: "Failed to fetch leaves" }); + } +} + + +//Update leave status +//PATCH /api/leaves/:id +export const updateLeaveStatus = async (req, res) => { + try { + const { status } = req.body; + + if (!["AP[ROVED", "REJECTED", "PENDING"].includes(status)) + return res.status(400).json({ error: "invalid status" }); + + + const leave = await LeaveApplication.findByIdAndUpdate(req.params.id, { status }, { returnDocument: 'after' }); + + return res.json({ + success: true, + data: leave + }) + + + } catch (error) { + return res.status(500).json({ error: "Failed" }); + } +} \ No newline at end of file diff --git a/server/middleware/auth.js b/server/middleware/auth.js index 80a1812..144f6d1 100644 --- a/server/middleware/auth.js +++ b/server/middleware/auth.js @@ -1,4 +1,4 @@ -import { jwt } from "jsonwebtoken"; +import jwt from "jsonwebtoken"; export const protect = (req, res, next) => { try { @@ -27,7 +27,7 @@ export const protect = (req, res, next) => { export const adminProtect = (req, res, next) => { - if (!req?.session?.role !== "ADMIN") { + if (req?.session?.role !== "ADMIN") { return res.status(401).json({ error: "Admin access required" }) } diff --git a/server/models/Employee.js b/server/models/Employee.js index 4c6ef94..8faae40 100644 --- a/server/models/Employee.js +++ b/server/models/Employee.js @@ -4,7 +4,7 @@ import { DEPARTMENTS } from "../constants/departments.js"; const EmployeeSchema = new mongoose.Schema({ userId: { - type: mongoose.Schema.types.ObjectId, + type: mongoose.Schema.Types.ObjectId, ref: "User", required: true, unique: true diff --git a/server/models/LeaveApplication.js b/server/models/LeaveApplication.js new file mode 100644 index 0000000..cccaf6b --- /dev/null +++ b/server/models/LeaveApplication.js @@ -0,0 +1,37 @@ +import mongoose from "mongoose"; + + + +const leaveApplicationSchema = new mongoose.Schema({ + employeeId: { + type: mongoose.Schhema.Types.ObjectId, + ref: "Employee", + required: true, + }, + type: { + type: String, + enum: ["SICK", "CASUAL", "ANNUAL"], + required: true + }, + startDate: { + type: Date, + required: true + }, + endDate: { + type: Date, + required: true + }, + reason: { + type: String, + required: true + }, + status: { + type: String, + enum: ["PENDING", "APPROVED", "REJECTED"], + default: "PENDING" + } +}); + + +const LeaveApplication = mongoose.model("LeaveApplication", leaveApplicationSchema); +export default LeaveApplication; \ No newline at end of file diff --git a/server/models/User.js b/server/models/User.js index 039cc6c..c8c6640 100644 --- a/server/models/User.js +++ b/server/models/User.js @@ -14,7 +14,7 @@ const UserSchema = new mongoose.Schema({ role: { type: String, enum: ["ADMIN", "EMPLOYEE"], - dafault: "EMPLOYEE" + default: "EMPLOYEE" } }, { timestamps: true }); diff --git a/server/routes/AttendanceRoutes.js b/server/routes/AttendanceRoutes.js index dbd75ff..60ff1ce 100644 --- a/server/routes/AttendanceRoutes.js +++ b/server/routes/AttendanceRoutes.js @@ -1,6 +1,6 @@ import { Router } from "express"; import { clockInOut, getAttendance } from "../controllers/attendanceController.js"; -import { protect } from "../middlewares/auth.js"; +import { protect } from "../middleware/auth.js"; const attendanceRouter = Router();