va-tracker-middleware/src/controllers/client/dashboard/clientDashboardVaLog.contro...

166 lines
5.8 KiB
JavaScript

import jwt from "jsonwebtoken";
import { VAModel, ProjectModel, LoggedModel, ClientModel } from "../../../models/vaModel.js";
// Helper function to parse date string in DD-MM-YYYY format
function parseDate(dateString) {
if (!dateString) return null;
const parts = dateString.split('-');
if (parts.length !== 3) return null;
const day = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10) - 1; // Months are 0-indexed in JavaScript
const year = parseInt(parts[2], 10);
// Validate date components
if (isNaN(day) || isNaN(month) || isNaN(year)) return null;
if (day < 1 || day > 31 || month < 0 || month > 11 || year < 1900) return null;
return new Date(year, month, day);
}
// Getting logged hours in a specific project of VA
async function client_dashboard_va_log(req, res) {
console.log(req)
try {
const accessToken = req.headers.token;
if (!accessToken) {
return res.status(401).json({ success: false, message: "Missing token" });
}
const decoded = jwt.verify(accessToken, process.env.JWT_SECRET_ACCESS_TOKEN);
if (!decoded || !decoded.email) {
return res.status(401).json({ success: false, message: "Invalid token" });
}
const clientEmail = decoded.email;
const clientUser = await ClientModel.findOne({ "userDetails.email": clientEmail });
if (!clientUser) {
return res.status(404).json({ success: false, message: "Client not found" });
}
const clientID = clientUser._id;
const clientProjectIds = clientUser.projectIds || [];
const payload = req.body || {};
const { vaId } = payload;
// const va = await VAModel.findOne({
// _id: vaId,
// clientIds: clientID
// });
// if (!va) {
// return res.status(403).json({
// success: false,
// message: "VA not found or not assigned to this client"
// });
// }
let logs = await LoggedModel.find({
vaId,
projectId: { $in: clientProjectIds },
})
.sort({ time: 1 })
.populate("projectId", "name") // attach project name
.lean();
if (!logs.length) {
return res.status(200).json({
success: true,
message: "No logs found in given range",
data: [],
totalWorkTime: "00:00:00",
});
}
let totalWorkSeconds = 0;
const projectWork = {}; // key: projectId -> seconds
// Group logs by date (YYYY-MM-DD format)
const logsByDate = {};
logs.forEach(log => {
const date = new Date(log.time).toISOString().split('T')[0]; // YYYY-MM-DD
if (!logsByDate[date]) {
logsByDate[date] = [];
}
logsByDate[date].push(log);
});
// Process each day separately
for (const [date, dayLogs] of Object.entries(logsByDate)) {
// Check if this day has any adjustment logs
const hasAdjustmentLogs = dayLogs.some(log => log.isAdjustment === true);
let dayWorkSeconds = 0;
let lastLogin = null;
let lastProjectId = null;
// If day has adjustment logs, only process adjustment logs
// If no adjustment logs, process all logs for that day
const logsToProcess = hasAdjustmentLogs
? dayLogs.filter(log => log.isAdjustment === true)
: dayLogs;
// Sort logs by time for proper pairing (already sorted by query, but ensure)
logsToProcess.sort((a, b) => new Date(a.time) - new Date(b.time));
// Calculate work duration for this day
for (const log of logsToProcess) {
const time = new Date(log.time);
if (log.loggedType === "LOGIN") {
lastLogin = time;
lastProjectId = log.projectId?._id?.toString() || null;
} else if (log.loggedType === "LOGOUT" && lastLogin) {
const diffSec = (time - lastLogin) / 1000;
dayWorkSeconds += diffSec;
if (lastProjectId) {
projectWork[lastProjectId] = (projectWork[lastProjectId] || 0) + diffSec;
}
// reset after each pair
lastLogin = null;
lastProjectId = null;
}
}
totalWorkSeconds += dayWorkSeconds;
}
// 🕓 Convert total seconds to hh:mm:ss
const formatTime = (seconds) => {
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
return `${h.toString().padStart(2, "0")}:${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
};
// 🧠 Build project-wise array
const projectDetails = await Promise.all(
Object.entries(projectWork).map(async ([projectId, sec]) => {
const project = await ProjectModel.findById(projectId).lean();
return {
projectId,
projectName: project?.name || "Unknown Project",
totalTime: formatTime(sec),
};
})
);
return res.status(200).json({
success: true,
totalWorkTime: formatTime(totalWorkSeconds),
projects: projectDetails,
});
} catch (error) {
console.log(error)
return res.status(500).send("Internal Server Error");
}
}
export { client_dashboard_va_log };