diff --git a/src/controllers/client/vaClient.controller.js b/src/controllers/client/vaClient.controller.js index 4bd8cb1..0da8485 100644 --- a/src/controllers/client/vaClient.controller.js +++ b/src/controllers/client/vaClient.controller.js @@ -8,45 +8,48 @@ const vaClientService = new VaClientService(new VaClientRepository()); async function va_register_client(req, res) { logger.info("ClientController - Register Client Hit ..."); - + try { const payload = req.body || {}; const { userDetails } = payload; if (!userDetails || !userDetails.email || !userDetails.name) { - return res.status(400).json({ - success: false, - message: "Missing required fields: name and email are required" + return res.status(400).json({ + success: false, + message: "Missing required fields: name and email are required" }); } const created = await vaClientService.registerClient(payload); logger.info(`ClientController - Client registered successfully: ${userDetails.email}`); - return res.status(201).json({ - success: true, + await passwordResetService.requestPasswordReset(userDetails.email, 'client'); + logger.info(`Client password reset requested for: ${email}`); + + return res.status(201).json({ + success: true, data: created, - message: "Client registered successfully" + message: "Client registered successfully" }); } catch (error) { logger.error(`ClientController - Register error: ${error.message}`); - + if (error.message === "User already exists with this email") { - return res.status(409).json({ - success: false, - message: error.message + return res.status(409).json({ + success: false, + message: error.message }); } if (error.message.includes("Salesforce API is unreachable")) { - return res.status(503).json({ - success: false, - message: "Salesforce service is currently unavailable. Please try again later." + return res.status(503).json({ + success: false, + message: "Salesforce service is currently unavailable. Please try again later." }); } - return res.status(500).json({ - success: false, - message: "Internal Server Error" + return res.status(500).json({ + success: false, + message: "Internal Server Error" }); } } @@ -56,52 +59,52 @@ async function get_client_profile(req, res) { try { const email = req.body.clientEmail; const client = await vaClientService.getClientByEmail(email); - + if (!client) { - return res.status(404).json({ - success: false, - message: "Client not found" + return res.status(404).json({ + success: false, + message: "Client not found" }); } - return res.status(200).json({ - success: true, - data: client + return res.status(200).json({ + success: true, + data: client }); } catch (error) { logger.error(`ClientController - Get client error: ${error.message}`); - return res.status(500).json({ - success: false, - message: "Internal Server Error" + return res.status(500).json({ + success: false, + message: "Internal Server Error" }); } } async function delete_client(req, res) { logger.info("ClientController - Delete Client Hit ..."); - + try { const { clientId } = req.params; if (!clientId) { - return res.status(400).json({ - success: false, - message: "Client ID is required" + return res.status(400).json({ + success: false, + message: "Client ID is required" }); } const deletedClient = await vaClientService.deleteClient(clientId); if (!deletedClient) { - return res.status(404).json({ - success: false, - message: "Client not found" + return res.status(404).json({ + success: false, + message: "Client not found" }); } logger.info(`ClientController - Client deleted successfully: ${clientId}`); - return res.status(200).json({ - success: true, + return res.status(200).json({ + success: true, message: "Client deleted successfully", data: { clientId: clientId, @@ -111,79 +114,79 @@ async function delete_client(req, res) { }); } catch (error) { logger.error(`ClientController - Delete error: ${error.message}`); - + if (error.message === "Client not found") { - return res.status(404).json({ - success: false, - message: error.message + return res.status(404).json({ + success: false, + message: error.message }); } - return res.status(500).json({ - success: false, - message: "Internal Server Error" + return res.status(500).json({ + success: false, + message: "Internal Server Error" }); } } async function update_client(req, res) { logger.info("ClientController - Update Client Hit ..."); - + try { const { clientId } = req.params; const payload = req.body || {}; const { userDetails } = payload; if (!clientId) { - return res.status(400).json({ - success: false, - message: "Client ID is required" + return res.status(400).json({ + success: false, + message: "Client ID is required" }); } if (!userDetails) { - return res.status(400).json({ - success: false, - message: "Missing userDetails in request body" + return res.status(400).json({ + success: false, + message: "Missing userDetails in request body" }); } const updatedClient = await vaClientService.updateClient(clientId, payload); logger.info(`ClientController - Client updated successfully: ${clientId}`); - return res.status(200).json({ - success: true, + return res.status(200).json({ + success: true, message: "Client updated successfully", data: updatedClient }); } catch (error) { logger.error(`ClientController - Update error: ${error.message}`); - + if (error.message === "Client not found") { - return res.status(404).json({ - success: false, - message: error.message + return res.status(404).json({ + success: false, + message: error.message }); } if (error.message.includes("Email already exists")) { - return res.status(409).json({ - success: false, - message: error.message + return res.status(409).json({ + success: false, + message: error.message }); } - return res.status(500).json({ - success: false, - message: error.message + return res.status(500).json({ + success: false, + message: error.message }); } } async function get_client_dashboard_profile(req, res) { try { - const accessToken = req.headers.token; - + const accessToken = req.headers.token; + if (!accessToken) { return res.status(401).json({ success: false, message: "Missing token" }); } @@ -195,14 +198,14 @@ async function get_client_dashboard_profile(req, res) { } const clientEmail = decoded.email; - + // Use the new method that returns only necessary fields const client = await vaClientService.getClientProfileByEmail(clientEmail); - + if (!client) { - return res.status(404).json({ - success: false, - message: "Client not found" + return res.status(404).json({ + success: false, + message: "Client not found" }); } @@ -217,15 +220,15 @@ async function get_client_dashboard_profile(req, res) { position: client.userDetails?.position || '' }; - return res.status(200).json({ - success: true, - data: profileData + return res.status(200).json({ + success: true, + data: profileData }); } catch (error) { logger.error(`ClientController - Get dashboard profile error: ${error.message}`); - return res.status(500).json({ - success: false, - message: "Internal Server Error" + return res.status(500).json({ + success: false, + message: "Internal Server Error" }); } } @@ -234,8 +237,8 @@ async function update_client_password(req, res) { logger.info("ClientController - Update Client Password Hit ..."); console.log("Update Client Password - Request Body:", req.body); try { - const accessToken = req.headers.token; - + const accessToken = req.headers.token; + if (!accessToken) { return res.status(401).json({ success: false, message: "Missing token" }); } @@ -249,14 +252,14 @@ async function update_client_password(req, res) { const clientEmail = decoded.email; const payload = req.body || {}; const { userDetails } = payload; - + // Get client by email to get the ID const client = await vaClientService.getClientByEmail(clientEmail); - + if (!client) { - return res.status(404).json({ - success: false, - message: "Client not found" + return res.status(404).json({ + success: false, + message: "Client not found" }); } @@ -266,41 +269,41 @@ async function update_client_password(req, res) { const result = await vaClientService.updateClientPassword(clientId, userDetails); logger.info(`ClientController - Client password updated successfully: ${clientEmail}`); - - return res.status(200).json({ - success: true, + + return res.status(200).json({ + success: true, message: "Password updated successfully", data: result }); } catch (error) { logger.error(`ClientController - Update password error: ${error.message}`); - + if (error.message === "Client not found") { - return res.status(404).json({ - success: false, - message: error.message + return res.status(404).json({ + success: false, + message: error.message }); } if (error.message.includes("Current password is incorrect") || - error.message.includes("New passwords do not match") || - error.message.includes("All password fields are required")) { - return res.status(400).json({ - success: false, - message: error.message + error.message.includes("New passwords do not match") || + error.message.includes("All password fields are required")) { + return res.status(400).json({ + success: false, + message: error.message }); } - return res.status(500).json({ - success: false, - message: "Internal Server Error" + return res.status(500).json({ + success: false, + message: "Internal Server Error" }); } } -export { - va_register_client, +export { + va_register_client, get_client_profile, delete_client, update_client, diff --git a/src/controllers/va/vaLog/vaLogTrackWork.controller.js b/src/controllers/va/vaLog/vaLogTrackWork.controller.js index 8333dfd..7fb27df 100644 --- a/src/controllers/va/vaLog/vaLogTrackWork.controller.js +++ b/src/controllers/va/vaLog/vaLogTrackWork.controller.js @@ -5,10 +5,10 @@ import { WorkTrackModel, VAModel, ProjectModel, LoggedModel } from "../../../mod function getDayRange(date = new Date()) { const start = new Date(date); start.setHours(0, 0, 0, 0); - + const end = new Date(date); end.setHours(23, 59, 59, 999); - + return { start, end }; } @@ -16,7 +16,7 @@ function formatHoursToReadable(hours) { const wholeHours = Math.floor(hours); const decimalMinutes = (hours - wholeHours) * 60; const wholeMinutes = Math.round(decimalMinutes); - + if (wholeHours > 0 && wholeMinutes > 0) { return `${wholeHours}h ${wholeMinutes}m`; } else if (wholeHours > 0) { @@ -31,7 +31,7 @@ async function checkDailyHoursAndLogout(vaId, vaEmail, projectId, project, curre try { const today = new Date(); const { start, end } = getDayRange(today); - + // Get today's work entries for this VA and project // Exclude the current session if it's already in the database const query = { @@ -39,23 +39,23 @@ async function checkDailyHoursAndLogout(vaId, vaEmail, projectId, project, curre projectId, from: { $gte: start, $lte: end } }; - + if (currentSessionId) { query._id = { $ne: currentSessionId }; } - + const todayWorkEntries = await WorkTrackModel.find(query); - + // Calculate total hours worked today let totalTodayMs = todayWorkEntries.reduce((total, entry) => { return total + (entry.totalTime || 0); }, 0); - + // Add the additional time from current session if provided totalTodayMs += additionalTimeMs; - + const totalTodayHours = totalTodayMs / (1000 * 60 * 60); - + // Check if daily dedicated hours are completed if (project.dedicatedHours > 0 && totalTodayHours >= project.dedicatedHours) { // Create automatic logout log @@ -69,13 +69,13 @@ async function checkDailyHoursAndLogout(vaId, vaEmail, projectId, project, curre try { const salesforceUrl = `${process.env.SF_DOCTRACKER_API_URL}services/apexrest/docva/api/va-project-log`; const sfDataSync = { - "_id": logoutLog._id, - "loggedType": "LOGOUT", - "vaId": vaId, - "vaEmail": vaEmail, - "projectId": projectId, - "time": logoutLog.time, - } + "_id": logoutLog._id, + "loggedType": "LOGOUT", + "vaId": vaId, + "vaEmail": vaEmail, + "projectId": projectId, + "time": logoutLog.time, + } const response = await fetch(salesforceUrl, { method: 'POST', @@ -86,7 +86,7 @@ async function checkDailyHoursAndLogout(vaId, vaEmail, projectId, project, curre }, body: JSON.stringify(sfDataSync) }); - + if (!response.ok) { const errorText = await response.text(); throw new Error(`Salesforce API responded with status ${response.status}: ${errorText}`); @@ -94,7 +94,7 @@ async function checkDailyHoursAndLogout(vaId, vaEmail, projectId, project, curre const result = await response.json(); // console.log("✅ Successfully synced VA data to Salesforce:", result); - + return { shouldLogout: true, totalTodayHours: totalTodayHours, @@ -105,14 +105,14 @@ async function checkDailyHoursAndLogout(vaId, vaEmail, projectId, project, curre } catch (error) { console.error("Failed to sync with Salesforce:", error.message); console.log(error) - + // Create a custom error to distinguish Salesforce errors const salesforceError = new Error(`Salesforce sync failed: ${error.message}`); salesforceError.isSalesforceError = true; throw salesforceError; } } - + return { shouldLogout: false, totalTodayHours: totalTodayHours, @@ -128,7 +128,7 @@ async function checkDailyHoursAndLogout(vaId, vaEmail, projectId, project, curre // Getting logged hours in a specific project of VA async function va_log_track_work_callback(req, res) { try { - const accessToken = req.headers.token; + const accessToken = req.headers.token; if (!accessToken) { return res.status(401).json({ success: false, message: "Missing token" }); } @@ -147,9 +147,14 @@ async function va_log_track_work_callback(req, res) { const vaId = vaUser._id; const payload = req.body || {}; - const { projectId, logId, title, appName, url = null } = payload; - const project = await ProjectModel.findById(projectId); + let { projectId, logId, title, appName, url = null } = payload; + + if (title === "") { + title = "" + } + + const project = await ProjectModel.findById(projectId); if (!project) return res.status(400).json({ success: false, message: "Project not found" }); const logEntry = await LoggedModel.findById(logId); @@ -175,7 +180,7 @@ async function va_log_track_work_callback(req, res) { // Handle POST → create entry if (req.method === "POST") { const dailyCheck = await checkDailyHoursAndLogout(vaId, vaEmail, projectId, project); - + if (dailyCheck.shouldLogout) { return res.status(400).json({ success: false, diff --git a/src/routes/v1/client.routes.js b/src/routes/v1/client.routes.js index 8c9c260..97f95e1 100644 --- a/src/routes/v1/client.routes.js +++ b/src/routes/v1/client.routes.js @@ -31,8 +31,6 @@ clientRoutes.delete("/tips/:tipId", clientAuthValidator, va_tips_delete); // clientRoutes.get("/:clientID?", va_clients_callback); // VA Clients Callback for getting all VA's or specific client by ID (NC) clientRoutes.get("/:clientId/projects/:projectId", va_clients_projects_callback); // VA Clients Projects Callback (NC) - - // dashboard API's clientRoutes.get("/dashboard", clientAuthValidator, client_dashboard); // VA Clients Projects Callback clientRoutes.post("/dashboard/va-report", clientAuthValidator, client_dashboard_va_log); // VA details diff --git a/views/client/dashboard-manage-va-tips.ejs b/views/client/dashboard-manage-va-tips.ejs index 14f9b4d..c73a03b 100644 --- a/views/client/dashboard-manage-va-tips.ejs +++ b/views/client/dashboard-manage-va-tips.ejs @@ -11,14 +11,14 @@ diff --git a/views/client_login.ejs b/views/client_login.ejs index d56945b..c483a9b 100644 --- a/views/client_login.ejs +++ b/views/client_login.ejs @@ -224,7 +224,7 @@ Forgot password? - +