attendance and leave api created successfully

This commit is contained in:
Sibunnayak 2024-07-22 20:20:49 +05:30
parent b4c88496fc
commit 7e169d7973
6 changed files with 495 additions and 256 deletions

4
app.js
View File

@ -171,6 +171,8 @@ import CouponRoute from "./resources/Affiliate&Coupon/Coupon/CouponRoute.js";
//support Ticket //support Ticket
// attandance // attandance
import attendance from "./resources/Attendance/AttandanceRoute.js" import attendance from "./resources/Attendance/AttandanceRoute.js"
//leave
import leave from "./resources/Leaves/LeaveRoute.js";
app.use("/api/v1", user); app.use("/api/v1", user);
//Product //Product
@ -228,6 +230,8 @@ app.use("/api/v1/coupon", CouponRoute);
app.use("/api/v1/blog", BlogRoute); app.use("/api/v1/blog", BlogRoute);
//attendance //attendance
app.use("/api/v1", attendance); app.use("/api/v1", attendance);
//leave
app.use("/api/v1", leave);
//config specialty //config specialty
// app.use("/api/config/specialty", SpecialtiesRouter); // app.use("/api/config/specialty", SpecialtiesRouter);

View File

@ -1,229 +1,113 @@
// import { Attendance } from "./AttandanceModel.js"; import { Attendance } from "./AttendanceModel.js";
// Mark attendance
// export const markAttendance = async (req, res) => { // export const markAttendance = async (req, res) => {
// try { // try {
// const { date, time, location, notes } = req.body; // const { date, time, location, notes } = req.body;
// const salesCoordinatorId = req.user._id; // const userId = req.user._id;
// const userType = req.userType;
// // Get the start and end of the day to check if the attendance is already marked // // Parse the input date
// const startOfDay = new Date(date); // const [year, month, day] = date.split("/");
// startOfDay.setHours(0, 0, 0, 0); // const parsedDate = new Date(Date.UTC(year, month - 1, day));
// const today = new Date();
// const endOfDay = new Date(date); // today.setUTCHours(0, 0, 0, 0);
// endOfDay.setHours(23, 59, 59, 999); // // Check if the date in req.body is not today's date
// if (parsedDate.getTime() !== today.getTime()) {
// // Check if the attendance record exists for today
// const existingAttendance = await AttendanceSalesCoOrdinator.findOne({
// salesCoordinator: salesCoordinatorId,
// "records.date": { $gte: startOfDay, $lte: endOfDay },
// });
// if (existingAttendance) {
// return res.status(400).json({ // return res.status(400).json({
// success: false, // success: false,
// message: "Attendance for today is already marked.", // message: `Leave can only be marked for today's date: ${
// today.toISOString().split("T")[0]
// }`,
// }); // });
// } // }
// // Get the start and end of the day to check if the leave is already marked
// const startOfDay = new Date(parsedDate);
// const endOfDay = new Date(parsedDate);
// endOfDay.setUTCHours(23, 59, 59, 999);
// // Check if attendance record exists for the sales coordinator // // Check if the attendance record exists for today
// let attendance = await AttendanceSalesCoOrdinator.findOne({ // const existingAttendance = await Attendance.findOne({
// salesCoordinator: salesCoordinatorId, // userId,
// userType,
// records: {
// $elemMatch: {
// date: { $gte: startOfDay, $lte: endOfDay },
// },
// },
// }); // });
// if (existingAttendance) {
// return res.status(400).json({
// success: false,
// message: "Attendance for today is already marked.",
// });
// }
// // Check if attendance record exists for the user
// let attendance = await Attendance.findOne({ userId, userType });
// if (!attendance) { // if (!attendance) {
// // Create a new attendance record if it doesn't exist // // Create a new attendance record if it doesn't exist
// attendance = new AttendanceSalesCoOrdinator({ // attendance = new Attendance({
// salesCoordinator: salesCoordinatorId, // userId,
// userType,
// records: [], // records: [],
// }); // });
// } // }
// // Add the new attendance record to the array // // Add the new attendance record to the array
// attendance.records.push({ date, time, location, notes }); // attendance.records.push({ date: startOfDay, time, location, notes });
// await attendance.save(); // await attendance.save();
// res.status(201).json({ // res.status(201).json({
// success: true, // success: true,
// message: "Attendance marked successfully", // message: "Attendance marked successfully",
// record: { date, time, location, notes }, // record: { date: today, time, location, notes },
// }); // });
// } catch (error) { // } catch (error) {
// console.error("Error marking attendance:", error);
// res.status(500).json({ // res.status(500).json({
// success: false, // success: false,
// message: error.message || "Something went wrong", // message: error.message || "Something went wrong",
// }); // });
// } // }
// }; // };
// export const getAttendanceBySalesCoordinator = async (req, res) => {
// try {
// const salesCoordinatorId = req.user._id;
// const attendance = await AttendanceSalesCoOrdinator.findOne({
// salesCoordinator: salesCoordinatorId,
// }).populate("salesCoordinator", "name email");
// if (!attendance) {
// return res.status(404).json({
// success: false,
// message: "No attendance records found for this sales coordinator.",
// });
// }
// res.status(200).json({
// success: true,
// attendance,
// });
// } catch (error) {
// res.status(500).json({
// success: false,
// message: error.message || "Something went wrong",
// });
// }
// };
// // admin
// export const AdmingetAttendanceBySalesCoordinator = async (req, res) => {
// try {
// const { id } = req.params;
// const { page = 1, show = 10 } = req.query;
// const limit = parseInt(show);
// const skip = (page - 1) * limit;
// // Find attendance records for the given sales coordinator
// const attendanceDoc = await AttendanceSalesCoOrdinator.findOne({
// salesCoordinator: id,
// }).populate("salesCoordinator", "name email");
// if (!attendanceDoc) {
// return res.status(404).json({
// success: false,
// message: "No attendance records found for this sales coordinator.",
// });
// }
// // Pagination and slicing records
// const totalData = attendanceDoc.records.length;
// const paginatedRecords = attendanceDoc.records.slice(skip, skip + limit);
// res.status(200).json({
// success: true,
// salesCoordinator: attendanceDoc.salesCoordinator,
// attendance: paginatedRecords,
// total_data: totalData,
// });
// } catch (error) {
// res.status(500).json({
// success: false,
// message: error.message || "Something went wrong",
// });
// }
// };
// export const getTodayAttendance = async (req, res) => {
// try {
// const today = new Date();
// today.setHours(0, 0, 0, 0);
// const startOfDay = new Date(today);
// const endOfDay = new Date(today);
// endOfDay.setHours(23, 59, 59, 999);
// const { page = 1, show = 10 } = req.query;
// const limit = parseInt(show);
// const skip = (page - 1) * limit;
// const attendances = await AttendanceSalesCoOrdinator.aggregate([
// { $unwind: '$records' },
// {
// $match: {
// 'records.date': { $gte: startOfDay, $lte: endOfDay }
// }
// },
// {
// $lookup: {
// from: 'salescoordinators',
// localField: 'salesCoordinator',
// foreignField: '_id',
// as: 'salesCoordinator'
// }
// },
// { $unwind: '$salesCoordinator' },
// {
// $facet: {
// totalData: [{ $count: 'count' }],
// attendance: [
// { $skip: skip },
// { $limit: limit },
// {
// $project: {
// salesCoordinator: {
// id: '$salesCoordinator._id',
// name: '$salesCoordinator.name',
// email: '$salesCoordinator.email'
// },
// date: '$records.date',
// time: '$records.time',
// location: '$records.location',
// note: '$records.notes'
// }
// }
// ]
// }
// }
// ]);
// const totalData = attendances[0].totalData[0] ? attendances[0].totalData[0].count : 0;
// res.status(200).json({
// success: true,
// attendance: attendances[0].attendance,
// total_data: totalData
// });
// } catch (error) {
// res.status(500).json({
// success: false,
// message: error.message || 'Something went wrong'
// });
// }
// };
import { Attendance } from "./AttendanceModel.js";
// Mark attendance
export const markAttendance = async (req, res) => { export const markAttendance = async (req, res) => {
try { try {
const { date, time, location, notes } = req.body; const { date, time, location, notes } = req.body;
const userId = req.user._id; const userId = req.user._id;
const userType = req.userType; const userType = req.userType;
// Get today's date // Parse the input date
const [year, month, day] = date.split("/");
const parsedDate = new Date(Date.UTC(year, month - 1, day));
const today = new Date(); const today = new Date();
today.setHours(0, 0, 0, 0); today.setUTCHours(0, 0, 0, 0);
// Check if the date in req.body is not today's date // Check if the date in req.body is not today's date
if (!isSameDay(new Date(date), today)) { if (parsedDate.getTime() !== today.getTime()) {
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
message: `Attendance can only be marked for today's date: ${today.toLocaleDateString()}`, message: `Attendance can only be marked for today's date: ${
today.toISOString().split("T")[0]
}`,
}); });
} }
// Get the start and end of the day to check if the attendance is already marked // Get the start and end of the day to check if the attendance is already marked
const startOfDay = new Date(date); const startOfDay = new Date(parsedDate);
startOfDay.setHours(0, 0, 0, 0); const endOfDay = new Date(parsedDate);
endOfDay.setUTCHours(23, 59, 59, 999);
const endOfDay = new Date(date);
endOfDay.setHours(23, 59, 59, 999);
// Check if the attendance record exists for today // Check if the attendance record exists for today
const existingAttendance = await Attendance.findOne({ const existingAttendance = await Attendance.findOne({
userId, userId,
userType, userType,
records: { 'records.date': {
$elemMatch: { $gte: startOfDay,
date: { $gte: startOfDay, $lte: endOfDay } $lte: endOfDay,
} },
}
}); });
if (existingAttendance) { if (existingAttendance) {
@ -246,15 +130,16 @@ export const markAttendance = async (req, res) => {
} }
// Add the new attendance record to the array // Add the new attendance record to the array
attendance.records.push({ date, time, location, notes }); attendance.records.push({ date: startOfDay, time, location, notes });
await attendance.save(); await attendance.save();
res.status(201).json({ res.status(201).json({
success: true, success: true,
message: "Attendance marked successfully", message: "Attendance marked successfully",
record: { date, time, location, notes }, record: { date: startOfDay, time, location, notes },
}); });
} catch (error) { } catch (error) {
console.error("Error marking attendance:", error);
res.status(500).json({ res.status(500).json({
success: false, success: false,
message: error.message || "Something went wrong", message: error.message || "Something went wrong",
@ -262,14 +147,6 @@ export const markAttendance = async (req, res) => {
} }
}; };
// Helper function to check if two dates are on the same day
function isSameDay(date1, date2) {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
}
// Get attendance by user ID // Get attendance by user ID
export const getAttendanceByUser = async (req, res) => { export const getAttendanceByUser = async (req, res) => {
@ -340,66 +217,102 @@ export const AdmingetAttendanceByUser = async (req, res) => {
// Get today's attendance for admin // Get today's attendance for admin
export const getTodayAttendance = async (req, res) => { export const getTodayAttendance = async (req, res) => {
try { try {
// Step 1: Get today's date in UTC and set the time to start and end of the day
const today = new Date(); const today = new Date();
today.setHours(0, 0, 0, 0); const todayStartUTC = new Date(
Date.UTC(
const startOfDay = new Date(today); today.getUTCFullYear(),
const endOfDay = new Date(today); today.getUTCMonth(),
endOfDay.setHours(23, 59, 59, 999); today.getUTCDate(),
0,
0,
0
)
);
const tomorrowStartUTC = new Date(todayStartUTC);
tomorrowStartUTC.setUTCDate(todayStartUTC.getUTCDate() + 1); // Start of the next day
// Step 2: Parse query parameters
const { page = 1, show = 10 } = req.query; const { page = 1, show = 10 } = req.query;
const limit = parseInt(show); const limit = parseInt(show, 10);
const skip = (page - 1) * limit; const skip = (page - 1) * limit;
// Step 3: Aggregate query to get today's attendance records
const attendances = await Attendance.aggregate([ const attendances = await Attendance.aggregate([
{ $unwind: '$records' }, { $unwind: "$records" },
{ {
$match: { $match: {
'records.date': { $gte: startOfDay, $lte: endOfDay } "records.date": {
} $gte: todayStartUTC,
$lt: tomorrowStartUTC,
},
},
}, },
{ {
$lookup: { $lookup: {
from: 'users', from: "salescoordinators",
localField: 'userId', localField: "userId",
foreignField: '_id', foreignField: "_id",
as: 'user' as: "salesCoOrdinatorUser",
} },
}, },
{ $unwind: '$user' },
{ {
$facet: { $lookup: {
totalData: [{ $count: 'count' }], from: "territorymanagers",
attendance: [ localField: "userId",
{ $skip: skip }, foreignField: "_id",
{ $limit: limit }, as: "territoryManagerUser",
{ },
$project: { },
user: { {
id: '$user._id', $addFields: {
name: '$user.name', user: {
email: '$user.email', $cond: {
userType: '$userType' if: { $eq: ["$userType", "SalesCoOrdinator"] },
}, then: { $arrayElemAt: ["$salesCoOrdinatorUser", 0] },
date: '$records.date', else: { $arrayElemAt: ["$territoryManagerUser", 0] },
time: '$records.time', },
location: '$records.location', },
notes: '$records.notes', },
} },
} {
] $project: {
} salesCoOrdinatorUser: 0,
} territoryManagerUser: 0,
},
},
]); ]);
const totalData = attendances.length;
const paginatedattendance = attendances.slice(skip, skip + limit);
// Step 6: Format the response
const formattedattendance = paginatedattendance.map((record) => ({
user: record.user
? {
id: record.user._id,
name: record.user.name,
email: record.user.email,
mobileNumber: record.user.mobileNumber,
userType: record.userType,
uniqueId: record.user.uniqueId,
}
: null,
date: record.records.date,
time: record.records.time,
location: record.records.location,
reason: record.records.reason,
leaveType: record.records.leaveType,
}));
const totalData = attendances[0].totalData[0]?.count || 0; // Send response
res.status(200).json({ res.status(200).json({
success: true, success: true,
total_data: totalData, total_data: totalData,
attendance: attendances[0].attendance attendance: formattedattendance,
page: parseInt(page, 10),
limit: limit,
}); });
} catch (error) { } catch (error) {
console.error("Error fetching todays attendance:", error);
res.status(500).json({ res.status(500).json({
success: false, success: false,
message: error.message || "Something went wrong", message: error.message || "Something went wrong",

View File

@ -1,34 +1,3 @@
// import mongoose from 'mongoose';
// const attendanceRecordSchema = new mongoose.Schema({
// date: {
// type: Date,
// required: true,
// },
// time: {
// type: String,
// required: true,
// },
// location: {
// type: String,
// required: true,
// },
// notes: {
// type: String,
// },
// });
// const attendanceSchema = new mongoose.Schema({
// salesCoordinator: {
// type: mongoose.Schema.Types.ObjectId,
// ref: 'SalesCoOrdinator',
// required: true,
// unique: true,
// },
// records: [attendanceRecordSchema],
// }, { timestamps: true, versionKey: false });
// export const AttendanceSalesCoOrdinator = mongoose.model('Attendance', attendanceSchema);
import mongoose from 'mongoose'; import mongoose from 'mongoose';
// Define attendance record schema // Define attendance record schema
@ -60,7 +29,7 @@ const attendanceSchema = new mongoose.Schema({
userType: { userType: {
type: String, type: String,
required: true, required: true,
enum: ['SalesCoOrdinator', 'TerritoryManager'], // Specify allowed user types enum: ['SalesCoOrdinator', 'TerritoryManager'],
}, },
records: [attendanceRecordSchema], records: [attendanceRecordSchema],
}, { timestamps: true, versionKey: false }); }, { timestamps: true, versionKey: false });

View File

@ -0,0 +1,250 @@
import { Leave } from "./LeaveModel.js";
// Mark leave
export const markLeave = async (req, res) => {
try {
const { date, time, location, reason, leaveType } = req.body;
const userId = req.user._id;
const userType = req.userType;
// Parse the input date
const [year, month, day] = date.split("/");
const parsedDate = new Date(Date.UTC(year, month - 1, day));
const today = new Date();
today.setUTCHours(0, 0, 0, 0);
// Check if the date in req.body is not today's date
if (parsedDate.getTime() !== today.getTime()) {
return res.status(400).json({
success: false,
message: `Leave can only be marked for today's date: ${
today.toISOString().split("T")[0]
}`,
});
}
// Get the start and end of the day to check if the leave is already marked
const startOfDay = new Date(parsedDate);
const endOfDay = new Date(parsedDate);
endOfDay.setUTCHours(23, 59, 59, 999);
// Check if the leave record exists for today
const existingLeave = await Leave.findOne({
userId,
userType,
records: {
$elemMatch: {
date: { $gte: startOfDay, $lte: endOfDay },
},
},
});
if (existingLeave) {
return res.status(400).json({
success: false,
message: "Leave for today is already marked.",
});
}
// Check if leave record exists for the user
let leave = await Leave.findOne({ userId, userType });
if (!leave) {
// Create a new leave record if it doesn't exist
leave = new Leave({
userId,
userType,
records: [],
});
}
// Add the new leave record to the array
leave.records.push({ date: startOfDay, time, location, reason, leaveType });
await leave.save();
res.status(201).json({
success: true,
message: "Leave marked successfully",
record: { date: startOfDay, time, location, reason, leaveType },
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message || "Something went wrong",
});
}
};
// Helper function to check if two dates are on the same day
function isSameDay(date1, date2) {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
}
// Get leave by user ID
export const getLeaveByUser = async (req, res) => {
try {
const userId = req.user._id;
const leave = await Leave.findOne({
userId,
}).populate("userId", "name email");
if (!leave) {
return res.status(404).json({
success: false,
message: "No leave records found for this user.",
});
}
res.status(200).json({
success: true,
leave,
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message || "Something went wrong",
});
}
};
// Admin route to get leave by user ID
export const AdmingetLeaveByUser = async (req, res) => {
try {
const { id } = req.params;
const { page = 1, show = 10 } = req.query;
const limit = parseInt(show);
const skip = (page - 1) * limit;
// Find leave records for the given user
const leaveDoc = await Leave.findOne({
userId: id,
}).populate("userId", "name email");
if (!leaveDoc) {
return res.status(404).json({
success: false,
message: "No leave records found for this user.",
});
}
// Pagination and slicing records
const totalData = leaveDoc.records.length;
const paginatedRecords = leaveDoc.records.slice(skip, skip + limit);
res.status(200).json({
success: true,
user: leaveDoc.userId,
leave: paginatedRecords,
total_data: totalData,
});
} catch (error) {
res.status500().json({
success: false,
message: error.message || "Something went wrong",
});
}
};
export const getTodayLeave = async (req, res) => {
try {
// Step 1: Get today's date in UTC and set the time to 00:00:00.000
const today = new Date();
const todayStartUTC = new Date(Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), 0, 0, 0));
const tomorrowStartUTC = new Date(todayStartUTC);
tomorrowStartUTC.setUTCDate(todayStartUTC.getUTCDate() + 1); // Start of the next day
// Step 2: Parse query parameters
const { page = 1, show = 10 } = req.query;
const limit = parseInt(show, 10);
const skip = (page - 1) * limit;
// Step 3: Aggregate query to get today's leave records
const leavesWithUserLookup = await Leave.aggregate([
{ $unwind: '$records' },
{
$match: {
'records.date': {
$gte: todayStartUTC,
$lt: tomorrowStartUTC
}
}
},
{
$lookup: {
from: 'salescoordinators',
localField: 'userId',
foreignField: '_id',
as: 'salesCoOrdinatorUser'
}
},
{
$lookup: {
from: 'territorymanagers',
localField: 'userId',
foreignField: '_id',
as: 'territoryManagerUser'
}
},
{
$addFields: {
user: {
$cond: {
if: { $eq: ["$userType", "SalesCoOrdinator"] },
then: { $arrayElemAt: ["$salesCoOrdinatorUser", 0] },
else: { $arrayElemAt: ["$territoryManagerUser", 0] }
}
}
}
},
{
$project: {
salesCoOrdinatorUser: 0,
territoryManagerUser: 0
}
}
]);
// Step 4: Calculate total data
const totalData = leavesWithUserLookup.length;
// Step 5: Implement pagination
const paginatedLeaves = leavesWithUserLookup.slice(skip, skip + limit);
// Step 6: Format the response
const formattedLeaves = paginatedLeaves.map(record => ({
user: record.user ? {
id: record.user._id,
name: record.user.name,
email: record.user.email,
mobileNumber: record.user.mobileNumber,
userType: record.userType,
uniqueId: record.user.uniqueId,
} : null,
date: record.records.date,
time: record.records.time,
location: record.records.location,
reason: record.records.reason,
leaveType: record.records.leaveType,
}));
// Send response
res.status(200).json({
success: true,
total_data: totalData,
leave: formattedLeaves,
page: parseInt(page, 10),
limit: limit,
});
} catch (error) {
console.error("Error fetching todays leave:", error);
res.status(500).json({
success: false,
message: error.message || "Something went wrong",
});
}
};

View File

@ -0,0 +1,43 @@
import mongoose from 'mongoose';
// Define leave record schema
const leaveRecordSchema = new mongoose.Schema({
date: {
type: Date,
required: true,
},
time: {
type: String,
required: true,
},
location: {
type: String,
required: true,
},
reason: {
type: String,
required: true,
},
leaveType: {
type: String,
required: true,
enum: ['Sick Leave', 'Casual Leave'],
},
});
// Define main leave schema
const leaveSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
refPath: 'userType',
required: true,
},
userType: {
type: String,
required: true,
enum: ['SalesCoOrdinator', 'TerritoryManager'],
},
records: [leaveRecordSchema],
}, { timestamps: true, versionKey: false });
export const Leave = mongoose.model('Leave', leaveSchema);

View File

@ -0,0 +1,60 @@
import express from "express";
import {
markLeave,
getLeaveByUser,
getTodayLeave,
AdmingetLeaveByUser,
} from "./LeaveController.js";
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
// import { isAuthenticatedTerritoryManager } from "../../middlewares/TerritoryManagerAuth.js";
import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js";
const router = express.Router();
// Place more specific routes first
// Route to get today's leave for admin
router.get(
"/leave/today",
isAuthenticatedUser,
authorizeRoles("admin"),
getTodayLeave
);
// Route to mark leave for Sales Coordinators
router.post(
"/markleave/salescoordinator",
isAuthenticatedSalesCoOrdinator,
markLeave
);
// Route to mark leave for Territory Managers
router.post(
"/markleave/territorymanager",
// isAuthenticatedTerritoryManager,
markLeave
);
// Route to get leave for the logged-in sales coordinator
router.get(
"/leave/salescoordinator",
isAuthenticatedSalesCoOrdinator,
getLeaveByUser
);
// Route to get leave for the logged-in territory manager
router.get(
"/leave/territorymanager",
// isAuthenticatedTerritoryManager,
getLeaveByUser
);
// Admin route to get leave by user ID
router.get(
"/leave/:id",
isAuthenticatedUser,
authorizeRoles("admin"),
AdmingetLeaveByUser
);
export default router;