Va and project List API update

This commit is contained in:
=bhagwanSingh 2025-12-05 13:29:04 +05:30
parent 59561f211d
commit 00cb793a7c
13 changed files with 169 additions and 134 deletions

View File

@ -6,7 +6,7 @@
"scripts": {
"start": "nodemon --inspect src/server.js",
"test": "echo \"Error: no test specified\" && exit 1",
"deploy": "curl -X POST http://35.162.222.18:9000/hooks/deploy-va-middleware",
"deploy": "curl -X POST http://35.95.209.161:9000/hooks/deploy-va-middleware",
"build": "npx webpack --mode production",
"dev": "npx webpack --mode development"
},

View File

@ -4,8 +4,8 @@ import { updateEntityRelationships } from "../../helper/updateEntityRelationship
// Register a new VA
async function project_add_sf(req, res) {
try {
const payload = req.body|| {};
const { name, hourlyRate, clientId, vaAssigned, dedicatedHours, vaWorkingScheduleStart, vaWorkingScheduleEnd, isFlexibleAllowedPt, vaWorkingDelayAllowedStart, vaWorkingDelayAllowedEnd } = payload;
const payload = req.body || {};
const { name, hourlyRate, clientId, vaAssigned, dedicatedHours, vaWorkingScheduleStart, vaWorkingScheduleEnd, isFlexibleAllowed, vaWorkingDelayAllowedStart, vaWorkingDelayAllowedEnd } = payload;
// Validate required fields
if (!name) {
@ -34,46 +34,55 @@ async function project_add_sf(req, res) {
}
// Validate and convert vaAssigned to array of ObjectIds
let vaAssignedArray = [];
if (vaAssigned) {
if (Array.isArray(vaAssigned)) {
try {
vaAssignedArray = vaAssigned.map(vaId => new Types.ObjectId(vaId));
} catch (error) {
return res.status(400).json({
success: false,
message: "Invalid VA ID format in vaAssigned array"
});
}
} else if (typeof vaAssigned === 'string') {
// Handle single VA ID as string
try {
vaAssignedArray = [new Types.ObjectId(vaAssigned)];
} catch (error) {
return res.status(400).json({
success: false,
message: "Invalid VA ID format"
});
}
}
}
// let vaAssignedArray = [];
// if (vaAssigned) {
// if (Array.isArray(vaAssigned)) {
// try {
// vaAssignedArray = vaAssigned.map(vaId => {
// if(typeof vaId === 'object' && "isFlexibleAllowed" in vaId){
// // Handle Error form SF Side for now - That vaId is coming as object
// return new Types.ObjectId(vaId.vaId)
// } else {
// return new Types.ObjectId(vaId)
// }
// });
// } catch (error) {
// return res.status(400).json({
// success: false,
// message: "Invalid VA ID format in vaAssigned array"
// });
// }
// } else if (typeof vaAssigned === 'string') {
// // Handle single VA ID as string
// try {
// vaAssignedArray = [new Types.ObjectId(vaAssigned)];
// } catch (error) {
// return res.status(400).json({
// success: false,
// message: "Invalid VA ID format"
// });
// }
// }
// }
// sanitize/construct allowed fields
const toCreate = {
name: name.trim(),
hourlyRate: hourlyRate || '0',
clientId: clientObjectId,
vaAssigned: vaAssignedArray,
vaAssigned: vaAssigned,
dedicatedHours: dedicatedHours ? parseFloat(dedicatedHours) : 0,
vaWorkingScheduleStart: vaWorkingScheduleStart || null,
vaWorkingScheduleEnd: vaWorkingScheduleEnd || null,
isFlexibleAllowedPt: isFlexibleAllowedPt || true,
isFlexibleAllowed: isFlexibleAllowed || true,
vaWorkingDelayAllowedStart: vaWorkingDelayAllowedStart || null,
vaWorkingDelayAllowedEnd: vaWorkingDelayAllowedEnd || null
};
const created = await ProjectModel.create(toCreate);
const vaAssignedArray = vaAssigned ? vaAssigned.map(vaDtl => vaDtl.vaId) : [];
const relationshipUpdate = await updateEntityRelationships({
project: {
projectId: created._id,

View File

@ -16,10 +16,10 @@ async function update_project_sf(req, res) {
vaAssigned,
dedicatedHours,
status,
totalLoggedHours ,
totalLoggedHours,
vaWorkingScheduleStart,
vaWorkingScheduleEnd,
isFlexibleAllowedPt,
isFlexibleAllowed,
vaWorkingDelayAllowedStart,
vaWorkingDelayAllowedEnd
} = payload;
@ -102,8 +102,8 @@ async function update_project_sf(req, res) {
updateData.vaWorkingScheduleEnd = vaWorkingScheduleEnd || null;
}
if (isFlexibleAllowedPt !== undefined) {
updateData.isFlexibleAllowedPt = isFlexibleAllowedPt;
if (isFlexibleAllowed !== undefined) {
updateData.isFlexibleAllowed = isFlexibleAllowed;
}
if (vaWorkingDelayAllowedStart !== undefined) {
@ -114,15 +114,26 @@ async function update_project_sf(req, res) {
updateData.vaWorkingDelayAllowedEnd = vaWorkingDelayAllowedEnd || null;
}
if (vaAssigned !== undefined && vaAssigned !== null && Array.isArray(vaAssigned)) {
updateData.vaAssigned = vaAssigned;
}
// Handle VA assignments - this requires relationship updates
if (vaAssigned !== undefined) {
let newVaAssignedArray = [];
let newVaAssignedArray = updateData.vaAssigned.map(vaDtl => vaDtl.vaId);
// Parse and validate VA IDs
if (vaAssigned && vaAssigned.length > 0) {
if (Array.isArray(vaAssigned)) {
try {
newVaAssignedArray = vaAssigned.map(vaId => new Types.ObjectId(vaId));
newVaAssignedArray = vaAssigned.map(vaId => {
if (typeof vaId === 'object' && "isFlexibleAllowed" in vaId) {
// Handle Error form SF Side for now - That vaId is coming as object
return new Types.ObjectId(vaId.vaId)
} else {
return new Types.ObjectId(vaId)
}
});
} catch (error) {
return res.status(400).json({
success: false,
@ -141,7 +152,7 @@ async function update_project_sf(req, res) {
}
}
updateData.vaAssigned = newVaAssignedArray;
// updateData.vaAssigned = newVaAssignedArray;
// Calculate VAs to add and remove for relationship updates
const currentVaIds = existingProject.vaAssigned.map(va => va.toString());

View File

@ -44,7 +44,7 @@ async function va_remove_function(req, res) {
if (projectIds.length > 0) {
const projectResult = await ProjectModel.updateMany(
{ _id: { $in: projectIds } },
{ $pull: { vaAssigned: vaId } }
{ $pull: { "vaAssigned.vaId": vaId } }
);
projectsUpdated = projectResult.modifiedCount;
console.log(`Removed VA from ${projectsUpdated} projects`);

View File

@ -105,7 +105,7 @@ function getCurrentUTCTime() {
// console.log(`Schedule Check - Current: ${currentMinutes}, Start: ${scheduleStartMinutes}, End: ${scheduleEndMinutes}, Allowed Start: ${allowedStartMinutes}, Allowed End: ${allowedEndMinutes}`);
// // Check for PARTTIME with flexible schedule
// if (vaStatus === "PARTTIME" && project.isFlexibleAllowedPt) {
// if (vaStatus === "PARTTIME" && project.isFlexibleAllowed) {
// return { isCompliant: true, warnings };
// }

View File

@ -72,7 +72,7 @@ async function va_projects_log_list_function(req, res) {
console.log("VA ID:", vaId.toString());
projectList = await ProjectModel.find({ vaAssigned: vaUser._id });
projectList = await ProjectModel.find({ "vaAssigned.vaId": vaUser._id });
}
if (!projectList.length) {

View File

@ -34,7 +34,7 @@ async function va_timesheet_adjustment_function(req, res) {
// Validate project exists and VA is assigned to it
const project = await ProjectModel.findOne({
_id: projectId,
vaAssigned: vaId
"vaAssigned.vaId": vaId
});
if (!project) {

View File

@ -43,7 +43,7 @@ async function va_timesheet_summary_function(req, res) {
// Validate project exists and VA is assigned to it
const project = await ProjectModel.findOne({
_id: projectId,
vaAssigned: vaId
"vaAssigned.vaId": vaId
});
if (!project) {

View File

@ -20,7 +20,7 @@ async function va_tips_manage_function(req, res) {
clientId,
status: "Unbilled",
amount: parseFloat(amount).toFixed(2),
description,
description: description || "",
vaName: vaUser.userDetails.firstName ? vaUser.userDetails.firstName : "" + " " + vaUser.userDetails.lastName ? vaUser.userDetails.lastName : "",
vaId,
};
@ -34,7 +34,7 @@ async function va_tips_manage_function(req, res) {
"vaId": createdTip.vaId.toString(),
"status": "Unbilled",
"clientId": createdTip.clientId.toString(),
"comment": createdTip.description,
"comment": createdTip.description || "",
"tipAmount": Number(parseFloat(createdTip.amount).toFixed(2)), // Convert to cents
}

View File

@ -69,7 +69,7 @@ async function updateEntityRelationships(data) {
if (vaId && Array.isArray(vaId)) {
await ProjectModel.findByIdAndUpdate(
projectId,
{ $addToSet: { vaAssigned: { $each: vaId } } }
{ $addToSet: { "vaAssigned.vaId": { $each: vaId } } }
);
}
@ -103,7 +103,7 @@ async function updateEntityRelationships(data) {
{ _id: { $in: projectId } },
{
$addToSet: {
vaAssigned: vaId
"vaAssigned.vaId": vaId
}
}
);
@ -285,7 +285,7 @@ async function removeEntityRelationships(data) {
if (projectId && Array.isArray(projectId)) {
await ProjectModel.updateMany(
{ _id: { $in: projectId } },
{ $pull: { vaAssigned: vaId } }
{ $pull: { "vaAssigned.vaId": vaId } }
);
}

View File

@ -89,9 +89,16 @@ const projectSchema = new Schema({
},
vaAssigned: [
{
_id: false,
vaId: {
type: Types.ObjectId,
ref: "VA",
},
isFlexibleAllowed: {
type: Boolean,
default: true
}
}
],
dedicatedHours: {
type: String,
@ -110,7 +117,7 @@ const projectSchema = new Schema({
type: String,
default: null
},
isFlexibleAllowedPt: {
isFlexibleAllowed: {
type: Boolean,
default: true
},

View File

@ -341,7 +341,7 @@ io.on("connection", (socket) => {
const projectVAIds = new Set();
const populated = await ProjectModel.findById(projectId).populate("vaAssigned");
populated.vaAssigned.forEach((va) => projectVAIds.add(va._id.toString()));
populated.vaAssigned.forEach((va) => projectVAIds.add(va.vaId.toString()));
socket.data.allowedVAs = Array.from(projectVAIds);
console.log(`Client ${clientId} can view VAs:`, socket.data.allowedVAs);
@ -498,6 +498,14 @@ io.on("connection", (socket) => {
});
app.get("/heath", () => {
if(Math.round(Math.random()) === 1) {
return res.status(200).json({"success": true, "message": "Server is Healthy"})
} else {
return res.status(403).json({"success": false, "message": "Server is not Healthy"})
}
})
app.use((req, res) => {
res.status(404).render("not_found", {
title: "404 - Page Not Found"

View File

@ -184,7 +184,7 @@
</div>
<div class="form-group">
<label class="form-label">Tip Description</label>
<textarea name="vaTipDescription" class="form-input" id="vaTipDescription"></textarea>
<textarea required="true" name="vaTipDescription" class="form-input" id="vaTipDescription"></textarea>
<div class="error-message" id="vaTipDescriptionError"></div>
</div>
<div class="modal-actions">