From 0a30abbaa285dff8ca19f219a92077beb40183a2 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Wed, 6 Dec 2023 17:16:44 -0500 Subject: [PATCH 01/19] added timeOffFrom and timeOffTill fields to mongoDB --- src/controllers/reasonSchedulingController.js | 188 ++++++---- src/helpers/dashboardhelper.js | 339 +++++++++--------- src/models/userProfile.js | 104 +++--- 3 files changed, 348 insertions(+), 283 deletions(-) diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js index e310049c2..89b312bc2 100644 --- a/src/controllers/reasonSchedulingController.js +++ b/src/controllers/reasonSchedulingController.js @@ -1,23 +1,19 @@ - -const moment = require('moment-timezone'); -const UserModel = require('../models/userProfile'); -const ReasonModel = require('../models/reason'); +const moment = require("moment-timezone"); +const UserModel = require("../models/userProfile"); +const ReasonModel = require("../models/reason"); const emailSender = require("../utilities/emailSender"); - const postReason = async (req, res) => { try { const { userId, requestor, reasonData } = req.body; const newDate = moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day'); - const currentDate = moment - .tz('America/Los_Angeles') - .startOf('day'); + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day"); + const currentDate = moment.tz("America/Los_Angeles").startOf("day"); // error case 0 - if (moment.tz(reasonData.date, 'America/Los_Angeles').day() !== 0) { + if (moment.tz(reasonData.date, "America/Los_Angeles").day() !== 0) { return res.status(400).json({ message: "You must choose the Sunday YOU'LL RETURN as your date. This is so your reason ends up as a note on that blue square.", @@ -27,19 +23,19 @@ const postReason = async (req, res) => { if (newDate.isBefore(currentDate)) { return res.status(400).json({ - message: 'You should select a date that is yet to come', + message: "You should select a date that is yet to come", errorCode: 7, }); } if (!reasonData.message) { return res.status(400).json({ - message: 'You must provide a reason.', + message: "You must provide a reason.", errorCode: 6, }); } - //Commented this condition to make reason scheduler available to all the users. + //Commented this condition to make reason scheduler available to all the users. // error case 1 // if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') { // return res.status(403).json({ @@ -54,15 +50,61 @@ const postReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } + // new changes + + if ( + foundUser.hasOwnProperty("timeOffFrom") && + foundUser.hasOwnProperty("timeOffTill") + ) { + if (currentDate >= foundUser.timeOffTill) { + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffFrom: currentDate, + timeOffTill: newDate, + }, + } + ); + } else { + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffTill: newDate, + }, + } + ); + } + } else { + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffFrom: currentDate, + timeOffTill: newDate, + }, + } + ); + } + + // + const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); @@ -70,14 +112,14 @@ const postReason = async (req, res) => { // error case 3 if (foundReason) { return res.status(403).json({ - message: 'The reason must be unique to the date', + message: "The reason must be unique to the date", errorCode: 3, }); } const savingDate = moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(); const newReason = new ReasonModel({ @@ -86,16 +128,13 @@ const postReason = async (req, res) => { userId, }); - //await newReason.save(); - const savedData = await newReason.save(); - if(savedData) - { - + const savedData = await newReason.save(); + if (savedData) { //Upon clicking the "Save" button in the Blue Square Reason Scheduler, an email will be automatically sent to the user and Jae. - const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been set`; + const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been set`; - const emailBody = `

Hi !

+ const emailBody = `

Hi !

This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has set their Blue Square Reason.

@@ -104,23 +143,21 @@ const postReason = async (req, res) => {

Thank you,
One Community

`; - - - // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - // 2 user email - - emailSender(`${foundUser.email}`, subject, emailBody, null, null); + // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - //3 - user email and hardcoded email ( After PR approval hardcode Jae's email) - // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); - } - - return res.sendStatus(200); + // 2 user email - + emailSender(`${foundUser.email}`, subject, emailBody, null, null); + //3 - user email and hardcoded email ( After PR approval hardcode Jae's email) + // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); + } + + return res.sendStatus(200); } catch (error) { console.log(error); return res.status(400).json({ - errMessage: 'Something went wrong', + errMessage: "Something went wrong", }); } }; @@ -143,7 +180,7 @@ const getAllReasons = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", }); } @@ -157,7 +194,7 @@ const getAllReasons = async (req, res) => { } catch (error) { console.log(error); return res.status(400).json({ - errMessage: 'Something went wrong while fetching the user', + errMessage: "Something went wrong while fetching the user", }); } }; @@ -181,24 +218,24 @@ const getSingleReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(queryDate, 'America/Los_Angeles') - .startOf('day') + .tz(queryDate, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); if (!foundReason) { return res.status(200).json({ - reason: '', - date: '', - userId: '', + reason: "", + date: "", + userId: "", isSet: false, }); } @@ -207,7 +244,7 @@ const getSingleReason = async (req, res) => { } catch (error) { console.log(error); return res.status(400).json({ - message: 'Something went wrong while fetching single reason', + message: "Something went wrong while fetching single reason", }); } }; @@ -228,7 +265,7 @@ const patchReason = async (req, res) => { if (!reasonData.message) { return res.status(400).json({ - message: 'You must provide a reason.', + message: "You must provide a reason.", errorCode: 6, }); } @@ -238,36 +275,34 @@ const patchReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); // error case 4 if (!foundReason) { return res.status(404).json({ - message: 'Reason not found', + message: "Reason not found", errorCode: 4, }); } foundReason.reason = reasonData.message; - + const savedData = await foundReason.save(); - if(savedData) - { - + if (savedData) { //Upon clicking the "Save" button in the Blue Square Reason Scheduler, an email will be automatically sent to the user and Jae. - const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been updated`; + const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been updated`; - const emailBody = `

Hi !

+ const emailBody = `

Hi !

This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has updated their Blue Square Reason.

@@ -276,25 +311,22 @@ const patchReason = async (req, res) => {

Thank you,
One Community

`; - - - // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - // 2 user email - - emailSender(`${foundUser.email}`, subject, emailBody, null, null); + // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - //3 - user email and hardcoded email ( After PR approval hardcode Jae's email) - // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); - - - } + // 2 user email - + emailSender(`${foundUser.email}`, subject, emailBody, null, null); + + //3 - user email and hardcoded email ( After PR approval hardcode Jae's email) + // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); + } return res.status(200).json({ - message: 'Reason Updated!', + message: "Reason Updated!", }); } catch (error) { return res.status(400).json({ - message: 'something went wrong while patching the reason', + message: "something went wrong while patching the reason", }); } }; @@ -305,10 +337,10 @@ const deleteReason = async (req, res) => { const { userId } = req.params; //error case 1 - if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') { + if (requestor.role !== "Owner" && requestor.role !== "Administrator") { return res.status(403).json({ message: - 'You must be an Owner or Administrator to schedule a reason for a Blue Square', + "You must be an Owner or Administrator to schedule a reason for a Blue Square", errorCode: 1, }); } @@ -318,21 +350,21 @@ const deleteReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), }); if (!foundReason) { return res.status(404).json({ - message: 'Reason not found', + message: "Reason not found", errorCode: 4, }); } @@ -340,13 +372,13 @@ const deleteReason = async (req, res) => { foundReason.remove((err) => { if (err) { return res.status(500).json({ - message: 'Error while deleting document', + message: "Error while deleting document", errorCode: 5, }); } return res.status(200).json({ - message: 'Document deleted', + message: "Document deleted", }); }); } catch (error) {} diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 34d464583..64c867f71 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -1,26 +1,26 @@ -const moment = require('moment-timezone'); -const mongoose = require('mongoose'); -const userProfile = require('../models/userProfile'); -const timeentry = require('../models/timeentry'); -const myTeam = require('../helpers/helperModels/myTeam'); +const moment = require("moment-timezone"); +const mongoose = require("mongoose"); +const userProfile = require("../models/userProfile"); +const timeentry = require("../models/timeentry"); +const myTeam = require("../helpers/helperModels/myTeam"); const dashboardhelper = function () { const personaldetails = function (userId) { return userProfile.findById( userId, - '_id firstName lastName role profilePic badgeCollection', + "_id firstName lastName role profilePic badgeCollection" ); }; const getOrgData = async function () { const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); /** * Previous aggregate pipeline had two issues: @@ -39,35 +39,35 @@ const dashboardhelper = function () { $gte: 1, }, role: { - $ne: 'Mentor', + $ne: "Mentor", }, }, }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { $project: { - personId: '$_id', + personId: "$_id", name: 1, weeklycommittedHours: 1, role: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, ], }, @@ -77,7 +77,7 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -88,27 +88,27 @@ const dashboardhelper = function () { totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, tangibletime: { $cond: [ { - $eq: ['$timeEntryData.isTangible', true], + $eq: ["$timeEntryData.isTangible", true], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, intangibletime: { $cond: [ { - $eq: ['$timeEntryData.isTangible', false], + $eq: ["$timeEntryData.isTangible", false], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, @@ -117,17 +117,17 @@ const dashboardhelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", }, time_hrs: { - $sum: { $divide: ['$totalSeconds', 3600] }, + $sum: { $divide: ["$totalSeconds", 3600] }, }, tangibletime_hrs: { - $sum: { $divide: ['$tangibletime', 3600] }, + $sum: { $divide: ["$tangibletime", 3600] }, }, intangibletime_hrs: { - $sum: { $divide: ['$intangibletime', 3600] }, + $sum: { $divide: ["$intangibletime", 3600] }, }, }, }, @@ -135,15 +135,15 @@ const dashboardhelper = function () { $group: { _id: 0, memberCount: { $sum: 1 }, - totalweeklycommittedHours: { $sum: '$_id.weeklycommittedHours' }, + totalweeklycommittedHours: { $sum: "$_id.weeklycommittedHours" }, totaltime_hrs: { - $sum: '$time_hrs', + $sum: "$time_hrs", }, totaltangibletime_hrs: { - $sum: '$tangibletime_hrs', + $sum: "$tangibletime_hrs", }, totalintangibletime_hrs: { - $sum: '$intangibletime_hrs', + $sum: "$intangibletime_hrs", }, }, }, @@ -155,13 +155,13 @@ const dashboardhelper = function () { const getLeaderboard = function (userId) { const userid = mongoose.Types.ObjectId(userId); const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); return myTeam.aggregate([ { $match: { @@ -169,22 +169,22 @@ const dashboardhelper = function () { }, }, { - $unwind: '$myteam', + $unwind: "$myteam", }, { $project: { _id: 0, role: 1, - personId: '$myteam._id', - name: '$myteam.fullName', + personId: "$myteam._id", + name: "$myteam.fullName", }, }, { $lookup: { - from: 'userProfiles', - localField: 'personId', - foreignField: '_id', - as: 'persondata', + from: "userProfiles", + localField: "personId", + foreignField: "_id", + as: "persondata", }, }, { @@ -192,31 +192,37 @@ const dashboardhelper = function () { // leaderboard user roles hierarchy $or: [ { - role: { $in: ['Owner', 'Core Team'] }, + role: { $in: ["Owner", "Core Team"] }, }, { $and: [ { - role: 'Administrator', + role: "Administrator", }, - { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } }, - ] + { "persondata.0.role": { $nin: ["Owner", "Administrator"] } }, + ], }, { $and: [ { - role: { $in: ['Manager', 'Mentor'] }, + role: { $in: ["Manager", "Mentor"] }, }, { - 'persondata.0.role': { - $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'], + "persondata.0.role": { + $nin: [ + "Manager", + "Mentor", + "Core Team", + "Administrator", + "Owner", + ], }, }, ], }, - { 'persondata.0._id': userId }, - { 'persondata.0.role': 'Volunteer' }, - { 'persondata.0.isVisible': true }, + { "persondata.0._id": userId }, + { "persondata.0.role": "Volunteer" }, + { "persondata.0.isVisible": true }, ], }, }, @@ -225,31 +231,31 @@ const dashboardhelper = function () { personId: 1, name: 1, role: { - $arrayElemAt: ['$persondata.role', 0], + $arrayElemAt: ["$persondata.role", 0], }, isVisible: { - $arrayElemAt: ['$persondata.isVisible', 0], + $arrayElemAt: ["$persondata.isVisible", 0], }, hasSummary: { $ne: [ { $arrayElemAt: [ { - $arrayElemAt: ['$persondata.weeklySummaries.summary', 0], + $arrayElemAt: ["$persondata.weeklySummaries.summary", 0], }, 0, ], }, - '', + "", ], }, weeklycommittedHours: { $sum: [ { - $arrayElemAt: ['$persondata.weeklycommittedHours', 0], + $arrayElemAt: ["$persondata.weeklycommittedHours", 0], }, { - $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0], + $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0], }, ], }, @@ -257,10 +263,10 @@ const dashboardhelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: 'personId', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "personId", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -273,15 +279,15 @@ const dashboardhelper = function () { weeklycommittedHours: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, ], }, @@ -291,7 +297,7 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -306,18 +312,18 @@ const dashboardhelper = function () { totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, isTangible: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.isTangible', + "$timeEntryData.isTangible", false, ], }, @@ -328,18 +334,18 @@ const dashboardhelper = function () { tangibletime: { $cond: [ { - $eq: ['$isTangible', true], + $eq: ["$isTangible", true], }, - '$totalSeconds', + "$totalSeconds", 0, ], }, intangibletime: { $cond: [ { - $eq: ['$isTangible', false], + $eq: ["$isTangible", false], }, - '$totalSeconds', + "$totalSeconds", 0, ], }, @@ -348,58 +354,65 @@ const dashboardhelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', - name: '$name', - role: '$role', - isVisible: '$isVisible', - hasSummary: '$hasSummary', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", + name: "$name", + role: "$role", + isVisible: "$isVisible", + hasSummary: "$hasSummary", }, totalSeconds: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, tangibletime: { - $sum: '$tangibletime', + $sum: "$tangibletime", }, intangibletime: { - $sum: '$intangibletime', + $sum: "$intangibletime", }, }, }, { $project: { _id: 0, - personId: '$_id.personId', - name: '$_id.name', - role: '$_id.role', - isVisible: '$_id.isVisible', - hasSummary: '$_id.hasSummary', - weeklycommittedHours: '$_id.weeklycommittedHours', + personId: "$_id.personId", + name: "$_id.name", + role: "$_id.role", + isVisible: "$_id.isVisible", + hasSummary: "$_id.hasSummary", + weeklycommittedHours: "$_id.weeklycommittedHours", totaltime_hrs: { - $divide: ['$totalSeconds', 3600], + $divide: ["$totalSeconds", 3600], }, totaltangibletime_hrs: { - $divide: ['$tangibletime', 3600], + $divide: ["$tangibletime", 3600], }, totalintangibletime_hrs: { - $divide: ['$intangibletime', 3600], + $divide: ["$intangibletime", 3600], }, percentagespentintangible: { $cond: [ { - $eq: ['$totalSeconds', 0], + $eq: ["$totalSeconds", 0], }, 0, { $multiply: [ { - $divide: ['$tangibletime', '$totalSeconds'], + $divide: ["$tangibletime", "$totalSeconds"], }, 100, ], }, ], }, + timeOffFrom: { + $ifNull: ["$persondata.timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$persondata.timeOffTill", null], + }, + currentDate: { $toDate: new Date() }, }, }, { @@ -420,14 +433,14 @@ const dashboardhelper = function () { const getUserLaborData = async function (userId) { try { const pdtStart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtEnd = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); const user = await userProfile.findById({ _id: userId, @@ -457,7 +470,7 @@ const dashboardhelper = function () { personId: userId, role: user.role, isVisible: user.isVisible, - hasSummary: user.weeklySummaries[0].summary !== '', + hasSummary: user.weeklySummaries[0].summary !== "", weeklycommittedHours: user.weeklycommittedHours, name: `${user.firstName} ${user.lastName}`, totaltime_hrs: (tangibleSeconds + intangibleSeconds) / 3600, @@ -470,8 +483,8 @@ const dashboardhelper = function () { } catch (err) { return [ { - personId: 'error', - name: 'Error Error', + personId: "error", + name: "Error Error", totaltime_hrs: 0, totaltangibletime_hrs: 0, totalintangibletime_hrs: 0, @@ -482,8 +495,8 @@ const dashboardhelper = function () { }; const laborthismonth = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return timeentry.aggregate([ { @@ -499,19 +512,19 @@ const dashboardhelper = function () { { $group: { _id: { - projectId: '$projectId', + projectId: "$projectId", }, labor: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, }, }, { $lookup: { - from: 'projects', - localField: '_id.projectId', - foreignField: '_id', - as: 'project', + from: "projects", + localField: "_id.projectId", + foreignField: "_id", + as: "project", }, }, { @@ -520,13 +533,13 @@ const dashboardhelper = function () { projectName: { $ifNull: [ { - $arrayElemAt: ['$project.projectName', 0], + $arrayElemAt: ["$project.projectName", 0], }, - 'Undefined', + "Undefined", ], }, timeSpent_hrs: { - $divide: ['$labor', 3600], + $divide: ["$labor", 3600], }, }, }, @@ -534,8 +547,8 @@ const dashboardhelper = function () { }; const laborthisweek = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return userProfile.aggregate([ { @@ -551,10 +564,10 @@ const dashboardhelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -562,18 +575,18 @@ const dashboardhelper = function () { weeklycommittedHours: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $eq: ['$$timeentry.isTangible', true], + $eq: ["$$timeentry.isTangible", true], }, { - $gte: ['$$timeentry.dateOfWork', fromdate], + $gte: ["$$timeentry.dateOfWork", fromdate], }, { - $lte: ['$$timeentry.dateOfWork', todate], + $lte: ["$$timeentry.dateOfWork", todate], }, ], }, @@ -583,27 +596,27 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, { $group: { _id: { - _id: '$_id', - weeklycommittedHours: '$weeklycommittedHours', + _id: "$_id", + weeklycommittedHours: "$weeklycommittedHours", }, effort: { - $sum: '$timeEntryData.totalSeconds', + $sum: "$timeEntryData.totalSeconds", }, }, }, { $project: { _id: 0, - weeklycommittedHours: '$_id.weeklycommittedHours', + weeklycommittedHours: "$_id.weeklycommittedHours", timeSpent_hrs: { - $divide: ['$effort', 3600], + $divide: ["$effort", 3600], }, }, }, @@ -611,8 +624,8 @@ const dashboardhelper = function () { }; const laborThisWeekByCategory = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return userProfile.aggregate([ { @@ -628,10 +641,10 @@ const dashboardhelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -639,18 +652,18 @@ const dashboardhelper = function () { weeklycommittedHours: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $eq: ['$$timeentry.isTangible', true], + $eq: ["$$timeentry.isTangible", true], }, { - $gte: ['$$timeentry.dateOfWork', fromdate], + $gte: ["$$timeentry.dateOfWork", fromdate], }, { - $lte: ['$$timeentry.dateOfWork', todate], + $lte: ["$$timeentry.dateOfWork", todate], }, ], }, @@ -660,37 +673,37 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, { $group: { - _id: '$timeEntryData.projectId', + _id: "$timeEntryData.projectId", effort: { - $sum: '$timeEntryData.totalSeconds', + $sum: "$timeEntryData.totalSeconds", }, }, }, { $lookup: { - from: 'projects', - localField: '_id', - foreignField: '_id', - as: 'project', + from: "projects", + localField: "_id", + foreignField: "_id", + as: "project", }, }, { $unwind: { - path: '$project', + path: "$project", preserveNullAndEmptyArrays: true, }, }, { $group: { - _id: '$project.category', + _id: "$project.category", effort: { - $sum: '$effort', + $sum: "$effort", }, }, }, @@ -698,7 +711,7 @@ const dashboardhelper = function () { $project: { _id: 1, timeSpent_hrs: { - $divide: ['$effort', 3600], + $divide: ["$effort", 3600], }, }, }, diff --git a/src/models/userProfile.js b/src/models/userProfile.js index e3f8d4a48..762b61c02 100644 --- a/src/models/userProfile.js +++ b/src/models/userProfile.js @@ -1,9 +1,9 @@ -const mongoose = require('mongoose'); -const moment = require('moment-timezone'); +const mongoose = require("mongoose"); +const moment = require("moment-timezone"); const { Schema } = mongoose; -const validate = require('mongoose-validator'); -const bcrypt = require('bcryptjs'); +const validate = require("mongoose-validator"); +const bcrypt = require("bcryptjs"); const SALT_ROUNDS = 10; const nextDay = new Date(); @@ -15,11 +15,12 @@ const userProfileSchema = new Schema({ required: true, validate: { validator(v) { - const passwordregex = /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; + const passwordregex = + /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; return passwordregex.test(v); }, message: - '{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.', + "{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.", }, }, isActive: { type: Boolean, required: true, default: true }, @@ -47,7 +48,9 @@ const userProfileSchema = new Schema({ type: String, required: true, unique: true, - validate: [validate({ validator: 'isEmail', message: 'Email address is invalid' })], + validate: [ + validate({ validator: "isEmail", message: "Email address is invalid" }), + ], }, weeklycommittedHours: { type: Number, default: 10 }, weeklycommittedHoursHistory: [ @@ -60,13 +63,15 @@ const userProfileSchema = new Schema({ createdDate: { type: Date, required: true, default: nextDay }, lastModifiedDate: { type: Date, required: true, default: Date.now() }, reactivationDate: { type: Date }, - personalLinks: [{ _id: Schema.Types.ObjectId, Name: String, Link: { type: String } }], + personalLinks: [ + { _id: Schema.Types.ObjectId, Name: String, Link: { type: String } }, + ], adminLinks: [{ _id: Schema.Types.ObjectId, Name: String, Link: String }], - teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'team' }], - projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'project' }], + teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: "team" }], + projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: "project" }], badgeCollection: [ { - badge: { type: mongoose.SchemaTypes.ObjectId, ref: 'badge' }, + badge: { type: mongoose.SchemaTypes.ObjectId, ref: "badge" }, count: { type: Number, default: 0 }, earnedDate: { type: Array, default: [] }, lastModified: { type: Date, required: true, default: Date.now() }, @@ -79,20 +84,25 @@ const userProfileSchema = new Schema({ ], profilePic: { type: String }, infringements: [ - { date: { type: String, required: true }, description: { type: String, required: true } }, + { + date: { type: String, required: true }, + description: { type: String, required: true }, + }, ], location: { - userProvided: { type: String, default: '' }, + userProvided: { type: String, default: "" }, coords: { - lat: { type: Number, default: '' }, - lng: { type: Number, default: '' }, + lat: { type: Number, default: "" }, + lng: { type: Number, default: "" }, }, - country: { type: String, default: '' }, - city: { type: String, default: '' } - + country: { type: String, default: "" }, + city: { type: String, default: "" }, }, oldInfringements: [ - { date: { type: String, required: true }, description: { type: String, required: true } }, + { + date: { type: String, required: true }, + description: { type: String, required: true }, + }, ], privacySettings: { blueSquares: { type: Boolean, default: true }, @@ -104,7 +114,7 @@ const userProfileSchema = new Schema({ dueDate: { type: Date, required: true, - default: moment().tz('America/Los_Angeles').endOf('week'), + default: moment().tz("America/Los_Angeles").endOf("week"), }, summary: { type: String }, uploadDate: { type: Date }, @@ -134,17 +144,17 @@ const userProfileSchema = new Schema({ category: { type: String, enum: [ - 'Food', - 'Energy', - 'Housing', - 'Education', - 'Society', - 'Economics', - 'Stewardship', - 'Other', - 'Unspecified', + "Food", + "Energy", + "Housing", + "Education", + "Society", + "Economics", + "Stewardship", + "Other", + "Unspecified", ], - default: 'Other', + default: "Other", }, hrs: { type: Number, default: 0 }, }, @@ -152,48 +162,58 @@ const userProfileSchema = new Schema({ savedTangibleHrs: [Number], timeEntryEditHistory: [ { - date: { type: Date, required: true, default: moment().tz('America/Los_Angeles').toDate() }, + date: { + type: Date, + required: true, + default: moment().tz("America/Los_Angeles").toDate(), + }, initialSeconds: { type: Number, required: true }, newSeconds: { type: Number, required: true }, }, ], weeklySummaryNotReq: { type: Boolean, default: false }, - timeZone: { type: String, required: true, default: 'America/Los_Angeles' }, + timeZone: { type: String, required: true, default: "America/Los_Angeles" }, isVisible: { type: Boolean, default: false }, weeklySummaryOption: { type: String }, - bioPosted: { type: String, default: 'default' }, + bioPosted: { type: String, default: "default" }, isFirstTimelog: { type: Boolean, default: true }, teamCode: { type: String, - default: '', + default: "", validate: { validator(v) { const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$|^$/; return teamCoderegex.test(v); }, - message: - 'Please enter a code in the format of A-AAA or AAAAA', + message: "Please enter a code in the format of A-AAA or AAAAA", }, }, infoCollections: [ { areaName: { type: String }, areaContent: { type: String }, - }], + }, + ], + timeOffFrom: { type: Date, default: undefined }, + timeOffTill: { type: Date, default: undefined }, }); -userProfileSchema.pre('save', function (next) { +userProfileSchema.pre("save", function (next) { const user = this; - if (!user.isModified('password')) return next(); + if (!user.isModified("password")) return next(); return bcrypt .genSalt(SALT_ROUNDS) - .then(result => bcrypt.hash(user.password, result)) + .then((result) => bcrypt.hash(user.password, result)) .then((hash) => { user.password = hash; return next(); }) - .catch(error => next(error)); + .catch((error) => next(error)); }); -module.exports = mongoose.model('userProfile', userProfileSchema, 'userProfiles'); +module.exports = mongoose.model( + "userProfile", + userProfileSchema, + "userProfiles" +); From 2df386581e81c2227d51c0d99a49770c43d34a30 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Sat, 16 Dec 2023 19:25:31 -0500 Subject: [PATCH 02/19] added TimeOffFrom and TimeOffTill to dashboardhelper leaderboard pipeline --- src/helpers/dashboardhelper.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 64c867f71..1eaf9b723 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -259,6 +259,12 @@ const dashboardhelper = function () { }, ], }, + timeOffFrom: { + $ifNull: ["$persondata.timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$persondata.timeOffTill", null], + }, }, }, { @@ -277,6 +283,8 @@ const dashboardhelper = function () { isVisible: 1, hasSummary: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, timeEntryData: { $filter: { input: "$timeEntryData", @@ -309,6 +317,8 @@ const dashboardhelper = function () { isVisible: 1, hasSummary: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, totalSeconds: { $cond: [ { @@ -356,6 +366,8 @@ const dashboardhelper = function () { _id: { personId: "$personId", weeklycommittedHours: "$weeklycommittedHours", + timeOffFrom: "$timeOffFrom", + timeOffTill: "$timeOffTill", name: "$name", role: "$role", isVisible: "$isVisible", @@ -406,12 +418,8 @@ const dashboardhelper = function () { }, ], }, - timeOffFrom: { - $ifNull: ["$persondata.timeOffFrom", null], - }, - timeOffTill: { - $ifNull: ["$persondata.timeOffTill", null], - }, + timeOffFrom: "$_id.timeOffFrom", + timeOffTill: "$_id.timeOffTill", currentDate: { $toDate: new Date() }, }, }, From 2ecf74d07810c42d71038fd1656ba632984b7dda Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Sat, 16 Dec 2023 23:16:19 -0500 Subject: [PATCH 03/19] added pst time instead of est for current date --- src/helpers/dashboardhelper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 1eaf9b723..0e3c71e9b 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -420,7 +420,9 @@ const dashboardhelper = function () { }, timeOffFrom: "$_id.timeOffFrom", timeOffTill: "$_id.timeOffTill", - currentDate: { $toDate: new Date() }, + currentDate: { + $toDate: moment.tz("America/Los_Angeles").startOf("day"), + }, }, }, { From 511062fd75c0cb619eea39b06d9def6e6a7bc6d7 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Sun, 17 Dec 2023 11:55:54 -0500 Subject: [PATCH 04/19] removed current date from leaderboard aggregation pipeline --- src/helpers/dashboardhelper.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 0e3c71e9b..5efeae4f7 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -420,9 +420,6 @@ const dashboardhelper = function () { }, timeOffFrom: "$_id.timeOffFrom", timeOffTill: "$_id.timeOffTill", - currentDate: { - $toDate: moment.tz("America/Los_Angeles").startOf("day"), - }, }, }, { From ecc27d33cc008ba26d694d6613ff33a5fac09f48 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Sun, 17 Dec 2023 14:16:00 -0500 Subject: [PATCH 05/19] added timeOffFrom and timeOffTill to taskHelper --- src/helpers/taskHelper.js | 316 ++++++++++++++++++++------------------ 1 file changed, 166 insertions(+), 150 deletions(-) diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index a94aaee94..937702e05 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -1,17 +1,17 @@ -const moment = require('moment-timezone'); -const userProfile = require('../models/userProfile'); -const myteam = require('../helpers/helperModels/myTeam'); +const moment = require("moment-timezone"); +const userProfile = require("../models/userProfile"); +const myteam = require("../helpers/helperModels/myTeam"); const taskHelper = function () { const getTasksForTeams = function (userId) { const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); return myteam.aggregate([ { $match: { @@ -19,23 +19,23 @@ const taskHelper = function () { }, }, { - $unwind: '$myteam', + $unwind: "$myteam", }, { $project: { _id: 0, - personId: '$myteam._id', - name: '$myteam.fullName', + personId: "$myteam._id", + name: "$myteam.fullName", role: 1, }, }, // have personId, name, role { $lookup: { - from: 'userProfiles', - localField: 'personId', - foreignField: '_id', - as: 'persondata', + from: "userProfiles", + localField: "personId", + foreignField: "_id", + as: "persondata", }, }, { @@ -43,31 +43,37 @@ const taskHelper = function () { // dashboard tasks user roles hierarchy $or: [ { - role: { $in: ['Owner', 'Core Team'] }, + role: { $in: ["Owner", "Core Team"] }, }, { $and: [ { - role: 'Administrator', + role: "Administrator", }, - { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } }, - ] + { "persondata.0.role": { $nin: ["Owner", "Administrator"] } }, + ], }, { $and: [ { - role: { $in: ['Manager', 'Mentor'] }, + role: { $in: ["Manager", "Mentor"] }, }, { - 'persondata.0.role': { - $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'], + "persondata.0.role": { + $nin: [ + "Manager", + "Mentor", + "Core Team", + "Administrator", + "Owner", + ], }, }, ], }, - { 'persondata.0._id': userId }, - { 'persondata.0.role': 'Volunteer' }, - { 'persondata.0.isVisible': true }, + { "persondata.0._id": userId }, + { "persondata.0.role": "Volunteer" }, + { "persondata.0.isVisible": true }, ], }, }, @@ -78,22 +84,28 @@ const taskHelper = function () { weeklycommittedHours: { $sum: [ { - $arrayElemAt: ['$persondata.weeklycommittedHours', 0], + $arrayElemAt: ["$persondata.weeklycommittedHours", 0], }, { - $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0], + $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0], }, ], }, + timeOffFrom: { + $ifNull: ["$persondata.timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$persondata.timeOffTill", null], + }, role: 1, }, }, { $lookup: { - from: 'timeEntries', - localField: 'personId', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "personId", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -101,17 +113,19 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, ], }, @@ -122,7 +136,7 @@ const taskHelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -131,21 +145,23 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, isTangible: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.isTangible', + "$timeEntryData.isTangible", false, ], }, @@ -157,9 +173,9 @@ const taskHelper = function () { tangibletime: { $cond: [ { - $eq: ['$isTangible', true], + $eq: ["$isTangible", true], }, - '$totalSeconds', + "$totalSeconds", 0, ], }, @@ -168,40 +184,44 @@ const taskHelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', - name: '$name', - role: '$role', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", + timeOffFrom: "$timeOffFrom", + timeOffTill: "$timeOffTill", + name: "$name", + role: "$role", }, totalSeconds: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, tangibletime: { - $sum: '$tangibletime', + $sum: "$tangibletime", }, }, }, { $project: { _id: 0, - personId: '$_id.personId', - name: '$_id.name', - weeklycommittedHours: '$_id.weeklycommittedHours', + personId: "$_id.personId", + name: "$_id.name", + weeklycommittedHours: "$_id.weeklycommittedHours", + timeOffFrom: "$_id.timeOffFrom", + timeOffTill: "$_id.timeOffTill", totaltime_hrs: { - $divide: ['$totalSeconds', 3600], + $divide: ["$totalSeconds", 3600], }, totaltangibletime_hrs: { - $divide: ['$tangibletime', 3600], + $divide: ["$tangibletime", 3600], }, - role: '$_id.role', + role: "$_id.role", }, }, { $lookup: { - from: 'tasks', - localField: 'personId', - foreignField: 'resources.userID', - as: 'tasks', + from: "tasks", + localField: "personId", + foreignField: "resources.userID", + as: "tasks", }, }, { @@ -215,25 +235,25 @@ const taskHelper = function () { }, { $unwind: { - path: '$tasks', + path: "$tasks", preserveNullAndEmptyArrays: true, }, }, { $lookup: { - from: 'wbs', - localField: 'tasks.wbsId', - foreignField: '_id', - as: 'projectId', + from: "wbs", + localField: "tasks.wbsId", + foreignField: "_id", + as: "projectId", }, }, { $addFields: { - 'tasks.projectId': { + "tasks.projectId": { $cond: [ - { $ne: ['$projectId', []] }, - { $arrayElemAt: ['$projectId', 0] }, - '$tasks.projectId', + { $ne: ["$projectId", []] }, + { $arrayElemAt: ["$projectId", 0] }, + "$tasks.projectId", ], }, }, @@ -255,55 +275,55 @@ const taskHelper = function () { }, { $addFields: { - 'tasks.projectId': '$tasks.projectId.projectId', + "tasks.projectId": "$tasks.projectId.projectId", }, }, { $lookup: { - from: 'taskNotifications', - localField: 'tasks._id', - foreignField: 'taskId', - as: 'tasks.taskNotifications', + from: "taskNotifications", + localField: "tasks._id", + foreignField: "taskId", + as: "tasks.taskNotifications", }, }, { $group: { - _id: '$personId', + _id: "$personId", tasks: { - $push: '$tasks', + $push: "$tasks", }, data: { - $first: '$$ROOT', + $first: "$$ROOT", }, }, }, { $addFields: { - 'data.tasks': { + "data.tasks": { $filter: { - input: '$tasks', - as: 'task', - cond: { $ne: ['$$task', {}] }, + input: "$tasks", + as: "task", + cond: { $ne: ["$$task", {}] }, }, }, }, }, { $replaceRoot: { - newRoot: '$data', + newRoot: "$data", }, }, ]); }; const getTasksForSingleUser = function (userId) { const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); return userProfile.aggregate([ { $match: { @@ -312,20 +332,16 @@ const taskHelper = function () { }, { $project: { - personId: '$_id', - role: '$role', + personId: "$_id", + role: "$role", name: { - $concat: [ - '$firstName', - ' ', - '$lastName', - ], + $concat: ["$firstName", " ", "$lastName"], }, weeklycommittedHours: { $sum: [ - '$weeklycommittedHours', + "$weeklycommittedHours", { - $ifNull: ['$missedHours', 0], + $ifNull: ["$missedHours", 0], }, ], }, @@ -333,10 +349,10 @@ const taskHelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: 'personId', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "personId", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -347,15 +363,15 @@ const taskHelper = function () { role: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, ], }, @@ -365,7 +381,7 @@ const taskHelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -378,18 +394,18 @@ const taskHelper = function () { totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, isTangible: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.isTangible', + "$timeEntryData.isTangible", false, ], }, @@ -400,9 +416,9 @@ const taskHelper = function () { tangibletime: { $cond: [ { - $eq: ['$isTangible', true], + $eq: ["$isTangible", true], }, - '$totalSeconds', + "$totalSeconds", 0, ], }, @@ -411,40 +427,40 @@ const taskHelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', - name: '$name', - role: '$role', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", + name: "$name", + role: "$role", }, totalSeconds: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, tangibletime: { - $sum: '$tangibletime', + $sum: "$tangibletime", }, }, }, { $project: { _id: 0, - personId: '$_id.personId', - name: '$_id.name', - weeklycommittedHours: '$_id.weeklycommittedHours', - role: '$_id.role', + personId: "$_id.personId", + name: "$_id.name", + weeklycommittedHours: "$_id.weeklycommittedHours", + role: "$_id.role", totaltime_hrs: { - $divide: ['$totalSeconds', 3600], + $divide: ["$totalSeconds", 3600], }, totaltangibletime_hrs: { - $divide: ['$tangibletime', 3600], + $divide: ["$tangibletime", 3600], }, }, }, { $lookup: { - from: 'tasks', - localField: 'personId', - foreignField: 'resources.userID', - as: 'tasks', + from: "tasks", + localField: "personId", + foreignField: "resources.userID", + as: "tasks", }, }, { @@ -458,25 +474,25 @@ const taskHelper = function () { }, { $unwind: { - path: '$tasks', + path: "$tasks", preserveNullAndEmptyArrays: true, }, }, { $lookup: { - from: 'wbs', - localField: 'tasks.wbsId', - foreignField: '_id', - as: 'projectId', + from: "wbs", + localField: "tasks.wbsId", + foreignField: "_id", + as: "projectId", }, }, { $addFields: { - 'tasks.projectId': { + "tasks.projectId": { $cond: [ - { $ne: ['$projectId', []] }, - { $arrayElemAt: ['$projectId', 0] }, - '$tasks.projectId', + { $ne: ["$projectId", []] }, + { $arrayElemAt: ["$projectId", 0] }, + "$tasks.projectId", ], }, }, @@ -498,40 +514,40 @@ const taskHelper = function () { }, { $addFields: { - 'tasks.projectId': '$tasks.projectId.projectId', + "tasks.projectId": "$tasks.projectId.projectId", }, }, { $lookup: { - from: 'taskNotifications', - localField: 'tasks._id', - foreignField: 'taskId', - as: 'tasks.taskNotifications', + from: "taskNotifications", + localField: "tasks._id", + foreignField: "taskId", + as: "tasks.taskNotifications", }, }, { $group: { - _id: '$personId', - tasks: { $push: '$tasks' }, + _id: "$personId", + tasks: { $push: "$tasks" }, data: { - $first: '$$ROOT', + $first: "$$ROOT", }, }, }, { $addFields: { - 'data.tasks': { + "data.tasks": { $filter: { - input: '$tasks', - as: 'task', - cond: { $ne: ['$$task', {}] }, + input: "$tasks", + as: "task", + cond: { $ne: ["$$task", {}] }, }, }, }, }, { $replaceRoot: { - newRoot: '$data', + newRoot: "$data", }, }, ]); @@ -539,7 +555,7 @@ const taskHelper = function () { const getUserProfileFirstAndLastName = function (userId) { return userProfile.findById(userId).then((results) => { if (!results) { - return ' '; + return " "; } return `${results.firstName} ${results.lastName}`; }); From 7de89472272d1c058c4c6f4f730cbe35697be5f4 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Sun, 17 Dec 2023 14:55:58 -0500 Subject: [PATCH 06/19] added timeOffFrom and timeOffTill to reportHelper --- src/helpers/reporthelper.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js index 0c2a8104d..2614a37f6 100644 --- a/src/helpers/reporthelper.js +++ b/src/helpers/reporthelper.js @@ -121,7 +121,13 @@ const reporthelper = function () { }, }, teamCode: { - $ifNull: ['$teamCode', ''], + $ifNull: ["$teamCode", ""], + }, + timeOffFrom: { + $ifNull: ["$timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$timeOffTill", null], }, role: 1, weeklySummaries: { From 33a0546451f5f90acf74fc91fe3e49b28cb41e57 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 18 Dec 2023 14:32:17 -0500 Subject: [PATCH 07/19] updated dashboardhelper and taskHelper to add timeOffFrom anf timeOffTill for individual task and leaderboard data --- src/helpers/dashboardhelper.js | 2 ++ src/helpers/taskHelper.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 5efeae4f7..b8c0f8293 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -485,6 +485,8 @@ const dashboardhelper = function () { totalintangibletime_hrs: intangibleSeconds / 3600, percentagespentintangible: (intangibleSeconds / tangibleSeconds) * 100, + timeOffFrom: user.timeOffFrom, + timeOffTill: user.timeOffTill, }, ]; } catch (err) { diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index 937702e05..f9353f89b 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -345,6 +345,12 @@ const taskHelper = function () { }, ], }, + timeOffFrom: { + $ifNull: ["$timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$timeOffTill", null], + }, }, }, { @@ -360,6 +366,8 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, role: 1, timeEntryData: { $filter: { @@ -390,6 +398,8 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, role: 1, totalSeconds: { $cond: [ @@ -429,6 +439,8 @@ const taskHelper = function () { _id: { personId: "$personId", weeklycommittedHours: "$weeklycommittedHours", + timeOffFrom: "$timeOffFrom", + timeOffTill: "$timeOffTill", name: "$name", role: "$role", }, @@ -446,6 +458,8 @@ const taskHelper = function () { personId: "$_id.personId", name: "$_id.name", weeklycommittedHours: "$_id.weeklycommittedHours", + timeOffFrom: "$_id.timeOffFrom", + timeOffTill: "$_id.timeOffTill", role: "$_id.role", totaltime_hrs: { $divide: ["$totalSeconds", 3600], From 367abce5a2300d6ef666c92d6d43ef0028f4c8c9 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 18 Dec 2023 17:50:04 -0500 Subject: [PATCH 08/19] modified the array representation for timeOffFrom and TimeOffTill to a value instead of array --- src/helpers/dashboardhelper.js | 4 ++-- src/helpers/taskHelper.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index b8c0f8293..48f9047da 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -260,10 +260,10 @@ const dashboardhelper = function () { ], }, timeOffFrom: { - $ifNull: ["$persondata.timeOffFrom", null], + $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null], }, timeOffTill: { - $ifNull: ["$persondata.timeOffTill", null], + $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null], }, }, }, diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index f9353f89b..b5268734e 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -92,10 +92,10 @@ const taskHelper = function () { ], }, timeOffFrom: { - $ifNull: ["$persondata.timeOffFrom", null], + $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null], }, timeOffTill: { - $ifNull: ["$persondata.timeOffTill", null], + $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null], }, role: 1, }, From 676ab6dd93e725a65995edd07be28b2ee8a18d54 Mon Sep 17 00:00:00 2001 From: Shiwani99 <78906820+Shiwani99@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:53:26 -0500 Subject: [PATCH 09/19] Added comments to reasonSchedulingController.js --- src/controllers/reasonSchedulingController.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js index 89b312bc2..3c6334051 100644 --- a/src/controllers/reasonSchedulingController.js +++ b/src/controllers/reasonSchedulingController.js @@ -55,12 +55,13 @@ const postReason = async (req, res) => { }); } - // new changes + // conditions added to check if timeOffFrom and timeOffTill fields existed if ( foundUser.hasOwnProperty("timeOffFrom") && foundUser.hasOwnProperty("timeOffTill") ) { + // if currentDate is greater than or equal to the last timeOffTill date then both the fields will be updated if (currentDate >= foundUser.timeOffTill) { await UserModel.findOneAndUpdate( { @@ -74,6 +75,7 @@ const postReason = async (req, res) => { } ); } else { + // else only timeOffTill will be updated await UserModel.findOneAndUpdate( { _id: userId, @@ -86,6 +88,7 @@ const postReason = async (req, res) => { ); } } else { + // if both the fields are not present then these fields will be added to mongoDB for that user await UserModel.findOneAndUpdate( { _id: userId, From 37ba941687f2a59a3b5741089fd5b7215288590f Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 8 Jan 2024 03:45:22 -0500 Subject: [PATCH 10/19] added timeOffFrom and timeOffTill fields to new aggregation in taskHelper and dashboardHelper --- src/helpers/dashboardhelper.js | 719 +++++++++++++++++++----------- src/helpers/taskHelper.js | 789 ++++++++++++++++++++------------- 2 files changed, 935 insertions(+), 573 deletions(-) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 48f9047da..4a6605213 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -3,6 +3,7 @@ const mongoose = require("mongoose"); const userProfile = require("../models/userProfile"); const timeentry = require("../models/timeentry"); const myTeam = require("../helpers/helperModels/myTeam"); +const team = require("../models/team"); const dashboardhelper = function () { const personaldetails = function (userId) { @@ -69,6 +70,16 @@ const dashboardhelper = function () { { $lte: ["$$timeentry.dateOfWork", pdtend], }, + { + $not: [ + { + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], + }, + ], + }, ], }, }, @@ -152,8 +163,15 @@ const dashboardhelper = function () { return output; }; - const getLeaderboard = function (userId) { + const getLeaderboard = async function (userId) { const userid = mongoose.Types.ObjectId(userId); + const userById = await userProfile + .findOne({ _id: userid, isActive: true }, { role: 1 }) + .then((res) => res) + .catch((e) => {}); + + if (userById == null) return null; + const userRole = userById.role; const pdtstart = moment() .tz("America/Los_Angeles") .startOf("week") @@ -162,274 +180,416 @@ const dashboardhelper = function () { .tz("America/Los_Angeles") .endOf("week") .format("YYYY-MM-DD"); - return myTeam.aggregate([ - { - $match: { - _id: userid, - }, - }, - { - $unwind: "$myteam", - }, - { - $project: { - _id: 0, - role: 1, - personId: "$myteam._id", - name: "$myteam.fullName", - }, - }, - { - $lookup: { - from: "userProfiles", - localField: "personId", - foreignField: "_id", - as: "persondata", - }, - }, - { - $match: { - // leaderboard user roles hierarchy - $or: [ - { - role: { $in: ["Owner", "Core Team"] }, - }, - { - $and: [ - { - role: "Administrator", - }, - { "persondata.0.role": { $nin: ["Owner", "Administrator"] } }, - ], - }, - { - $and: [ - { - role: { $in: ["Manager", "Mentor"] }, - }, - { - "persondata.0.role": { - $nin: [ - "Manager", - "Mentor", - "Core Team", - "Administrator", - "Owner", - ], - }, - }, - ], - }, - { "persondata.0._id": userId }, - { "persondata.0.role": "Volunteer" }, - { "persondata.0.isVisible": true }, - ], - }, - }, - { - $project: { - personId: 1, - name: 1, - role: { - $arrayElemAt: ["$persondata.role", 0], - }, - isVisible: { - $arrayElemAt: ["$persondata.isVisible", 0], - }, - hasSummary: { - $ne: [ - { - $arrayElemAt: [ - { - $arrayElemAt: ["$persondata.weeklySummaries.summary", 0], - }, - 0, - ], - }, - "", - ], - }, - weeklycommittedHours: { - $sum: [ - { - $arrayElemAt: ["$persondata.weeklycommittedHours", 0], - }, - { - $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0], - }, - ], - }, - timeOffFrom: { - $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null], - }, - timeOffTill: { - $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null], - }, - }, - }, - { - $lookup: { - from: "timeEntries", - localField: "personId", - foreignField: "personId", - as: "timeEntryData", - }, - }, - { - $project: { - personId: 1, - name: 1, - role: 1, - isVisible: 1, - hasSummary: 1, - weeklycommittedHours: 1, - timeOffFrom: 1, - timeOffTill: 1, - timeEntryData: { - $filter: { - input: "$timeEntryData", - as: "timeentry", - cond: { - $and: [ - { - $gte: ["$$timeentry.dateOfWork", pdtstart], - }, - { - $lte: ["$$timeentry.dateOfWork", pdtend], - }, - ], - }, - }, - }, - }, - }, - { - $unwind: { - path: "$timeEntryData", - preserveNullAndEmptyArrays: true, - }, - }, - { - $project: { - personId: 1, - name: 1, - role: 1, - isVisible: 1, - hasSummary: 1, - weeklycommittedHours: 1, - timeOffFrom: 1, - timeOffTill: 1, - totalSeconds: { - $cond: [ - { - $gte: ["$timeEntryData.totalSeconds", 0], - }, - "$timeEntryData.totalSeconds", - 0, - ], - }, - isTangible: { - $cond: [ - { - $gte: ["$timeEntryData.totalSeconds", 0], - }, - "$timeEntryData.isTangible", - false, - ], - }, - }, - }, - { - $addFields: { - tangibletime: { - $cond: [ - { - $eq: ["$isTangible", true], - }, - "$totalSeconds", - 0, - ], - }, - intangibletime: { - $cond: [ - { - $eq: ["$isTangible", false], - }, - "$totalSeconds", - 0, - ], - }, - }, - }, - { - $group: { - _id: { - personId: "$personId", - weeklycommittedHours: "$weeklycommittedHours", - timeOffFrom: "$timeOffFrom", - timeOffTill: "$timeOffTill", - name: "$name", - role: "$role", - isVisible: "$isVisible", - hasSummary: "$hasSummary", - }, - totalSeconds: { - $sum: "$totalSeconds", - }, - tangibletime: { - $sum: "$tangibletime", - }, - intangibletime: { - $sum: "$intangibletime", - }, - }, - }, - { - $project: { - _id: 0, - personId: "$_id.personId", - name: "$_id.name", - role: "$_id.role", - isVisible: "$_id.isVisible", - hasSummary: "$_id.hasSummary", - weeklycommittedHours: "$_id.weeklycommittedHours", - totaltime_hrs: { - $divide: ["$totalSeconds", 3600], - }, - totaltangibletime_hrs: { - $divide: ["$tangibletime", 3600], - }, - totalintangibletime_hrs: { - $divide: ["$intangibletime", 3600], - }, - percentagespentintangible: { - $cond: [ - { - $eq: ["$totalSeconds", 0], - }, - 0, - { - $multiply: [ - { - $divide: ["$tangibletime", "$totalSeconds"], - }, - 100, - ], - }, - ], - }, - timeOffFrom: "$_id.timeOffFrom", - timeOffTill: "$_id.timeOffTill", - }, - }, - { - $sort: { - totaltangibletime_hrs: -1, - name: 1, - role: 1, - }, + + let teamMemberIds = [userid]; + let teamMembers = []; + + if ( + userRole != "Administrator" && + userRole != "Owner" && + userRole != "Core Team" + ) { + // Manager , Mentor , Volunteer ... , Show only team members + const teamsResult = await team + .find({ "members.userId": { $in: [userid] } }, { members: 1 }) + .then((res) => res) + .catch((e) => {}); + + teamsResult.map((_myTeam) => { + _myTeam.members.map((teamMember) => { + if (!teamMember.userId.equals(userid)) + teamMemberIds.push(teamMember.userId); + }); + }); + + teamMembers = await userProfile + .find( + { _id: { $in: teamMemberIds }, isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else if (userRole == "Administrator") { + // All users except Owner and Core Team + const excludedRoles = ["Core Team", "Owner"]; + teamMembers = await userProfile + .find( + { isActive: true, role: { $nin: excludedRoles } }, + { + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else { + // 'Core Team', 'Owner' //All users + teamMembers = await userProfile + .find( + { isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } + + teamMemberIds = teamMembers.map((member) => member._id); + + const timeEntries = await timeentry.find({ + dateOfWork: { + $gte: pdtstart, + $lte: pdtend, }, - ]); + personId: { $in: teamMemberIds }, + }); + + const timeEntryByPerson = {}; + timeEntries.map((timeEntry) => { + const personIdStr = timeEntry.personId.toString(); + + if (timeEntryByPerson[personIdStr] == null) { + timeEntryByPerson[personIdStr] = { + tangibleSeconds: 0, + intangibleSeconds: 0, + totalSeconds: 0, + }; + } + + if (timeEntry.isTangible === true) { + timeEntryByPerson[personIdStr].tangibleSeconds += + timeEntry.totalSeconds; + } else { + timeEntryByPerson[personIdStr].intangibleSeconds += + timeEntry.totalSeconds; + } + + timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; + }); + + const leaderBoardData = []; + teamMembers.map((teamMember) => { + const obj = { + personId: teamMember._id, + role: teamMember.role, + name: `${teamMember.firstName} ${teamMember.lastName}`, + isVisible: teamMember.isVisible, + hasSummary: + teamMember.weeklySummaries?.length > 0 + ? teamMember.weeklySummaries[0].summary != "" + : false, + weeklycommittedHours: teamMember.weeklycommittedHours, + totaltangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + 3600 || 0, + totalintangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.intangibleSeconds / + 3600 || 0, + totaltime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 || + 0, + percentagespentintangible: + timeEntryByPerson[teamMember._id.toString()] && + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds != 0 && + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds != 0 + ? (timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds) * + 100 + : 0, + timeOffFrom: teamMember.timeOffFrom || null, + timeOffTill: teamMember.timeOffTill || null, + }; + leaderBoardData.push(obj); + }); + + const sortedLBData = leaderBoardData.sort((a, b) => { + // Sort by totaltangibletime_hrs in descending order + if (b.totaltangibletime_hrs !== a.totaltangibletime_hrs) { + return b.totaltangibletime_hrs - a.totaltangibletime_hrs; + } + + // Then sort by name in ascending order + if (a.name !== b.name) { + return a.name.localeCompare(b.name); + } + + // Finally, sort by role in ascending order + return a.role.localeCompare(b.role); + }); + + return sortedLBData; + + // return myTeam.aggregate([ + // { + // $match: { + // _id: userid, + // }, + // }, + // { + // $unwind: '$myteam', + // }, + // { + // $project: { + // _id: 0, + // role: 1, + // personId: '$myteam._id', + // name: '$myteam.fullName', + // }, + // }, + // { + // $lookup: { + // from: 'userProfiles', + // localField: 'personId', + // foreignField: '_id', + // as: 'persondata', + // }, + // }, + // { + // $match: { + // // leaderboard user roles hierarchy + // $or: [ + // { + // role: { $in: ['Owner', 'Core Team'] }, + // }, + // { + // $and: [ + // { + // role: 'Administrator', + // }, + // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } }, + // ], + // }, + // { + // $and: [ + // { + // role: { $in: ['Manager', 'Mentor'] }, + // }, + // { + // 'persondata.0.role': { + // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'], + // }, + // }, + // ], + // }, + // { 'persondata.0._id': userId }, + // { 'persondata.0.role': 'Volunteer' }, + // { 'persondata.0.isVisible': true }, + // ], + // }, + // }, + // { + // $project: { + // personId: 1, + // name: 1, + // role: { + // $arrayElemAt: ['$persondata.role', 0], + // }, + // isVisible: { + // $arrayElemAt: ['$persondata.isVisible', 0], + // }, + // hasSummary: { + // $ne: [ + // { + // $arrayElemAt: [ + // { + // $arrayElemAt: ['$persondata.weeklySummaries.summary', 0], + // }, + // 0, + // ], + // }, + // '', + // ], + // }, + // weeklycommittedHours: { + // $sum: [ + // { + // $arrayElemAt: ['$persondata.weeklycommittedHours', 0], + // }, + // { + // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0], + // }, + // ], + // }, + // }, + // }, + // { + // $lookup: { + // from: 'timeEntries', + // localField: 'personId', + // foreignField: 'personId', + // as: 'timeEntryData', + // }, + // }, + // { + // $project: { + // personId: 1, + // name: 1, + // role: 1, + // isVisible: 1, + // hasSummary: 1, + // weeklycommittedHours: 1, + // timeEntryData: { + // $filter: { + // input: '$timeEntryData', + // as: 'timeentry', + // cond: { + // $and: [ + // { + // $gte: ['$$timeentry.dateOfWork', pdtstart], + // }, + // { + // $lte: ['$$timeentry.dateOfWork', pdtend], + // }, + // ], + // }, + // }, + // }, + // }, + // }, + // { + // $unwind: { + // path: '$timeEntryData', + // preserveNullAndEmptyArrays: true, + // }, + // }, + // { + // $project: { + // personId: 1, + // name: 1, + // role: 1, + // isVisible: 1, + // hasSummary: 1, + // weeklycommittedHours: 1, + // totalSeconds: { + // $cond: [ + // { + // $gte: ['$timeEntryData.totalSeconds', 0], + // }, + // '$timeEntryData.totalSeconds', + // 0, + // ], + // }, + // isTangible: { + // $cond: [ + // { + // $gte: ['$timeEntryData.totalSeconds', 0], + // }, + // '$timeEntryData.isTangible', + // false, + // ], + // }, + // }, + // }, + // { + // $addFields: { + // tangibletime: { + // $cond: [ + // { + // $eq: ['$isTangible', true], + // }, + // '$totalSeconds', + // 0, + // ], + // }, + // intangibletime: { + // $cond: [ + // { + // $eq: ['$isTangible', false], + // }, + // '$totalSeconds', + // 0, + // ], + // }, + // }, + // }, + // { + // $group: { + // _id: { + // personId: '$personId', + // weeklycommittedHours: '$weeklycommittedHours', + // name: '$name', + // role: '$role', + // isVisible: '$isVisible', + // hasSummary: '$hasSummary', + // }, + // totalSeconds: { + // $sum: '$totalSeconds', + // }, + // tangibletime: { + // $sum: '$tangibletime', + // }, + // intangibletime: { + // $sum: '$intangibletime', + // }, + // }, + // }, + // { + // $project: { + // _id: 0, + // personId: '$_id.personId', + // name: '$_id.name', + // role: '$_id.role', + // isVisible: '$_id.isVisible', + // hasSummary: '$_id.hasSummary', + // weeklycommittedHours: '$_id.weeklycommittedHours', + // totaltime_hrs: { + // $divide: ['$totalSeconds', 3600], + // }, + // totaltangibletime_hrs: { + // $divide: ['$tangibletime', 3600], + // }, + // totalintangibletime_hrs: { + // $divide: ['$intangibletime', 3600], + // }, + // percentagespentintangible: { + // $cond: [ + // { + // $eq: ['$totalSeconds', 0], + // }, + // 0, + // { + // $multiply: [ + // { + // $divide: ['$tangibletime', '$totalSeconds'], + // }, + // 100, + // ], + // }, + // ], + // }, + // }, + // }, + // { + // $sort: { + // totaltangibletime_hrs: -1, + // name: 1, + // role: 1, + // }, + // }, + // ]); }; /** @@ -458,6 +618,7 @@ const dashboardhelper = function () { $gte: pdtStart, $lte: pdtEnd, }, + entryType: { $in: ["default", null] }, personId: userId, }); @@ -485,8 +646,6 @@ const dashboardhelper = function () { totalintangibletime_hrs: intangibleSeconds / 3600, percentagespentintangible: (intangibleSeconds / tangibleSeconds) * 100, - timeOffFrom: user.timeOffFrom, - timeOffTill: user.timeOffTill, }, ]; } catch (err) { @@ -597,6 +756,16 @@ const dashboardhelper = function () { { $lte: ["$$timeentry.dateOfWork", todate], }, + { + $not: [ + { + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], + }, + ], + }, ], }, }, @@ -674,6 +843,16 @@ const dashboardhelper = function () { { $lte: ["$$timeentry.dateOfWork", todate], }, + { + $not: [ + { + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], + }, + ], + }, ], }, }, diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index b5268734e..f96257a67 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -1,9 +1,37 @@ const moment = require("moment-timezone"); +const mongoose = require("mongoose"); const userProfile = require("../models/userProfile"); -const myteam = require("../helpers/helperModels/myTeam"); +const timeentry = require("../models/timeentry"); +const myTeam = require("../helpers/helperModels/myTeam"); +const team = require("../models/team"); +const Task = require("../models/task"); +const TaskNotification = require("../models/taskNotification"); +const Wbs = require("../models/wbs"); const taskHelper = function () { - const getTasksForTeams = function (userId) { + const getTasksForTeams = async function (userId) { + const userid = mongoose.Types.ObjectId(userId); + const userById = await userProfile + .findOne( + { _id: userid, isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + role: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + + if (userById == null) return null; + const userRole = userById.role; + const pdtstart = moment() .tz("America/Los_Angeles") .startOf("week") @@ -12,308 +40,460 @@ const taskHelper = function () { .tz("America/Los_Angeles") .endOf("week") .format("YYYY-MM-DD"); - return myteam.aggregate([ - { - $match: { - _id: userId, - }, - }, - { - $unwind: "$myteam", - }, - { - $project: { - _id: 0, - personId: "$myteam._id", - name: "$myteam.fullName", - role: 1, - }, - }, - // have personId, name, role - { - $lookup: { - from: "userProfiles", - localField: "personId", - foreignField: "_id", - as: "persondata", - }, - }, - { - $match: { - // dashboard tasks user roles hierarchy - $or: [ - { - role: { $in: ["Owner", "Core Team"] }, - }, - { - $and: [ - { - role: "Administrator", - }, - { "persondata.0.role": { $nin: ["Owner", "Administrator"] } }, - ], - }, - { - $and: [ - { - role: { $in: ["Manager", "Mentor"] }, - }, - { - "persondata.0.role": { - $nin: [ - "Manager", - "Mentor", - "Core Team", - "Administrator", - "Owner", - ], - }, - }, - ], - }, - { "persondata.0._id": userId }, - { "persondata.0.role": "Volunteer" }, - { "persondata.0.isVisible": true }, - ], - }, - }, - { - $project: { - personId: 1, - name: 1, - weeklycommittedHours: { - $sum: [ - { - $arrayElemAt: ["$persondata.weeklycommittedHours", 0], - }, - { - $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0], - }, - ], - }, - timeOffFrom: { - $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null], - }, - timeOffTill: { - $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null], - }, - role: 1, - }, - }, - { - $lookup: { - from: "timeEntries", - localField: "personId", - foreignField: "personId", - as: "timeEntryData", - }, - }, - { - $project: { - personId: 1, - name: 1, - weeklycommittedHours: 1, - timeOffFrom: 1, - timeOffTill: 1, - timeEntryData: { - $filter: { - input: "$timeEntryData", - as: "timeentry", - cond: { - $and: [ - { - $gte: ["$$timeentry.dateOfWork", pdtstart], - }, - { - $lte: ["$$timeentry.dateOfWork", pdtend], - }, - ], - }, - }, - }, - role: 1, - }, - }, - { - $unwind: { - path: "$timeEntryData", - preserveNullAndEmptyArrays: true, - }, - }, - { - $project: { - personId: 1, - name: 1, - weeklycommittedHours: 1, - timeOffFrom: 1, - timeOffTill: 1, - totalSeconds: { - $cond: [ - { - $gte: ["$timeEntryData.totalSeconds", 0], - }, - "$timeEntryData.totalSeconds", - 0, - ], - }, - isTangible: { - $cond: [ - { - $gte: ["$timeEntryData.totalSeconds", 0], - }, - "$timeEntryData.isTangible", - false, - ], - }, - role: 1, - }, - }, - { - $addFields: { - tangibletime: { - $cond: [ - { - $eq: ["$isTangible", true], - }, - "$totalSeconds", - 0, - ], - }, - }, - }, - { - $group: { - _id: { - personId: "$personId", - weeklycommittedHours: "$weeklycommittedHours", - timeOffFrom: "$timeOffFrom", - timeOffTill: "$timeOffTill", - name: "$name", - role: "$role", - }, - totalSeconds: { - $sum: "$totalSeconds", - }, - tangibletime: { - $sum: "$tangibletime", - }, - }, - }, - { - $project: { - _id: 0, - personId: "$_id.personId", - name: "$_id.name", - weeklycommittedHours: "$_id.weeklycommittedHours", - timeOffFrom: "$_id.timeOffFrom", - timeOffTill: "$_id.timeOffTill", - totaltime_hrs: { - $divide: ["$totalSeconds", 3600], - }, - totaltangibletime_hrs: { - $divide: ["$tangibletime", 3600], - }, - role: "$_id.role", - }, - }, - { - $lookup: { - from: "tasks", - localField: "personId", - foreignField: "resources.userID", - as: "tasks", - }, - }, - { - $project: { - tasks: { - resources: { - profilePic: 0, - }, - }, - }, - }, - { - $unwind: { - path: "$tasks", - preserveNullAndEmptyArrays: true, - }, - }, - { - $lookup: { - from: "wbs", - localField: "tasks.wbsId", - foreignField: "_id", - as: "projectId", - }, - }, - { - $addFields: { - "tasks.projectId": { - $cond: [ - { $ne: ["$projectId", []] }, - { $arrayElemAt: ["$projectId", 0] }, - "$tasks.projectId", - ], - }, - }, - }, - { - $project: { - projectId: 0, - tasks: { - projectId: { - _id: 0, - isActive: 0, - modifiedDatetime: 0, - wbsName: 0, - createdDatetime: 0, - __v: 0, - }, - }, - }, - }, - { - $addFields: { - "tasks.projectId": "$tasks.projectId.projectId", - }, - }, - { - $lookup: { - from: "taskNotifications", - localField: "tasks._id", - foreignField: "taskId", - as: "tasks.taskNotifications", - }, - }, - { - $group: { - _id: "$personId", - tasks: { - $push: "$tasks", - }, - data: { - $first: "$$ROOT", - }, - }, - }, - { - $addFields: { - "data.tasks": { - $filter: { - input: "$tasks", - as: "task", - cond: { $ne: ["$$task", {}] }, - }, - }, - }, - }, - { - $replaceRoot: { - newRoot: "$data", - }, + + let teamMemberIds = [userid]; + let teamMembers = []; + + if ( + userRole != "Administrator" && + userRole != "Owner" && + userRole != "Core Team" + ) { + // Manager , Mentor , Volunteer ... , Show only team members + const teamsResult = await team + .find({ "members.userId": { $in: [userid] } }, { members: 1 }) + .then((res) => res) + .catch((e) => {}); + + teamsResult.map((_myTeam) => { + _myTeam.members.map((teamMember) => { + if (!teamMember.userId.equals(userid)) + teamMemberIds.push(teamMember.userId); + }); + }); + + teamMembers = await userProfile + .find( + { _id: { $in: teamMemberIds }, isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else if (userRole == "Administrator") { + // All users except Owner and Core Team + const excludedRoles = ["Core Team", "Owner"]; + teamMembers = await userProfile + .find( + { isActive: true, role: { $nin: excludedRoles } }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffFrom: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else { + // 'Core Team', 'Owner' //All users + teamMembers = await userProfile + .find( + { isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } + + teamMemberIds = teamMembers.map((member) => member._id); + + const timeEntries = await timeentry.find({ + dateOfWork: { + $gte: pdtstart, + $lte: pdtend, }, - ]); + personId: { $in: teamMemberIds }, + }); + + const timeEntryByPerson = {}; + timeEntries.map((timeEntry) => { + const personIdStr = timeEntry.personId.toString(); + + if (timeEntryByPerson[personIdStr] == null) { + timeEntryByPerson[personIdStr] = { + tangibleSeconds: 0, + intangibleSeconds: 0, + totalSeconds: 0, + }; + } + + if (timeEntry.isTangible === true) { + timeEntryByPerson[personIdStr].tangibleSeconds += + timeEntry.totalSeconds; + } + timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; + }); + + const teamMemberTasks = await Task.find( + { "resources.userID": { $in: teamMemberIds } }, + { "resources.profilePic": 0 } + ).populate({ + path: "wbsId", + select: "projectId", + }); + const teamMemberTaskIds = teamMemberTasks.map((task) => task._id); + const teamMemberTaskNotifications = await TaskNotification.find({ + taskId: { $in: teamMemberTaskIds }, + }); + + const taskNotificationByTaskNdUser = []; + teamMemberTaskNotifications.map((teamMemberTaskNotification) => { + const taskIdStr = teamMemberTaskNotification.taskId.toString(); + const userIdStr = teamMemberTaskNotification.userId.toString(); + const taskNdUserID = `${taskIdStr},${userIdStr}`; + + if (taskNotificationByTaskNdUser[taskNdUserID]) { + taskNotificationByTaskNdUser[taskNdUserID].push( + teamMemberTaskNotification + ); + } else { + taskNotificationByTaskNdUser[taskNdUserID] = [ + teamMemberTaskNotification, + ]; + } + }); + + const taskByPerson = []; + + teamMemberTasks.map((teamMemberTask) => { + const projId = teamMemberTask.wbsId?.projectId; + const _teamMemberTask = { ...teamMemberTask._doc }; + _teamMemberTask.projectId = projId; + const taskIdStr = _teamMemberTask._id.toString(); + + teamMemberTask.resources.map((resource) => { + const resourceIdStr = resource.userID.toString(); + const taskNdUserID = `${taskIdStr},${resourceIdStr}`; + _teamMemberTask.taskNotifications = + taskNotificationByTaskNdUser[taskNdUserID] || []; + if (taskByPerson[resourceIdStr]) { + taskByPerson[resourceIdStr].push(_teamMemberTask); + } else { + taskByPerson[resourceIdStr] = [_teamMemberTask]; + } + }); + }); + + const teamMemberTasksData = []; + teamMembers.map((teamMember) => { + const obj = { + personId: teamMember._id, + role: teamMember.role, + name: `${teamMember.firstName} ${teamMember.lastName}`, + weeklycommittedHours: teamMember.weeklycommittedHours, + timeOffFrom: teamMember.timeOffFrom || null, + timeOffTill: teamMember.timeOffTill || null, + totaltangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + 3600 || 0, + totaltime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 || + 0, + tasks: taskByPerson[teamMember._id.toString()] || [], + }; + teamMemberTasksData.push(obj); + }); + + return teamMemberTasksData; + + // return myteam.aggregate([ + // { + // $match: { + // _id: userId, + // }, + // }, + // { + // $unwind: '$myteam', + // }, + // { + // $project: { + // _id: 0, + // personId: '$myteam._id', + // name: '$myteam.fullName', + // role: 1, + // }, + // }, + // // have personId, name, role + // { + // $lookup: { + // from: 'userProfiles', + // localField: 'personId', + // foreignField: '_id', + // as: 'persondata', + // }, + // }, + // { + // $match: { + // // dashboard tasks user roles hierarchy + // $or: [ + // { + // role: { $in: ['Owner', 'Core Team'] }, + // }, + // { + // $and: [ + // { + // role: 'Administrator', + // }, + // { 'persondata.0.role': { $nin: ['Owner', 'Administrator'] } }, + // ], + // }, + // { + // $and: [ + // { + // role: { $in: ['Manager', 'Mentor'] }, + // }, + // { + // 'persondata.0.role': { + // $nin: ['Manager', 'Mentor', 'Core Team', 'Administrator', 'Owner'], + // }, + // }, + // ], + // }, + // { 'persondata.0._id': userId }, + // { 'persondata.0.role': 'Volunteer' }, + // { 'persondata.0.isVisible': true }, + // ], + // }, + // }, + // { + // $project: { + // personId: 1, + // name: 1, + // weeklycommittedHours: { + // $sum: [ + // { + // $arrayElemAt: ['$persondata.weeklycommittedHours', 0], + // }, + // { + // $ifNull: [{ $arrayElemAt: ['$persondata.missedHours', 0] }, 0], + // }, + // ], + // }, + // role: 1, + // }, + // }, + // { + // $lookup: { + // from: 'timeEntries', + // localField: 'personId', + // foreignField: 'personId', + // as: 'timeEntryData', + // }, + // }, + // { + // $project: { + // personId: 1, + // name: 1, + // weeklycommittedHours: 1, + // timeEntryData: { + // $filter: { + // input: '$timeEntryData', + // as: 'timeentry', + // cond: { + // $and: [ + // { + // $gte: ['$$timeentry.dateOfWork', pdtstart], + // }, + // { + // $lte: ['$$timeentry.dateOfWork', pdtend], + // }, + // ], + // }, + // }, + // }, + // role: 1, + // }, + // }, + // { + // $unwind: { + // path: '$timeEntryData', + // preserveNullAndEmptyArrays: true, + // }, + // }, + // { + // $project: { + // personId: 1, + // name: 1, + // weeklycommittedHours: 1, + // totalSeconds: { + // $cond: [ + // { + // $gte: ['$timeEntryData.totalSeconds', 0], + // }, + // '$timeEntryData.totalSeconds', + // 0, + // ], + // }, + // isTangible: { + // $cond: [ + // { + // $gte: ['$timeEntryData.totalSeconds', 0], + // }, + // '$timeEntryData.isTangible', + // false, + // ], + // }, + // role: 1, + // }, + // }, + // { + // $addFields: { + // tangibletime: { + // $cond: [ + // { + // $eq: ['$isTangible', true], + // }, + // '$totalSeconds', + // 0, + // ], + // }, + // }, + // }, + // { + // $group: { + // _id: { + // personId: '$personId', + // weeklycommittedHours: '$weeklycommittedHours', + // name: '$name', + // role: '$role', + // }, + // totalSeconds: { + // $sum: '$totalSeconds', + // }, + // tangibletime: { + // $sum: '$tangibletime', + // }, + // }, + // }, + // { + // $project: { + // _id: 0, + // personId: '$_id.personId', + // name: '$_id.name', + // weeklycommittedHours: '$_id.weeklycommittedHours', + // totaltime_hrs: { + // $divide: ['$totalSeconds', 3600], + // }, + // totaltangibletime_hrs: { + // $divide: ['$tangibletime', 3600], + // }, + // role: '$_id.role', + // }, + // }, + // { + // $lookup: { + // from: 'tasks', + // localField: 'personId', + // foreignField: 'resources.userID', + // as: 'tasks', + // }, + // }, + // { + // $project: { + // tasks: { + // resources: { + // profilePic: 0, + // }, + // }, + // }, + // }, + // { + // $unwind: { + // path: '$tasks', + // preserveNullAndEmptyArrays: true, + // }, + // }, + // { + // $lookup: { + // from: 'wbs', + // localField: 'tasks.wbsId', + // foreignField: '_id', + // as: 'projectId', + // }, + // }, + // { + // $addFields: { + // 'tasks.projectId': { + // $cond: [ + // { $ne: ['$projectId', []] }, + // { $arrayElemAt: ['$projectId', 0] }, + // '$tasks.projectId', + // ], + // }, + // }, + // }, + // { + // $project: { + // projectId: 0, + // tasks: { + // projectId: { + // _id: 0, + // isActive: 0, + // modifiedDatetime: 0, + // wbsName: 0, + // createdDatetime: 0, + // __v: 0, + // }, + // }, + // }, + // }, + // { + // $addFields: { + // 'tasks.projectId': '$tasks.projectId.projectId', + // }, + // }, + // { + // $lookup: { + // from: 'taskNotifications', + // localField: 'tasks._id', + // foreignField: 'taskId', + // as: 'tasks.taskNotifications', + // }, + // }, + // { + // $group: { + // _id: '$personId', + // tasks: { + // $push: '$tasks', + // }, + // data: { + // $first: '$$ROOT', + // }, + // }, + // }, + // { + // $addFields: { + // 'data.tasks': { + // $filter: { + // input: '$tasks', + // as: 'task', + // cond: { $ne: ['$$task', {}] }, + // }, + // }, + // }, + // }, + // { + // $replaceRoot: { + // newRoot: '$data', + // }, + // }, + // ]); }; const getTasksForSingleUser = function (userId) { const pdtstart = moment() @@ -381,6 +561,9 @@ const taskHelper = function () { { $lte: ["$$timeentry.dateOfWork", pdtend], }, + { + $in: ["$$timeentry.entryType", ["default", null]], + }, ], }, }, From b81b0a15340148a6378ce6aa920e39bfe01a76b2 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Wed, 6 Dec 2023 17:16:44 -0500 Subject: [PATCH 11/19] added timeOffFrom and timeOffTill fields to mongoDB --- src/controllers/reasonSchedulingController.js | 171 ++++---- src/helpers/dashboardhelper.js | 374 ++++++++++-------- src/models/userProfile.js | 104 +++-- 3 files changed, 387 insertions(+), 262 deletions(-) diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js index 6f872f338..4d56c5a5e 100644 --- a/src/controllers/reasonSchedulingController.js +++ b/src/controllers/reasonSchedulingController.js @@ -1,23 +1,19 @@ - -const moment = require('moment-timezone'); -const UserModel = require('../models/userProfile'); -const ReasonModel = require('../models/reason'); -const emailSender = require('../utilities/emailSender'); - +const moment = require("moment-timezone"); +const UserModel = require("../models/userProfile"); +const ReasonModel = require("../models/reason"); +const emailSender = require("../utilities/emailSender"); const postReason = async (req, res) => { try { const { userId, requestor, reasonData } = req.body; const newDate = moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day'); - const currentDate = moment - .tz('America/Los_Angeles') - .startOf('day'); + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day"); + const currentDate = moment.tz("America/Los_Angeles").startOf("day"); // error case 0 - if (moment.tz(reasonData.date, 'America/Los_Angeles').day() !== 0) { + if (moment.tz(reasonData.date, "America/Los_Angeles").day() !== 0) { return res.status(400).json({ message: "You must choose the Sunday YOU'LL RETURN as your date. This is so your reason ends up as a note on that blue square.", @@ -27,19 +23,19 @@ const postReason = async (req, res) => { if (newDate.isBefore(currentDate)) { return res.status(400).json({ - message: 'You should select a date that is yet to come', + message: "You should select a date that is yet to come", errorCode: 7, }); } if (!reasonData.message) { return res.status(400).json({ - message: 'You must provide a reason.', + message: "You must provide a reason.", errorCode: 6, }); } - // Commented this condition to make reason scheduler available to all the users. + // Commented this condition to make reason scheduler available to all the users. // error case 1 // if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') { // return res.status(403).json({ @@ -54,15 +50,61 @@ const postReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } + // new changes + + if ( + foundUser.hasOwnProperty("timeOffFrom") && + foundUser.hasOwnProperty("timeOffTill") + ) { + if (currentDate >= foundUser.timeOffTill) { + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffFrom: currentDate, + timeOffTill: newDate, + }, + } + ); + } else { + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffTill: newDate, + }, + } + ); + } + } else { + await UserModel.findOneAndUpdate( + { + _id: userId, + }, + { + $set: { + timeOffFrom: currentDate, + timeOffTill: newDate, + }, + } + ); + } + + // + const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); @@ -70,14 +112,14 @@ const postReason = async (req, res) => { // error case 3 if (foundReason) { return res.status(403).json({ - message: 'The reason must be unique to the date', + message: "The reason must be unique to the date", errorCode: 3, }); } const savingDate = moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(); const newReason = new ReasonModel({ @@ -86,14 +128,13 @@ const postReason = async (req, res) => { userId, }); - // await newReason.save(); - const savedData = await newReason.save(); + const savedData = await newReason.save(); if (savedData) { // Upon clicking the "Save" button in the Blue Square Reason Scheduler, an email will be automatically sent to the user and Jae. - const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been set`; + const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been set`; - const emailBody = `

Hi !

+ const emailBody = `

Hi !

This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has set their Blue Square Reason.

@@ -103,21 +144,20 @@ const postReason = async (req, res) => {

Thank you,
One Community

`; + // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - - // 2 user email - - emailSender(`${foundUser.email}`, subject, emailBody, null, null); + // 2 user email - + emailSender(`${foundUser.email}`, subject, emailBody, null, null); - // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) - // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); - } + // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) + // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); + } return res.sendStatus(200); } catch (error) { console.log(error); return res.status(400).json({ - errMessage: 'Something went wrong', + errMessage: "Something went wrong", }); } }; @@ -140,7 +180,7 @@ const getAllReasons = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", }); } @@ -154,7 +194,7 @@ const getAllReasons = async (req, res) => { } catch (error) { console.log(error); return res.status(400).json({ - errMessage: 'Something went wrong while fetching the user', + errMessage: "Something went wrong while fetching the user", }); } }; @@ -178,24 +218,24 @@ const getSingleReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(queryDate, 'America/Los_Angeles') - .startOf('day') + .tz(queryDate, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); if (!foundReason) { return res.status(200).json({ - reason: '', - date: '', - userId: '', + reason: "", + date: "", + userId: "", isSet: false, }); } @@ -204,7 +244,7 @@ const getSingleReason = async (req, res) => { } catch (error) { console.log(error); return res.status(400).json({ - message: 'Something went wrong while fetching single reason', + message: "Something went wrong while fetching single reason", }); } }; @@ -225,7 +265,7 @@ const patchReason = async (req, res) => { if (!reasonData.message) { return res.status(400).json({ - message: 'You must provide a reason.', + message: "You must provide a reason.", errorCode: 6, }); } @@ -235,22 +275,22 @@ const patchReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), userId, }); // error case 4 if (!foundReason) { return res.status(404).json({ - message: 'Reason not found', + message: "Reason not found", errorCode: 4, }); } @@ -260,9 +300,9 @@ const patchReason = async (req, res) => { const savedData = await foundReason.save(); if (savedData) { // Upon clicking the "Save" button in the Blue Square Reason Scheduler, an email will be automatically sent to the user and Jae. - const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been updated`; + const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been updated`; - const emailBody = `

Hi !

+ const emailBody = `

Hi !

This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has updated their Blue Square Reason.

@@ -272,22 +312,21 @@ const patchReason = async (req, res) => {

Thank you,
One Community

`; + // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); - // 1 hardcoded email- emailSender('@gmail.com', subject, emailBody, null, null); + // 2 user email - + emailSender(`${foundUser.email}`, subject, emailBody, null, null); - // 2 user email - - emailSender(`${foundUser.email}`, subject, emailBody, null, null); - - // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) - // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); - } + // 3 - user email and hardcoded email ( After PR approval hardcode Jae's email) + // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); + } return res.status(200).json({ - message: 'Reason Updated!', + message: "Reason Updated!", }); } catch (error) { return res.status(400).json({ - message: 'something went wrong while patching the reason', + message: "something went wrong while patching the reason", }); } }; @@ -298,10 +337,10 @@ const deleteReason = async (req, res) => { const { userId } = req.params; // error case 1 - if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') { + if (requestor.role !== "Owner" && requestor.role !== "Administrator") { return res.status(403).json({ message: - 'You must be an Owner or Administrator to schedule a reason for a Blue Square', + "You must be an Owner or Administrator to schedule a reason for a Blue Square", errorCode: 1, }); } @@ -311,21 +350,21 @@ const deleteReason = async (req, res) => { // error case 2 if (!foundUser) { return res.status(404).json({ - message: 'User not found', + message: "User not found", errorCode: 2, }); } const foundReason = await ReasonModel.findOne({ date: moment - .tz(reasonData.date, 'America/Los_Angeles') - .startOf('day') + .tz(reasonData.date, "America/Los_Angeles") + .startOf("day") .toISOString(), }); if (!foundReason) { return res.status(404).json({ - message: 'Reason not found', + message: "Reason not found", errorCode: 4, }); } @@ -333,13 +372,13 @@ const deleteReason = async (req, res) => { foundReason.remove((err) => { if (err) { return res.status(500).json({ - message: 'Error while deleting document', + message: "Error while deleting document", errorCode: 5, }); } return res.status(200).json({ - message: 'Document deleted', + message: "Document deleted", }); }); } catch (error) {} diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 9bedb0e8f..a200a0095 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -1,28 +1,27 @@ -const moment = require('moment-timezone'); -const mongoose = require('mongoose'); -const userProfile = require('../models/userProfile'); -const timeentry = require('../models/timeentry'); -const myTeam = require('../helpers/helperModels/myTeam'); -const team = require('../models/team'); - +const moment = require("moment-timezone"); +const mongoose = require("mongoose"); +const userProfile = require("../models/userProfile"); +const timeentry = require("../models/timeentry"); +const myTeam = require("../helpers/helperModels/myTeam"); +const team = require("../models/team"); const dashboardhelper = function () { const personaldetails = function (userId) { return userProfile.findById( userId, - '_id firstName lastName role profilePic badgeCollection', + "_id firstName lastName role profilePic badgeCollection" ); }; const getOrgData = async function () { const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); /** * Previous aggregate pipeline had two issues: @@ -41,40 +40,43 @@ const dashboardhelper = function () { $gte: 1, }, role: { - $ne: 'Mentor', + $ne: "Mentor", }, }, }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { $project: { - personId: '$_id', + personId: "$_id", name: 1, weeklycommittedHours: 1, role: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, { $not: [ { - $in: ['$$timeentry.entryType', ['person', 'team', 'project']], + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], }, ], }, @@ -86,7 +88,7 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -97,27 +99,27 @@ const dashboardhelper = function () { totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, tangibletime: { $cond: [ { - $eq: ['$timeEntryData.isTangible', true], + $eq: ["$timeEntryData.isTangible", true], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, intangibletime: { $cond: [ { - $eq: ['$timeEntryData.isTangible', false], + $eq: ["$timeEntryData.isTangible", false], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, @@ -126,17 +128,17 @@ const dashboardhelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", }, time_hrs: { - $sum: { $divide: ['$totalSeconds', 3600] }, + $sum: { $divide: ["$totalSeconds", 3600] }, }, tangibletime_hrs: { - $sum: { $divide: ['$tangibletime', 3600] }, + $sum: { $divide: ["$tangibletime", 3600] }, }, intangibletime_hrs: { - $sum: { $divide: ['$intangibletime', 3600] }, + $sum: { $divide: ["$intangibletime", 3600] }, }, }, }, @@ -144,15 +146,15 @@ const dashboardhelper = function () { $group: { _id: 0, memberCount: { $sum: 1 }, - totalweeklycommittedHours: { $sum: '$_id.weeklycommittedHours' }, + totalweeklycommittedHours: { $sum: "$_id.weeklycommittedHours" }, totaltime_hrs: { - $sum: '$time_hrs', + $sum: "$time_hrs", }, totaltangibletime_hrs: { - $sum: '$tangibletime_hrs', + $sum: "$tangibletime_hrs", }, totalintangibletime_hrs: { - $sum: '$intangibletime_hrs', + $sum: "$intangibletime_hrs", }, }, }, @@ -163,55 +165,93 @@ const dashboardhelper = function () { const getLeaderboard = async function (userId) { const userid = mongoose.Types.ObjectId(userId); - const userById = await userProfile.findOne({ _id: userid, isActive: true }, { role: 1 }) - .then(res => res).catch((e) => {}); + const userById = await userProfile + .findOne({ _id: userid, isActive: true }, { role: 1 }) + .then((res) => res) + .catch((e) => {}); if (userById == null) return null; const userRole = userById.role; const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); let teamMemberIds = [userid]; let teamMembers = []; - if (userRole != 'Administrator' && userRole != 'Owner' && userRole != 'Core Team') // Manager , Mentor , Volunteer ... , Show only team members - { - const teamsResult = await team.find({ 'members.userId': { $in: [userid] } }, { members: 1 }) - .then(res => res).catch((e) => {}); + if ( + userRole != "Administrator" && + userRole != "Owner" && + userRole != "Core Team" + ) { + // Manager , Mentor , Volunteer ... , Show only team members + const teamsResult = await team + .find({ "members.userId": { $in: [userid] } }, { members: 1 }) + .then((res) => res) + .catch((e) => {}); teamsResult.map((_myTeam) => { _myTeam.members.map((teamMember) => { - if (!teamMember.userId.equals(userid)) teamMemberIds.push(teamMember.userId); - }); + if (!teamMember.userId.equals(userid)) + teamMemberIds.push(teamMember.userId); + }); }); - teamMembers = await userProfile.find({ _id: { $in: teamMemberIds }, isActive: true }, + teamMembers = await userProfile + .find( + { _id: { $in: teamMemberIds }, isActive: true }, { - role: 1, firstName: 1, lastName: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); - } else if (userRole == 'Administrator') { // All users except Owner and Core Team - const excludedRoles = ['Core Team', 'Owner']; - teamMembers = await userProfile.find({ isActive: true, role: { $nin: excludedRoles } }, + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else if (userRole == "Administrator") { + // All users except Owner and Core Team + const excludedRoles = ["Core Team", "Owner"]; + teamMembers = await userProfile + .find( + { isActive: true, role: { $nin: excludedRoles } }, { - role: 1, firstName: 1, lastName: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); - } else { // 'Core Team', 'Owner' //All users - teamMembers = await userProfile.find({ isActive: true }, + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else { + // 'Core Team', 'Owner' //All users + teamMembers = await userProfile + .find( + { isActive: true }, { - role: 1, firstName: 1, lastName: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); - } + role: 1, + firstName: 1, + lastName: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } - teamMemberIds = teamMembers.map(member => member._id); + teamMemberIds = teamMembers.map((member) => member._id); const timeEntries = await timeentry.find({ dateOfWork: { @@ -225,36 +265,56 @@ const dashboardhelper = function () { timeEntries.map((timeEntry) => { const personIdStr = timeEntry.personId.toString(); - if (timeEntryByPerson[personIdStr] == null) { timeEntryByPerson[personIdStr] = { tangibleSeconds: 0, intangibleSeconds: 0, totalSeconds: 0 }; } + if (timeEntryByPerson[personIdStr] == null) { + timeEntryByPerson[personIdStr] = { + tangibleSeconds: 0, + intangibleSeconds: 0, + totalSeconds: 0, + }; + } if (timeEntry.isTangible === true) { - timeEntryByPerson[personIdStr].tangibleSeconds += timeEntry.totalSeconds; + timeEntryByPerson[personIdStr].tangibleSeconds += + timeEntry.totalSeconds; } else { - timeEntryByPerson[personIdStr].intangibleSeconds += timeEntry.totalSeconds; + timeEntryByPerson[personIdStr].intangibleSeconds += + timeEntry.totalSeconds; } timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; }); - const leaderBoardData = []; teamMembers.map((teamMember) => { - const obj = { - personId: teamMember._id, - role: teamMember.role, - name: `${teamMember.firstName } ${ teamMember.lastName}`, - isVisible: teamMember.isVisible, - hasSummary: teamMember.weeklySummaries?.length > 0 ? teamMember.weeklySummaries[0].summary != '' : false, - weeklycommittedHours: teamMember.weeklycommittedHours, - totaltangibletime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / 3600) || 0), - totalintangibletime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.intangibleSeconds / 3600) || 0), - totaltime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600) || 0), - percentagespentintangible: - (timeEntryByPerson[teamMember._id.toString()] && timeEntryByPerson[teamMember._id.toString()]?.totalSeconds != 0 && timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds != 0) - ? (timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / timeEntryByPerson[teamMember._id.toString()]?.totalSeconds) * 100 - : 0, - }; - leaderBoardData.push(obj); + const obj = { + personId: teamMember._id, + role: teamMember.role, + name: `${teamMember.firstName} ${teamMember.lastName}`, + isVisible: teamMember.isVisible, + hasSummary: + teamMember.weeklySummaries?.length > 0 + ? teamMember.weeklySummaries[0].summary != "" + : false, + weeklycommittedHours: teamMember.weeklycommittedHours, + totaltangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + 3600 || 0, + totalintangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.intangibleSeconds / + 3600 || 0, + totaltime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 || + 0, + percentagespentintangible: + timeEntryByPerson[teamMember._id.toString()] && + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds != 0 && + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds != 0 + ? (timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds) * + 100 + : 0, + }; + leaderBoardData.push(obj); }); const sortedLBData = leaderBoardData.sort((a, b) => { @@ -532,14 +592,14 @@ const dashboardhelper = function () { const getUserLaborData = async function (userId) { try { const pdtStart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtEnd = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); const user = await userProfile.findById({ _id: userId, @@ -550,7 +610,7 @@ const dashboardhelper = function () { $gte: pdtStart, $lte: pdtEnd, }, - entryType: { $in: ['default', null] }, + entryType: { $in: ["default", null] }, personId: userId, }); @@ -570,7 +630,7 @@ const dashboardhelper = function () { personId: userId, role: user.role, isVisible: user.isVisible, - hasSummary: user.weeklySummaries[0].summary !== '', + hasSummary: user.weeklySummaries[0].summary !== "", weeklycommittedHours: user.weeklycommittedHours, name: `${user.firstName} ${user.lastName}`, totaltime_hrs: (tangibleSeconds + intangibleSeconds) / 3600, @@ -583,8 +643,8 @@ const dashboardhelper = function () { } catch (err) { return [ { - personId: 'error', - name: 'Error Error', + personId: "error", + name: "Error Error", totaltime_hrs: 0, totaltangibletime_hrs: 0, totalintangibletime_hrs: 0, @@ -595,8 +655,8 @@ const dashboardhelper = function () { }; const laborthismonth = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return timeentry.aggregate([ { @@ -612,19 +672,19 @@ const dashboardhelper = function () { { $group: { _id: { - projectId: '$projectId', + projectId: "$projectId", }, labor: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, }, }, { $lookup: { - from: 'projects', - localField: '_id.projectId', - foreignField: '_id', - as: 'project', + from: "projects", + localField: "_id.projectId", + foreignField: "_id", + as: "project", }, }, { @@ -633,13 +693,13 @@ const dashboardhelper = function () { projectName: { $ifNull: [ { - $arrayElemAt: ['$project.projectName', 0], + $arrayElemAt: ["$project.projectName", 0], }, - 'Undefined', + "Undefined", ], }, timeSpent_hrs: { - $divide: ['$labor', 3600], + $divide: ["$labor", 3600], }, }, }, @@ -647,8 +707,8 @@ const dashboardhelper = function () { }; const laborthisweek = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return userProfile.aggregate([ { @@ -664,10 +724,10 @@ const dashboardhelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -675,23 +735,26 @@ const dashboardhelper = function () { weeklycommittedHours: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $eq: ['$$timeentry.isTangible', true], + $eq: ["$$timeentry.isTangible", true], }, { - $gte: ['$$timeentry.dateOfWork', fromdate], + $gte: ["$$timeentry.dateOfWork", fromdate], }, { - $lte: ['$$timeentry.dateOfWork', todate], + $lte: ["$$timeentry.dateOfWork", todate], }, { $not: [ { - $in: ['$$timeentry.entryType', ['person', 'team', 'project']], + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], }, ], }, @@ -703,27 +766,27 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, { $group: { _id: { - _id: '$_id', - weeklycommittedHours: '$weeklycommittedHours', + _id: "$_id", + weeklycommittedHours: "$weeklycommittedHours", }, effort: { - $sum: '$timeEntryData.totalSeconds', + $sum: "$timeEntryData.totalSeconds", }, }, }, { $project: { _id: 0, - weeklycommittedHours: '$_id.weeklycommittedHours', + weeklycommittedHours: "$_id.weeklycommittedHours", timeSpent_hrs: { - $divide: ['$effort', 3600], + $divide: ["$effort", 3600], }, }, }, @@ -731,8 +794,8 @@ const dashboardhelper = function () { }; const laborThisWeekByCategory = function (userId, startDate, endDate) { - const fromdate = moment(startDate).format('YYYY-MM-DD'); - const todate = moment(endDate).format('YYYY-MM-DD'); + const fromdate = moment(startDate).format("YYYY-MM-DD"); + const todate = moment(endDate).format("YYYY-MM-DD"); return userProfile.aggregate([ { @@ -748,10 +811,10 @@ const dashboardhelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: '_id', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "_id", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -759,23 +822,26 @@ const dashboardhelper = function () { weeklycommittedHours: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $eq: ['$$timeentry.isTangible', true], + $eq: ["$$timeentry.isTangible", true], }, { - $gte: ['$$timeentry.dateOfWork', fromdate], + $gte: ["$$timeentry.dateOfWork", fromdate], }, { - $lte: ['$$timeentry.dateOfWork', todate], + $lte: ["$$timeentry.dateOfWork", todate], }, { $not: [ { - $in: ['$$timeentry.entryType', ['person', 'team', 'project']], + $in: [ + "$$timeentry.entryType", + ["person", "team", "project"], + ], }, ], }, @@ -787,37 +853,37 @@ const dashboardhelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, { $group: { - _id: '$timeEntryData.projectId', + _id: "$timeEntryData.projectId", effort: { - $sum: '$timeEntryData.totalSeconds', + $sum: "$timeEntryData.totalSeconds", }, }, }, { $lookup: { - from: 'projects', - localField: '_id', - foreignField: '_id', - as: 'project', + from: "projects", + localField: "_id", + foreignField: "_id", + as: "project", }, }, { $unwind: { - path: '$project', + path: "$project", preserveNullAndEmptyArrays: true, }, }, { $group: { - _id: '$project.category', + _id: "$project.category", effort: { - $sum: '$effort', + $sum: "$effort", }, }, }, @@ -825,7 +891,7 @@ const dashboardhelper = function () { $project: { _id: 1, timeSpent_hrs: { - $divide: ['$effort', 3600], + $divide: ["$effort", 3600], }, }, }, diff --git a/src/models/userProfile.js b/src/models/userProfile.js index 8a8de2e18..762b61c02 100644 --- a/src/models/userProfile.js +++ b/src/models/userProfile.js @@ -1,9 +1,9 @@ -const mongoose = require('mongoose'); -const moment = require('moment-timezone'); +const mongoose = require("mongoose"); +const moment = require("moment-timezone"); const { Schema } = mongoose; -const validate = require('mongoose-validator'); -const bcrypt = require('bcryptjs'); +const validate = require("mongoose-validator"); +const bcrypt = require("bcryptjs"); const SALT_ROUNDS = 10; const nextDay = new Date(); @@ -15,11 +15,12 @@ const userProfileSchema = new Schema({ required: true, validate: { validator(v) { - const passwordregex = /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; + const passwordregex = + /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/; return passwordregex.test(v); }, message: - '{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.', + "{VALUE} is not a valid password!password should be at least 8 charcaters long with uppercase, lowercase and number/special char.", }, }, isActive: { type: Boolean, required: true, default: true }, @@ -47,7 +48,9 @@ const userProfileSchema = new Schema({ type: String, required: true, unique: true, - validate: [validate({ validator: 'isEmail', message: 'Email address is invalid' })], + validate: [ + validate({ validator: "isEmail", message: "Email address is invalid" }), + ], }, weeklycommittedHours: { type: Number, default: 10 }, weeklycommittedHoursHistory: [ @@ -60,13 +63,15 @@ const userProfileSchema = new Schema({ createdDate: { type: Date, required: true, default: nextDay }, lastModifiedDate: { type: Date, required: true, default: Date.now() }, reactivationDate: { type: Date }, - personalLinks: [{ _id: Schema.Types.ObjectId, Name: String, Link: { type: String } }], + personalLinks: [ + { _id: Schema.Types.ObjectId, Name: String, Link: { type: String } }, + ], adminLinks: [{ _id: Schema.Types.ObjectId, Name: String, Link: String }], - teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'team' }], - projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'project' }], + teams: [{ type: mongoose.SchemaTypes.ObjectId, ref: "team" }], + projects: [{ type: mongoose.SchemaTypes.ObjectId, ref: "project" }], badgeCollection: [ { - badge: { type: mongoose.SchemaTypes.ObjectId, ref: 'badge' }, + badge: { type: mongoose.SchemaTypes.ObjectId, ref: "badge" }, count: { type: Number, default: 0 }, earnedDate: { type: Array, default: [] }, lastModified: { type: Date, required: true, default: Date.now() }, @@ -79,20 +84,25 @@ const userProfileSchema = new Schema({ ], profilePic: { type: String }, infringements: [ - { date: { type: String, required: true }, description: { type: String, required: true } }, + { + date: { type: String, required: true }, + description: { type: String, required: true }, + }, ], location: { - userProvided: { type: String, default: '' }, + userProvided: { type: String, default: "" }, coords: { - lat: { type: Number, default: '' }, - lng: { type: Number, default: '' }, + lat: { type: Number, default: "" }, + lng: { type: Number, default: "" }, }, - country: { type: String, default: '' }, - city: { type: String, default: '' }, - + country: { type: String, default: "" }, + city: { type: String, default: "" }, }, oldInfringements: [ - { date: { type: String, required: true }, description: { type: String, required: true } }, + { + date: { type: String, required: true }, + description: { type: String, required: true }, + }, ], privacySettings: { blueSquares: { type: Boolean, default: true }, @@ -104,7 +114,7 @@ const userProfileSchema = new Schema({ dueDate: { type: Date, required: true, - default: moment().tz('America/Los_Angeles').endOf('week'), + default: moment().tz("America/Los_Angeles").endOf("week"), }, summary: { type: String }, uploadDate: { type: Date }, @@ -134,17 +144,17 @@ const userProfileSchema = new Schema({ category: { type: String, enum: [ - 'Food', - 'Energy', - 'Housing', - 'Education', - 'Society', - 'Economics', - 'Stewardship', - 'Other', - 'Unspecified', + "Food", + "Energy", + "Housing", + "Education", + "Society", + "Economics", + "Stewardship", + "Other", + "Unspecified", ], - default: 'Other', + default: "Other", }, hrs: { type: Number, default: 0 }, }, @@ -152,48 +162,58 @@ const userProfileSchema = new Schema({ savedTangibleHrs: [Number], timeEntryEditHistory: [ { - date: { type: Date, required: true, default: moment().tz('America/Los_Angeles').toDate() }, + date: { + type: Date, + required: true, + default: moment().tz("America/Los_Angeles").toDate(), + }, initialSeconds: { type: Number, required: true }, newSeconds: { type: Number, required: true }, }, ], weeklySummaryNotReq: { type: Boolean, default: false }, - timeZone: { type: String, required: true, default: 'America/Los_Angeles' }, + timeZone: { type: String, required: true, default: "America/Los_Angeles" }, isVisible: { type: Boolean, default: false }, weeklySummaryOption: { type: String }, - bioPosted: { type: String, default: 'default' }, + bioPosted: { type: String, default: "default" }, isFirstTimelog: { type: Boolean, default: true }, teamCode: { type: String, - default: '', + default: "", validate: { validator(v) { const teamCoderegex = /^([a-zA-Z]-[a-zA-Z]{3}|[a-zA-Z]{5})$|^$/; return teamCoderegex.test(v); }, - message: - 'Please enter a code in the format of A-AAA or AAAAA', + message: "Please enter a code in the format of A-AAA or AAAAA", }, }, infoCollections: [ { areaName: { type: String }, areaContent: { type: String }, - }], + }, + ], + timeOffFrom: { type: Date, default: undefined }, + timeOffTill: { type: Date, default: undefined }, }); -userProfileSchema.pre('save', function (next) { +userProfileSchema.pre("save", function (next) { const user = this; - if (!user.isModified('password')) return next(); + if (!user.isModified("password")) return next(); return bcrypt .genSalt(SALT_ROUNDS) - .then(result => bcrypt.hash(user.password, result)) + .then((result) => bcrypt.hash(user.password, result)) .then((hash) => { user.password = hash; return next(); }) - .catch(error => next(error)); + .catch((error) => next(error)); }); -module.exports = mongoose.model('userProfile', userProfileSchema, 'userProfiles'); +module.exports = mongoose.model( + "userProfile", + userProfileSchema, + "userProfiles" +); From 02ba9860461b0e01b15bc68c0b89fa14bb2817df Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Sun, 17 Dec 2023 14:16:00 -0500 Subject: [PATCH 12/19] added timeOffFrom and timeOffTill to taskHelper --- src/helpers/taskHelper.js | 420 +++++++++++++++++++++----------------- 1 file changed, 237 insertions(+), 183 deletions(-) diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index 800d1ee6b..fc6a331b3 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -1,149 +1,207 @@ -const moment = require('moment-timezone'); -const mongoose = require('mongoose'); -const userProfile = require('../models/userProfile'); -const timeentry = require('../models/timeentry'); -const myTeam = require('../helpers/helperModels/myTeam'); -const team = require('../models/team'); -const Task = require('../models/task'); -const TaskNotification = require('../models/taskNotification'); -const Wbs = require('../models/wbs'); +const moment = require("moment-timezone"); +const mongoose = require("mongoose"); +const userProfile = require("../models/userProfile"); +const timeentry = require("../models/timeentry"); +const myTeam = require("../helpers/helperModels/myTeam"); +const team = require("../models/team"); +const Task = require("../models/task"); +const TaskNotification = require("../models/taskNotification"); +const Wbs = require("../models/wbs"); const taskHelper = function () { const getTasksForTeams = async function (userId) { const userid = mongoose.Types.ObjectId(userId); - const userById = await userProfile.findOne({ _id: userid, isActive: true }, { - role: 1, firstName: 1, lastName: 1, role: 1, isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, -}) - .then(res => res).catch((e) => {}); + const userById = await userProfile + .findOne( + { _id: userid, isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + role: 1, + isVisible: 1, + weeklycommittedHours: 1, + weeklySummaries: 1, + } + ) + .then((res) => res) + .catch((e) => {}); if (userById == null) return null; const userRole = userById.role; const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); - let teamMemberIds = [userid]; - let teamMembers = []; + let teamMemberIds = [userid]; + let teamMembers = []; - if (userRole != 'Administrator' && userRole != 'Owner' && userRole != 'Core Team') // Manager , Mentor , Volunteer ... , Show only team members - { - const teamsResult = await team.find({ 'members.userId': { $in: [userid] } }, { members: 1 }) - .then(res => res).catch((e) => {}); + if ( + userRole != "Administrator" && + userRole != "Owner" && + userRole != "Core Team" + ) { + // Manager , Mentor , Volunteer ... , Show only team members + const teamsResult = await team + .find({ "members.userId": { $in: [userid] } }, { members: 1 }) + .then((res) => res) + .catch((e) => {}); - teamsResult.map((_myTeam) => { - _myTeam.members.map((teamMember) => { - if (!teamMember.userId.equals(userid)) teamMemberIds.push(teamMember.userId); - }); - }); + teamsResult.map((_myTeam) => { + _myTeam.members.map((teamMember) => { + if (!teamMember.userId.equals(userid)) + teamMemberIds.push(teamMember.userId); + }); + }); - teamMembers = await userProfile.find({ _id: { $in: teamMemberIds }, isActive: true }, - { - role: 1, firstName: 1, lastName: 1, weeklycommittedHours: 1, -}) - .then(res => res).catch((e) => {}); - } else if (userRole == 'Administrator') { // All users except Owner and Core Team - const excludedRoles = ['Core Team', 'Owner']; - teamMembers = await userProfile.find({ isActive: true, role: { $nin: excludedRoles } }, - { - role: 1, firstName: 1, lastName: 1, weeklycommittedHours: 1, -}) - .then(res => res).catch((e) => {}); - } else { // 'Core Team', 'Owner' //All users - teamMembers = await userProfile.find({ isActive: true }, - { - role: 1, firstName: 1, lastName: 1, weeklycommittedHours: 1, -}) - .then(res => res).catch((e) => {}); - } + teamMembers = await userProfile + .find( + { _id: { $in: teamMemberIds }, isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else if (userRole == "Administrator") { + // All users except Owner and Core Team + const excludedRoles = ["Core Team", "Owner"]; + teamMembers = await userProfile + .find( + { isActive: true, role: { $nin: excludedRoles } }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } else { + // 'Core Team', 'Owner' //All users + teamMembers = await userProfile + .find( + { isActive: true }, + { + role: 1, + firstName: 1, + lastName: 1, + weeklycommittedHours: 1, + } + ) + .then((res) => res) + .catch((e) => {}); + } - teamMemberIds = teamMembers.map(member => member._id); + teamMemberIds = teamMembers.map((member) => member._id); - const timeEntries = await timeentry.find({ - dateOfWork: { - $gte: pdtstart, - $lte: pdtend, - }, - personId: { $in: teamMemberIds }, - }); + const timeEntries = await timeentry.find({ + dateOfWork: { + $gte: pdtstart, + $lte: pdtend, + }, + personId: { $in: teamMemberIds }, + }); - const timeEntryByPerson = {}; - timeEntries.map((timeEntry) => { - const personIdStr = timeEntry.personId.toString(); + const timeEntryByPerson = {}; + timeEntries.map((timeEntry) => { + const personIdStr = timeEntry.personId.toString(); - if (timeEntryByPerson[personIdStr] == null) { timeEntryByPerson[personIdStr] = { tangibleSeconds: 0, intangibleSeconds: 0, totalSeconds: 0 }; } + if (timeEntryByPerson[personIdStr] == null) { + timeEntryByPerson[personIdStr] = { + tangibleSeconds: 0, + intangibleSeconds: 0, + totalSeconds: 0, + }; + } - if (timeEntry.isTangible === true) { - timeEntryByPerson[personIdStr].tangibleSeconds += timeEntry.totalSeconds; - } - timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; - }); + if (timeEntry.isTangible === true) { + timeEntryByPerson[personIdStr].tangibleSeconds += + timeEntry.totalSeconds; + } + timeEntryByPerson[personIdStr].totalSeconds += timeEntry.totalSeconds; + }); - const teamMemberTasks = await Task.find({ 'resources.userID': { $in: teamMemberIds } }, { 'resources.profilePic': 0 }) - .populate({ - path: 'wbsId', - select: 'projectId', - }); - const teamMemberTaskIds = teamMemberTasks.map(task => task._id); - const teamMemberTaskNotifications = await TaskNotification.find({ taskId: { $in: teamMemberTaskIds } }); + const teamMemberTasks = await Task.find( + { "resources.userID": { $in: teamMemberIds } }, + { "resources.profilePic": 0 } + ).populate({ + path: "wbsId", + select: "projectId", + }); + const teamMemberTaskIds = teamMemberTasks.map((task) => task._id); + const teamMemberTaskNotifications = await TaskNotification.find({ + taskId: { $in: teamMemberTaskIds }, + }); - const taskNotificationByTaskNdUser = []; - teamMemberTaskNotifications.map((teamMemberTaskNotification) => { - const taskIdStr = teamMemberTaskNotification.taskId.toString(); - const userIdStr = teamMemberTaskNotification.userId.toString(); - const taskNdUserID = `${taskIdStr},${userIdStr}`; + const taskNotificationByTaskNdUser = []; + teamMemberTaskNotifications.map((teamMemberTaskNotification) => { + const taskIdStr = teamMemberTaskNotification.taskId.toString(); + const userIdStr = teamMemberTaskNotification.userId.toString(); + const taskNdUserID = `${taskIdStr},${userIdStr}`; - if (taskNotificationByTaskNdUser[taskNdUserID]) { - taskNotificationByTaskNdUser[taskNdUserID].push(teamMemberTaskNotification); - } else { - taskNotificationByTaskNdUser[taskNdUserID] = [teamMemberTaskNotification]; - } - }); + if (taskNotificationByTaskNdUser[taskNdUserID]) { + taskNotificationByTaskNdUser[taskNdUserID].push( + teamMemberTaskNotification + ); + } else { + taskNotificationByTaskNdUser[taskNdUserID] = [ + teamMemberTaskNotification, + ]; + } + }); - const taskByPerson = []; + const taskByPerson = []; - teamMemberTasks.map((teamMemberTask) => { - const projId = teamMemberTask.wbsId?.projectId; - const _teamMemberTask = { ...teamMemberTask._doc }; - _teamMemberTask.projectId = projId; - const taskIdStr = _teamMemberTask._id.toString(); + teamMemberTasks.map((teamMemberTask) => { + const projId = teamMemberTask.wbsId?.projectId; + const _teamMemberTask = { ...teamMemberTask._doc }; + _teamMemberTask.projectId = projId; + const taskIdStr = _teamMemberTask._id.toString(); - teamMemberTask.resources.map((resource) => { - const resourceIdStr = resource.userID.toString(); - const taskNdUserID = `${taskIdStr},${resourceIdStr}`; - _teamMemberTask.taskNotifications = taskNotificationByTaskNdUser[taskNdUserID] || []; - if (taskByPerson[resourceIdStr]) { - taskByPerson[resourceIdStr].push(_teamMemberTask); - } else { - taskByPerson[resourceIdStr] = [_teamMemberTask]; - } - }); + teamMemberTask.resources.map((resource) => { + const resourceIdStr = resource.userID.toString(); + const taskNdUserID = `${taskIdStr},${resourceIdStr}`; + _teamMemberTask.taskNotifications = + taskNotificationByTaskNdUser[taskNdUserID] || []; + if (taskByPerson[resourceIdStr]) { + taskByPerson[resourceIdStr].push(_teamMemberTask); + } else { + taskByPerson[resourceIdStr] = [_teamMemberTask]; + } }); - + }); const teamMemberTasksData = []; teamMembers.map((teamMember) => { - const obj = { - personId: teamMember._id, - role: teamMember.role, - name: `${teamMember.firstName } ${ teamMember.lastName}`, - weeklycommittedHours: teamMember.weeklycommittedHours, - totaltangibletime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / 3600) || 0), - totaltime_hrs: ((timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600) || 0), - tasks: taskByPerson[teamMember._id.toString()] || [], - }; - teamMemberTasksData.push(obj); + const obj = { + personId: teamMember._id, + role: teamMember.role, + name: `${teamMember.firstName} ${teamMember.lastName}`, + weeklycommittedHours: teamMember.weeklycommittedHours, + totaltangibletime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.tangibleSeconds / + 3600 || 0, + totaltime_hrs: + timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 || + 0, + tasks: taskByPerson[teamMember._id.toString()] || [], + }; + teamMemberTasksData.push(obj); }); - return teamMemberTasksData; - // return myteam.aggregate([ // { // $match: { @@ -429,13 +487,13 @@ const taskHelper = function () { }; const getTasksForSingleUser = function (userId) { const pdtstart = moment() - .tz('America/Los_Angeles') - .startOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .startOf("week") + .format("YYYY-MM-DD"); const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); + .tz("America/Los_Angeles") + .endOf("week") + .format("YYYY-MM-DD"); return userProfile.aggregate([ { $match: { @@ -444,20 +502,16 @@ const taskHelper = function () { }, { $project: { - personId: '$_id', - role: '$role', + personId: "$_id", + role: "$role", name: { - $concat: [ - '$firstName', - ' ', - '$lastName', - ], + $concat: ["$firstName", " ", "$lastName"], }, weeklycommittedHours: { $sum: [ - '$weeklycommittedHours', + "$weeklycommittedHours", { - $ifNull: ['$missedHours', 0], + $ifNull: ["$missedHours", 0], }, ], }, @@ -465,10 +519,10 @@ const taskHelper = function () { }, { $lookup: { - from: 'timeEntries', - localField: 'personId', - foreignField: 'personId', - as: 'timeEntryData', + from: "timeEntries", + localField: "personId", + foreignField: "personId", + as: "timeEntryData", }, }, { @@ -479,18 +533,18 @@ const taskHelper = function () { role: 1, timeEntryData: { $filter: { - input: '$timeEntryData', - as: 'timeentry', + input: "$timeEntryData", + as: "timeentry", cond: { $and: [ { - $gte: ['$$timeentry.dateOfWork', pdtstart], + $gte: ["$$timeentry.dateOfWork", pdtstart], }, { - $lte: ['$$timeentry.dateOfWork', pdtend], + $lte: ["$$timeentry.dateOfWork", pdtend], }, { - $in: ['$$timeentry.entryType', ['default', null]], + $in: ["$$timeentry.entryType", ["default", null]], }, ], }, @@ -500,7 +554,7 @@ const taskHelper = function () { }, { $unwind: { - path: '$timeEntryData', + path: "$timeEntryData", preserveNullAndEmptyArrays: true, }, }, @@ -513,18 +567,18 @@ const taskHelper = function () { totalSeconds: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.totalSeconds', + "$timeEntryData.totalSeconds", 0, ], }, isTangible: { $cond: [ { - $gte: ['$timeEntryData.totalSeconds', 0], + $gte: ["$timeEntryData.totalSeconds", 0], }, - '$timeEntryData.isTangible', + "$timeEntryData.isTangible", false, ], }, @@ -535,9 +589,9 @@ const taskHelper = function () { tangibletime: { $cond: [ { - $eq: ['$isTangible', true], + $eq: ["$isTangible", true], }, - '$totalSeconds', + "$totalSeconds", 0, ], }, @@ -546,40 +600,40 @@ const taskHelper = function () { { $group: { _id: { - personId: '$personId', - weeklycommittedHours: '$weeklycommittedHours', - name: '$name', - role: '$role', + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", + name: "$name", + role: "$role", }, totalSeconds: { - $sum: '$totalSeconds', + $sum: "$totalSeconds", }, tangibletime: { - $sum: '$tangibletime', + $sum: "$tangibletime", }, }, }, { $project: { _id: 0, - personId: '$_id.personId', - name: '$_id.name', - weeklycommittedHours: '$_id.weeklycommittedHours', - role: '$_id.role', + personId: "$_id.personId", + name: "$_id.name", + weeklycommittedHours: "$_id.weeklycommittedHours", + role: "$_id.role", totaltime_hrs: { - $divide: ['$totalSeconds', 3600], + $divide: ["$totalSeconds", 3600], }, totaltangibletime_hrs: { - $divide: ['$tangibletime', 3600], + $divide: ["$tangibletime", 3600], }, }, }, { $lookup: { - from: 'tasks', - localField: 'personId', - foreignField: 'resources.userID', - as: 'tasks', + from: "tasks", + localField: "personId", + foreignField: "resources.userID", + as: "tasks", }, }, { @@ -593,25 +647,25 @@ const taskHelper = function () { }, { $unwind: { - path: '$tasks', + path: "$tasks", preserveNullAndEmptyArrays: true, }, }, { $lookup: { - from: 'wbs', - localField: 'tasks.wbsId', - foreignField: '_id', - as: 'projectId', + from: "wbs", + localField: "tasks.wbsId", + foreignField: "_id", + as: "projectId", }, }, { $addFields: { - 'tasks.projectId': { + "tasks.projectId": { $cond: [ - { $ne: ['$projectId', []] }, - { $arrayElemAt: ['$projectId', 0] }, - '$tasks.projectId', + { $ne: ["$projectId", []] }, + { $arrayElemAt: ["$projectId", 0] }, + "$tasks.projectId", ], }, }, @@ -633,40 +687,40 @@ const taskHelper = function () { }, { $addFields: { - 'tasks.projectId': '$tasks.projectId.projectId', + "tasks.projectId": "$tasks.projectId.projectId", }, }, { $lookup: { - from: 'taskNotifications', - localField: 'tasks._id', - foreignField: 'taskId', - as: 'tasks.taskNotifications', + from: "taskNotifications", + localField: "tasks._id", + foreignField: "taskId", + as: "tasks.taskNotifications", }, }, { $group: { - _id: '$personId', - tasks: { $push: '$tasks' }, + _id: "$personId", + tasks: { $push: "$tasks" }, data: { - $first: '$$ROOT', + $first: "$$ROOT", }, }, }, { $addFields: { - 'data.tasks': { + "data.tasks": { $filter: { - input: '$tasks', - as: 'task', - cond: { $ne: ['$$task', {}] }, + input: "$tasks", + as: "task", + cond: { $ne: ["$$task", {}] }, }, }, }, }, { $replaceRoot: { - newRoot: '$data', + newRoot: "$data", }, }, ]); @@ -674,7 +728,7 @@ const taskHelper = function () { const getUserProfileFirstAndLastName = function (userId) { return userProfile.findById(userId).then((results) => { if (!results) { - return ' '; + return " "; } return `${results.firstName} ${results.lastName}`; }); From c26046ec38728b000962cfd42dd7c71ca1fe24c1 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Sun, 17 Dec 2023 14:55:58 -0500 Subject: [PATCH 13/19] added timeOffFrom and timeOffTill to reportHelper --- src/helpers/reporthelper.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/helpers/reporthelper.js b/src/helpers/reporthelper.js index 3826aa8ed..eac0a71a1 100644 --- a/src/helpers/reporthelper.js +++ b/src/helpers/reporthelper.js @@ -121,7 +121,13 @@ const reporthelper = function () { }, }, teamCode: { - $ifNull: ['$teamCode', ''], + $ifNull: ["$teamCode", ""], + }, + timeOffFrom: { + $ifNull: ["$timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$timeOffTill", null], }, role: 1, weeklySummaries: { From a153942136a951dde7b4503a58f52218087ffe33 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 18 Dec 2023 14:32:17 -0500 Subject: [PATCH 14/19] updated dashboardhelper and taskHelper to add timeOffFrom anf timeOffTill for individual task and leaderboard data --- src/helpers/dashboardhelper.js | 2 ++ src/helpers/taskHelper.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index a200a0095..0482f4252 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -638,6 +638,8 @@ const dashboardhelper = function () { totalintangibletime_hrs: intangibleSeconds / 3600, percentagespentintangible: (intangibleSeconds / tangibleSeconds) * 100, + timeOffFrom: user.timeOffFrom, + timeOffTill: user.timeOffTill, }, ]; } catch (err) { diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index fc6a331b3..6d5449bc8 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -515,6 +515,12 @@ const taskHelper = function () { }, ], }, + timeOffFrom: { + $ifNull: ["$timeOffFrom", null], + }, + timeOffTill: { + $ifNull: ["$timeOffTill", null], + }, }, }, { @@ -530,6 +536,8 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, role: 1, timeEntryData: { $filter: { @@ -563,6 +571,8 @@ const taskHelper = function () { personId: 1, name: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, role: 1, totalSeconds: { $cond: [ @@ -602,6 +612,8 @@ const taskHelper = function () { _id: { personId: "$personId", weeklycommittedHours: "$weeklycommittedHours", + timeOffFrom: "$timeOffFrom", + timeOffTill: "$timeOffTill", name: "$name", role: "$role", }, @@ -619,6 +631,8 @@ const taskHelper = function () { personId: "$_id.personId", name: "$_id.name", weeklycommittedHours: "$_id.weeklycommittedHours", + timeOffFrom: "$_id.timeOffFrom", + timeOffTill: "$_id.timeOffTill", role: "$_id.role", totaltime_hrs: { $divide: ["$totalSeconds", 3600], From f484767ccef78e1e8e6118f8323003241c9daa1d Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 18 Dec 2023 17:50:04 -0500 Subject: [PATCH 15/19] modified the array representation for timeOffFrom and TimeOffTill to a value instead of array --- src/helpers/dashboardhelper.js | 265 +++++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 0482f4252..e6d5118f6 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -258,6 +258,7 @@ const dashboardhelper = function () { $gte: pdtstart, $lte: pdtend, }, +<<<<<<< HEAD personId: { $in: teamMemberIds }, }); @@ -582,6 +583,270 @@ const dashboardhelper = function () { // }, // }, // ]); +======= + { + $unwind: "$myteam", + }, + { + $project: { + _id: 0, + role: 1, + personId: "$myteam._id", + name: "$myteam.fullName", + }, + }, + { + $lookup: { + from: "userProfiles", + localField: "personId", + foreignField: "_id", + as: "persondata", + }, + }, + { + $match: { + // leaderboard user roles hierarchy + $or: [ + { + role: { $in: ["Owner", "Core Team"] }, + }, + { + $and: [ + { + role: "Administrator", + }, + { "persondata.0.role": { $nin: ["Owner", "Administrator"] } }, + ], + }, + { + $and: [ + { + role: { $in: ["Manager", "Mentor"] }, + }, + { + "persondata.0.role": { + $nin: [ + "Manager", + "Mentor", + "Core Team", + "Administrator", + "Owner", + ], + }, + }, + ], + }, + { "persondata.0._id": userId }, + { "persondata.0.role": "Volunteer" }, + { "persondata.0.isVisible": true }, + ], + }, + }, + { + $project: { + personId: 1, + name: 1, + role: { + $arrayElemAt: ["$persondata.role", 0], + }, + isVisible: { + $arrayElemAt: ["$persondata.isVisible", 0], + }, + hasSummary: { + $ne: [ + { + $arrayElemAt: [ + { + $arrayElemAt: ["$persondata.weeklySummaries.summary", 0], + }, + 0, + ], + }, + "", + ], + }, + weeklycommittedHours: { + $sum: [ + { + $arrayElemAt: ["$persondata.weeklycommittedHours", 0], + }, + { + $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0], + }, + ], + }, + timeOffFrom: { + $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null], + }, + timeOffTill: { + $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null], + }, + }, + }, + { + $lookup: { + from: "timeEntries", + localField: "personId", + foreignField: "personId", + as: "timeEntryData", + }, + }, + { + $project: { + personId: 1, + name: 1, + role: 1, + isVisible: 1, + hasSummary: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, + timeEntryData: { + $filter: { + input: "$timeEntryData", + as: "timeentry", + cond: { + $and: [ + { + $gte: ["$$timeentry.dateOfWork", pdtstart], + }, + { + $lte: ["$$timeentry.dateOfWork", pdtend], + }, + ], + }, + }, + }, + }, + }, + { + $unwind: { + path: "$timeEntryData", + preserveNullAndEmptyArrays: true, + }, + }, + { + $project: { + personId: 1, + name: 1, + role: 1, + isVisible: 1, + hasSummary: 1, + weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, + totalSeconds: { + $cond: [ + { + $gte: ["$timeEntryData.totalSeconds", 0], + }, + "$timeEntryData.totalSeconds", + 0, + ], + }, + isTangible: { + $cond: [ + { + $gte: ["$timeEntryData.totalSeconds", 0], + }, + "$timeEntryData.isTangible", + false, + ], + }, + }, + }, + { + $addFields: { + tangibletime: { + $cond: [ + { + $eq: ["$isTangible", true], + }, + "$totalSeconds", + 0, + ], + }, + intangibletime: { + $cond: [ + { + $eq: ["$isTangible", false], + }, + "$totalSeconds", + 0, + ], + }, + }, + }, + { + $group: { + _id: { + personId: "$personId", + weeklycommittedHours: "$weeklycommittedHours", + timeOffFrom: "$timeOffFrom", + timeOffTill: "$timeOffTill", + name: "$name", + role: "$role", + isVisible: "$isVisible", + hasSummary: "$hasSummary", + }, + totalSeconds: { + $sum: "$totalSeconds", + }, + tangibletime: { + $sum: "$tangibletime", + }, + intangibletime: { + $sum: "$intangibletime", + }, + }, + }, + { + $project: { + _id: 0, + personId: "$_id.personId", + name: "$_id.name", + role: "$_id.role", + isVisible: "$_id.isVisible", + hasSummary: "$_id.hasSummary", + weeklycommittedHours: "$_id.weeklycommittedHours", + totaltime_hrs: { + $divide: ["$totalSeconds", 3600], + }, + totaltangibletime_hrs: { + $divide: ["$tangibletime", 3600], + }, + totalintangibletime_hrs: { + $divide: ["$intangibletime", 3600], + }, + percentagespentintangible: { + $cond: [ + { + $eq: ["$totalSeconds", 0], + }, + 0, + { + $multiply: [ + { + $divide: ["$tangibletime", "$totalSeconds"], + }, + 100, + ], + }, + ], + }, + timeOffFrom: "$_id.timeOffFrom", + timeOffTill: "$_id.timeOffTill", + }, + }, + { + $sort: { + totaltangibletime_hrs: -1, + name: 1, + role: 1, + }, + }, + ]); +>>>>>>> 367abce (modified the array representation for timeOffFrom and TimeOffTill to a value instead of array) }; /** From a956753af7579b5049338493273f19cefb419f0d Mon Sep 17 00:00:00 2001 From: Shiwani99 <78906820+Shiwani99@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:53:26 -0500 Subject: [PATCH 16/19] Added comments to reasonSchedulingController.js --- src/controllers/reasonSchedulingController.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js index 4d56c5a5e..63dc51fed 100644 --- a/src/controllers/reasonSchedulingController.js +++ b/src/controllers/reasonSchedulingController.js @@ -55,12 +55,13 @@ const postReason = async (req, res) => { }); } - // new changes + // conditions added to check if timeOffFrom and timeOffTill fields existed if ( foundUser.hasOwnProperty("timeOffFrom") && foundUser.hasOwnProperty("timeOffTill") ) { + // if currentDate is greater than or equal to the last timeOffTill date then both the fields will be updated if (currentDate >= foundUser.timeOffTill) { await UserModel.findOneAndUpdate( { @@ -74,6 +75,7 @@ const postReason = async (req, res) => { } ); } else { + // else only timeOffTill will be updated await UserModel.findOneAndUpdate( { _id: userId, @@ -86,6 +88,7 @@ const postReason = async (req, res) => { ); } } else { + // if both the fields are not present then these fields will be added to mongoDB for that user await UserModel.findOneAndUpdate( { _id: userId, From 6346f4a40093db72230a5a4a673b50a3bd3324be Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 8 Jan 2024 06:04:11 -0500 Subject: [PATCH 17/19] fixed issues with rebasing current branch with development and added timeOffFrom and timeOffTill to the new aggregation in dashboard and task helper --- package-lock.json | 106 ++++++------- src/helpers/dashboardhelper.js | 273 +-------------------------------- src/helpers/taskHelper.js | 10 ++ 3 files changed, 71 insertions(+), 318 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff66994e8..ecce49ec7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1568,7 +1568,7 @@ "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, "@types/mime": { @@ -1729,7 +1729,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "array-includes": { "version": "3.1.6", @@ -2768,7 +2768,7 @@ "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" }, "bignumber.js": { "version": "9.0.2", @@ -2863,7 +2863,7 @@ "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, "buffer-from": { "version": "1.1.2", @@ -2995,7 +2995,7 @@ "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" }, "clone-deep": { "version": "4.0.1", @@ -3039,12 +3039,12 @@ "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "concat-stream": { "version": "1.6.2", @@ -3100,7 +3100,7 @@ "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "core-js": { "version": "3.21.1", @@ -3253,7 +3253,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { "version": "1.4.81", @@ -3269,7 +3269,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "es-abstract": { "version": "1.19.1", @@ -3350,7 +3350,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "1.0.5", @@ -4264,7 +4264,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-target-shim": { "version": "5.0.1", @@ -4445,7 +4445,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fast-text-encoding": { @@ -4575,7 +4575,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs-readdir-recursive": { "version": "1.1.0", @@ -4585,7 +4585,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "fsevents": { "version": "2.3.2", @@ -4968,7 +4968,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "indent-string": { @@ -4980,7 +4980,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -5085,7 +5085,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, "is-glob": { "version": "4.0.3", @@ -5187,13 +5187,13 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, "js-tokens": { "version": "4.0.0", @@ -5231,7 +5231,7 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "json5": { @@ -5552,7 +5552,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, "lodash.merge": { "version": "4.6.2", @@ -5729,7 +5729,7 @@ "lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=" + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" }, "make-dir": { "version": "2.1.0", @@ -5743,7 +5743,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memory-pager": { "version": "1.5.0", @@ -5754,7 +5754,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "merge-stream": { "version": "2.0.0", @@ -5765,7 +5765,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { "version": "4.0.5", @@ -5945,7 +5945,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "negotiator": { @@ -6085,7 +6085,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { "version": "1.12.0", @@ -6804,7 +6804,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -6834,7 +6834,7 @@ "os-shim": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", - "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", + "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==", "dev": true }, "p-limit": { @@ -6879,7 +6879,7 @@ "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==" }, "parseurl": { "version": "1.3.3", @@ -6894,7 +6894,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-key": { "version": "3.1.1", @@ -6910,7 +6910,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "picocolors": { "version": "1.0.0", @@ -6957,7 +6957,7 @@ "pre-commit": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz", - "integrity": "sha1-287g7p3nI15X95xW186UZBpp7sY=", + "integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==", "dev": true, "requires": { "cross-spawn": "^5.0.1", @@ -6968,7 +6968,7 @@ "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", "dev": true, "requires": { "lru-cache": "^4.0.1", @@ -6979,7 +6979,7 @@ "which": { "version": "1.2.14", "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -7021,7 +7021,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, "pstree.remy": { @@ -7499,7 +7499,7 @@ "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "optional": true, "requires": { "memory-pager": "^1.0.2" @@ -7508,7 +7508,7 @@ "spawn-sync": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", - "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", + "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==", "dev": true, "requires": { "concat-stream": "^1.4.7", @@ -7903,7 +7903,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, "strip-final-newline": { @@ -7934,19 +7934,19 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, "to-regex-range": { "version": "5.0.1", @@ -7973,7 +7973,7 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "tsconfig-paths": { "version": "3.14.2", @@ -8091,7 +8091,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true }, "unbox-primitive": { @@ -8138,7 +8138,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -8152,17 +8152,17 @@ "url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=" + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "3.4.0", @@ -8185,17 +8185,17 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -8313,7 +8313,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "ws": { "version": "8.8.1", diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index e6d5118f6..9335a67c4 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -212,6 +212,8 @@ const dashboardhelper = function () { isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, } ) .then((res) => res) @@ -229,6 +231,8 @@ const dashboardhelper = function () { isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, } ) .then((res) => res) @@ -245,6 +249,8 @@ const dashboardhelper = function () { isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, } ) .then((res) => res) @@ -258,7 +264,6 @@ const dashboardhelper = function () { $gte: pdtstart, $lte: pdtend, }, -<<<<<<< HEAD personId: { $in: teamMemberIds }, }); @@ -314,6 +319,8 @@ const dashboardhelper = function () { timeEntryByPerson[teamMember._id.toString()]?.totalSeconds) * 100 : 0, + timeOffFrom: teamMember.timeOffFrom || null, + timeOffTill: teamMember.timeOffTill || null, }; leaderBoardData.push(obj); }); @@ -583,270 +590,6 @@ const dashboardhelper = function () { // }, // }, // ]); -======= - { - $unwind: "$myteam", - }, - { - $project: { - _id: 0, - role: 1, - personId: "$myteam._id", - name: "$myteam.fullName", - }, - }, - { - $lookup: { - from: "userProfiles", - localField: "personId", - foreignField: "_id", - as: "persondata", - }, - }, - { - $match: { - // leaderboard user roles hierarchy - $or: [ - { - role: { $in: ["Owner", "Core Team"] }, - }, - { - $and: [ - { - role: "Administrator", - }, - { "persondata.0.role": { $nin: ["Owner", "Administrator"] } }, - ], - }, - { - $and: [ - { - role: { $in: ["Manager", "Mentor"] }, - }, - { - "persondata.0.role": { - $nin: [ - "Manager", - "Mentor", - "Core Team", - "Administrator", - "Owner", - ], - }, - }, - ], - }, - { "persondata.0._id": userId }, - { "persondata.0.role": "Volunteer" }, - { "persondata.0.isVisible": true }, - ], - }, - }, - { - $project: { - personId: 1, - name: 1, - role: { - $arrayElemAt: ["$persondata.role", 0], - }, - isVisible: { - $arrayElemAt: ["$persondata.isVisible", 0], - }, - hasSummary: { - $ne: [ - { - $arrayElemAt: [ - { - $arrayElemAt: ["$persondata.weeklySummaries.summary", 0], - }, - 0, - ], - }, - "", - ], - }, - weeklycommittedHours: { - $sum: [ - { - $arrayElemAt: ["$persondata.weeklycommittedHours", 0], - }, - { - $ifNull: [{ $arrayElemAt: ["$persondata.missedHours", 0] }, 0], - }, - ], - }, - timeOffFrom: { - $ifNull: [{ $arrayElemAt: ["$persondata.timeOffFrom", 0] }, null], - }, - timeOffTill: { - $ifNull: [{ $arrayElemAt: ["$persondata.timeOffTill", 0] }, null], - }, - }, - }, - { - $lookup: { - from: "timeEntries", - localField: "personId", - foreignField: "personId", - as: "timeEntryData", - }, - }, - { - $project: { - personId: 1, - name: 1, - role: 1, - isVisible: 1, - hasSummary: 1, - weeklycommittedHours: 1, - timeOffFrom: 1, - timeOffTill: 1, - timeEntryData: { - $filter: { - input: "$timeEntryData", - as: "timeentry", - cond: { - $and: [ - { - $gte: ["$$timeentry.dateOfWork", pdtstart], - }, - { - $lte: ["$$timeentry.dateOfWork", pdtend], - }, - ], - }, - }, - }, - }, - }, - { - $unwind: { - path: "$timeEntryData", - preserveNullAndEmptyArrays: true, - }, - }, - { - $project: { - personId: 1, - name: 1, - role: 1, - isVisible: 1, - hasSummary: 1, - weeklycommittedHours: 1, - timeOffFrom: 1, - timeOffTill: 1, - totalSeconds: { - $cond: [ - { - $gte: ["$timeEntryData.totalSeconds", 0], - }, - "$timeEntryData.totalSeconds", - 0, - ], - }, - isTangible: { - $cond: [ - { - $gte: ["$timeEntryData.totalSeconds", 0], - }, - "$timeEntryData.isTangible", - false, - ], - }, - }, - }, - { - $addFields: { - tangibletime: { - $cond: [ - { - $eq: ["$isTangible", true], - }, - "$totalSeconds", - 0, - ], - }, - intangibletime: { - $cond: [ - { - $eq: ["$isTangible", false], - }, - "$totalSeconds", - 0, - ], - }, - }, - }, - { - $group: { - _id: { - personId: "$personId", - weeklycommittedHours: "$weeklycommittedHours", - timeOffFrom: "$timeOffFrom", - timeOffTill: "$timeOffTill", - name: "$name", - role: "$role", - isVisible: "$isVisible", - hasSummary: "$hasSummary", - }, - totalSeconds: { - $sum: "$totalSeconds", - }, - tangibletime: { - $sum: "$tangibletime", - }, - intangibletime: { - $sum: "$intangibletime", - }, - }, - }, - { - $project: { - _id: 0, - personId: "$_id.personId", - name: "$_id.name", - role: "$_id.role", - isVisible: "$_id.isVisible", - hasSummary: "$_id.hasSummary", - weeklycommittedHours: "$_id.weeklycommittedHours", - totaltime_hrs: { - $divide: ["$totalSeconds", 3600], - }, - totaltangibletime_hrs: { - $divide: ["$tangibletime", 3600], - }, - totalintangibletime_hrs: { - $divide: ["$intangibletime", 3600], - }, - percentagespentintangible: { - $cond: [ - { - $eq: ["$totalSeconds", 0], - }, - 0, - { - $multiply: [ - { - $divide: ["$tangibletime", "$totalSeconds"], - }, - 100, - ], - }, - ], - }, - timeOffFrom: "$_id.timeOffFrom", - timeOffTill: "$_id.timeOffTill", - }, - }, - { - $sort: { - totaltangibletime_hrs: -1, - name: 1, - role: 1, - }, - }, - ]); ->>>>>>> 367abce (modified the array representation for timeOffFrom and TimeOffTill to a value instead of array) }; /** diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index 6d5449bc8..8347a56ef 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -22,6 +22,8 @@ const taskHelper = function () { isVisible: 1, weeklycommittedHours: 1, weeklySummaries: 1, + timeOffFrom: 1, + timeOffTill: 1, } ) .then((res) => res) @@ -68,6 +70,8 @@ const taskHelper = function () { firstName: 1, lastName: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, } ) .then((res) => res) @@ -83,6 +87,8 @@ const taskHelper = function () { firstName: 1, lastName: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, } ) .then((res) => res) @@ -97,6 +103,8 @@ const taskHelper = function () { firstName: 1, lastName: 1, weeklycommittedHours: 1, + timeOffFrom: 1, + timeOffTill: 1, } ) .then((res) => res) @@ -196,6 +204,8 @@ const taskHelper = function () { timeEntryByPerson[teamMember._id.toString()]?.totalSeconds / 3600 || 0, tasks: taskByPerson[teamMember._id.toString()] || [], + timeOffFrom: teamMember.timeOffFrom || null, + timeOffTill: teamMember.timeOffTill || null, }; teamMemberTasksData.push(obj); }); From 2f362910ce36b623aff3ddfe2ce02d2353153e74 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 8 Jan 2024 07:22:46 -0500 Subject: [PATCH 18/19] resolved errors after merge conflicts --- src/controllers/reasonSchedulingController.js | 11 +--------- src/helpers/dashboardhelper.js | 21 ++++++++++--------- src/helpers/taskHelper.js | 15 ------------- 3 files changed, 12 insertions(+), 35 deletions(-) diff --git a/src/controllers/reasonSchedulingController.js b/src/controllers/reasonSchedulingController.js index 4fce71b3a..a76dcf4a2 100644 --- a/src/controllers/reasonSchedulingController.js +++ b/src/controllers/reasonSchedulingController.js @@ -11,9 +11,6 @@ const postReason = async (req, res) => { .tz(reasonData.date, "America/Los_Angeles") .startOf("day"); const currentDate = moment.tz("America/Los_Angeles").startOf("day"); - .tz(reasonData.date, "America/Los_Angeles") - .startOf("day"); - const currentDate = moment.tz("America/Los_Angeles").startOf("day"); // error case 0 if (moment.tz(reasonData.date, "America/Los_Angeles").day() !== 0) { @@ -38,7 +35,6 @@ const postReason = async (req, res) => { }); } - // Commented this condition to make reason scheduler available to all the users. // error case 1 // if (requestor.role !== 'Owner' && requestor.role !== 'Administrator') { @@ -160,7 +156,6 @@ const postReason = async (req, res) => { // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); } - return res.sendStatus(200); } catch (error) { console.log(error); @@ -307,11 +302,9 @@ const patchReason = async (req, res) => { const savedData = await foundReason.save(); if (savedData) { - // Upon clicking the "Save" button in the Blue Square Reason Scheduler, an email will be automatically sent to the user and Jae. const subject = `Blue Square Reason for ${foundUser.firstName} ${foundUser.lastName} has been updated`; - const emailBody = `

Hi !

const emailBody = `

Hi !

This email is to let you know that ${foundUser.firstName} ${foundUser.lastName} has updated their Blue Square Reason.

@@ -331,7 +324,6 @@ const patchReason = async (req, res) => { // emailSender(`${foundUser.email},@gmail.com`, subject, emailBody, null, null); } - return res.status(200).json({ message: "Reason Updated!", message: "Reason Updated!", @@ -348,13 +340,12 @@ const deleteReason = async (req, res) => { const { reasonData, requestor } = req.body; const { userId } = req.params; - // error case 1 if (requestor.role !== "Owner" && requestor.role !== "Administrator") { return res.status(403).json({ message: "You must be an Owner or Administrator to schedule a reason for a Blue Square", - "You must be an Owner or Administrator to schedule a reason for a Blue Square", + errorCode: 1, }); } diff --git a/src/helpers/dashboardhelper.js b/src/helpers/dashboardhelper.js index 2babef0b2..9f172dd2a 100644 --- a/src/helpers/dashboardhelper.js +++ b/src/helpers/dashboardhelper.js @@ -174,20 +174,17 @@ const dashboardhelper = function () { .then((res) => res) .catch((e) => {}); - if (userById == null) return null; const userRole = userById.role; const pdtstart = moment() .tz("America/Los_Angeles") .startOf("week") .format("YYYY-MM-DD"); + + const pdtend = moment() .tz("America/Los_Angeles") - .startOf("week") + .endOf("week") .format("YYYY-MM-DD"); - const pdtend = moment() - .tz('America/Los_Angeles') - .endOf('week') - .format('YYYY-MM-DD'); let teamMemberIds = [userid]; let teamMembers = []; @@ -210,9 +207,6 @@ const dashboardhelper = function () { }); }); - teamMembers = await userProfile - .find( - { _id: { $in: teamMemberIds }, isActive: true }, teamMembers = await userProfile .find( { _id: { $in: teamMemberIds }, isActive: true }, @@ -235,6 +229,7 @@ const dashboardhelper = function () { teamMembers = await userProfile .find( { isActive: true, role: { $nin: excludedRoles } }, + { role: 1, firstName: 1, lastName: 1, @@ -300,7 +295,13 @@ const dashboardhelper = function () { timeEntries.map((timeEntry) => { const personIdStr = timeEntry.personId.toString(); - if (timeEntryByPerson[personIdStr] == null) { timeEntryByPerson[personIdStr] = { tangibleSeconds: 0, intangibleSeconds: 0, totalSeconds: 0 }; } + if (timeEntryByPerson[personIdStr] == null) { + timeEntryByPerson[personIdStr] = { + tangibleSeconds: 0, + intangibleSeconds: 0, + totalSeconds: 0, + }; + } if (timeEntry.isTangible === true) { timeEntryByPerson[personIdStr].tangibleSeconds += diff --git a/src/helpers/taskHelper.js b/src/helpers/taskHelper.js index 0d26b96bb..372c960dd 100644 --- a/src/helpers/taskHelper.js +++ b/src/helpers/taskHelper.js @@ -40,25 +40,10 @@ const taskHelper = function () { .tz("America/Los_Angeles") .endOf("week") .format("YYYY-MM-DD"); - .tz("America/Los_Angeles") - .endOf("week") - .format("YYYY-MM-DD"); let teamMemberIds = [userid]; let teamMembers = []; - let teamMemberIds = [userid]; - let teamMembers = []; - if ( - userRole != "Administrator" && - userRole != "Owner" && - userRole != "Core Team" - ) { - // Manager , Mentor , Volunteer ... , Show only team members - const teamsResult = await team - .find({ "members.userId": { $in: [userid] } }, { members: 1 }) - .then((res) => res) - .catch((e) => {}); if ( userRole != "Administrator" && userRole != "Owner" && From bd9a1500299a597190de07ff4eb38e6ef4b2ef77 Mon Sep 17 00:00:00 2001 From: Shiwani Rajagopalan Date: Mon, 8 Jan 2024 07:26:38 -0500 Subject: [PATCH 19/19] resolved errors in userProfile.js after conflicts --- src/models/userProfile.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/models/userProfile.js b/src/models/userProfile.js index 8f5e23d2c..aaa3923f5 100644 --- a/src/models/userProfile.js +++ b/src/models/userProfile.js @@ -1,13 +1,9 @@ const mongoose = require("mongoose"); const moment = require("moment-timezone"); -const mongoose = require("mongoose"); -const moment = require("moment-timezone"); const { Schema } = mongoose; const validate = require("mongoose-validator"); const bcrypt = require("bcryptjs"); -const validate = require("mongoose-validator"); -const bcrypt = require("bcryptjs"); const SALT_ROUNDS = 10; const nextDay = new Date();