Updated project logs function

This commit is contained in:
Aakash Mittal 2025-11-07 19:34:23 +05:30
parent e55183a2ef
commit 07075bdefb
3 changed files with 121 additions and 32 deletions

View File

@ -1,5 +1,11 @@
import { LoggedModel, ProjectModel } from "../../../models/vaModel.js"; import { LoggedModel, ProjectModel } from "../../../models/vaModel.js";
function formatHMS(totalSeconds) {
const hrs = Math.floor(totalSeconds / 3600);
const mins = Math.floor((totalSeconds % 3600) / 60);
const secs = Math.floor(totalSeconds % 60);
return `${hrs}h ${mins}m ${secs}s`;
}
async function va_log_callback(req, res) { async function va_log_callback(req, res) {
try { try {
@ -35,42 +41,86 @@ async function va_log_callback(req, res) {
}; };
const logs = await LoggedModel.find(query).sort({ time: 1 }); const logs = await LoggedModel.find(query).sort({ time: 1 }).lean();
if (!logs.length) { if (!logs.length) {
return res.json({ success: true, message: "No logs found", totalWork: "0h 0m" }); return res.json({ success: true, message: "No logs found", totalWork: "0h 0m 0s", totalSeconds: 0, sessions: [] });
} }
// Find first LOGIN and last LOGOUT let totalSeconds = 0;
const firstLogin = logs.find((l) => l.loggedType === "LOGIN"); const sessions = [];
const lastLogout = [...logs].reverse().find((l) => l.loggedType === "LOGOUT"); let lastLogin = null; // keep Date object
let lastLoginRaw = null; // raw log object for session details
if (!firstLogin || !lastLogout) { for (const log of logs) {
return res.json({ const t = new Date(log.time);
success: true,
message: "Incomplete log data (missing LOGIN or LOGOUT)", if (String(log.loggedType).toUpperCase() === "LOGIN") {
totalWork: "0h 0m", // If there's already an open login (multiple consecutive LOGINS), ignore the new one
firstLogin, if (!lastLogin) {
lastLogout, lastLogin = t;
lastLoginRaw = log;
} else {
// consecutive LOGIN without LOGOUT — ignore this login (or you may choose to update lastLogin to this newer time)
// we'll ignore to favor the first login until a logout arrives
}
} else if (String(log.loggedType).toUpperCase() === "LOGOUT") {
if (lastLogin) {
// valid pair: lastLogin -> this logout
const diffSec = Math.floor((t - lastLogin) / 1000);
if (diffSec > 0) {
totalSeconds += diffSec;
sessions.push({
loginId: lastLoginRaw?._id || null,
logoutId: log._id,
from: lastLogin,
to: t,
durationSeconds: diffSec,
durationFormatted: formatHMS(diffSec)
}); });
} }
// reset for next pair
lastLogin = null;
lastLoginRaw = null;
} else {
// LOGOUT with no preceding LOGIN in range — ignore
}
}
}
// Calculate duration // If there's an open LOGIN at the end of the range, close it at toDate (or now if toDate > now)
const diffMs = new Date(lastLogout.time) - new Date(firstLogin.time); if (lastLogin) {
const totalMinutes = Math.floor(diffMs / (1000 * 60)); // Use the smaller of toDate and current time as the end point
const hours = Math.floor(totalMinutes / 60); const now = new Date();
const minutes = totalMinutes % 60; const endPoint = toDate > now ? now : toDate;
res.json({ const diffSec = Math.floor((endPoint - lastLogin) / 1000);
if (diffSec > 0) {
totalSeconds += diffSec;
sessions.push({
loginId: lastLoginRaw?._id || null,
logoutId: null,
from: lastLogin,
to: endPoint,
durationSeconds: diffSec,
durationFormatted: formatHMS(diffSec),
note: "Open session closed at range end"
});
}
}
return res.json({
success: true, success: true,
vaId, vaId,
projectId, projectId,
firstLogin: firstLogin.time, from: fromDate,
lastLogout: lastLogout.time, to: toDate,
logs: logs, logs,
totalTimeLogged: `${hours}h ${minutes}m`, sessions,
hoursLogged: hours, totalTimeLogged: formatHMS(totalSeconds),
minutesLogged: minutes, totalSeconds,
hoursLogged: Math.floor(totalSeconds / 3600),
minutesLogged: Math.floor((totalSeconds % 3600) / 60),
}); });
} catch (err) { } catch (err) {

View File

@ -47,26 +47,59 @@ async function va_profile_update_callback(req, res) {
} }
}); });
if (userDetails.password) { /* ---------------------- PASSWORD UPDATE ---------------------- */
if (!userDetails.cPassword) { if (userDetails.password || userDetails.cPassword || userDetails.oldPassword) {
const { oldPassword, password, cPassword } = userDetails;
if (!oldPassword || !password || !cPassword) {
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
message: "Please confirm your new password", message: "Please provide oldPassword, password, and cPassword to update password",
}); });
} }
if (userDetails.password !== userDetails.cPassword) { if (password !== cPassword) {
return res.status(400).json({ return res.status(400).json({
success: false, success: false,
message: "Passwords do not match", message: "New passwords do not match",
}); });
} }
// Verify old password
const isMatch = await bcrypt.compare(oldPassword, vaUser.userDetails.password);
if (!isMatch) {
return res.status(400).json({
success: false,
message: "Old password is incorrect",
});
}
// Hash and update new password
const saltRounds = 10; const saltRounds = 10;
const hashedPassword = await bcrypt.hash(userDetails.password, saltRounds); const hashedPassword = await bcrypt.hash(password, saltRounds);
vaUser.userDetails.password = hashedPassword; vaUser.userDetails.password = hashedPassword;
} }
// if (userDetails.password) {
// if (!userDetails.cPassword) {
// return res.status(400).json({
// success: false,
// message: "Please confirm your new password",
// });
// }
// if (userDetails.password !== userDetails.cPassword) {
// return res.status(400).json({
// success: false,
// message: "Passwords do not match",
// });
// }
// const saltRounds = 10;
// const hashedPassword = await bcrypt.hash(userDetails.password, saltRounds);
// vaUser.userDetails.password = hashedPassword;
// }
await vaUser.save(); await vaUser.save();
const updatedUser = await VAModel.findById(vaUser._id) const updatedUser = await VAModel.findById(vaUser._id)

View File

@ -37,7 +37,13 @@ vaRoutes.get("/search", va_filter_search);
vaRoutes.get("/clients/:clientID", va_clients_callback); // VA Clients Callback for getting all clients or specific client by ID vaRoutes.get("/clients/:clientID", va_clients_callback); // VA Clients Callback for getting all clients or specific client by ID
vaRoutes.get("/clients/:clientId/projects/:projectId", va_clients_projects_callback); // VA Clients Projects Callback vaRoutes.get("/clients/:clientId/projects/:projectId", va_clients_projects_callback); // VA Clients Projects Callback
vaRoutes.get("/project/:projectId", va_projects_callback);
// Getting Project List assigned to VA should be ACTIVE and add total logged hours added by VA
vaRoutes.get("/list/project/:projectId", va_projects_callback);
// GET Windows Tab Logged Data for VA IN Between Login and LOGOUT
vaRoutes.get("/report/project/:projectId", va_projects_callback);
vaRoutes.post("/log/project", authValidator, va_project_log_callback); // VA Logged IN / Logged Out in project vaRoutes.post("/log/project", authValidator, va_project_log_callback); // VA Logged IN / Logged Out in project