Skip to content

Commit dd56658

Browse files
Merge pull request #1704 from Real-Dev-Squad/develop
dev to main sync
2 parents 46b7470 + 6d31b55 commit dd56658

File tree

9 files changed

+283
-80
lines changed

9 files changed

+283
-80
lines changed

controllers/tasks.js

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ const updateTaskStatus = async (req, res, next) => {
312312
try {
313313
let userStatusUpdate;
314314
const taskId = req.params.id;
315-
const { userStatusFlag } = req.query;
316315
const { id: userId, username } = req.userData;
317316
const task = await tasks.fetchSelfTask(taskId, userId);
318317

@@ -321,34 +320,18 @@ const updateTaskStatus = async (req, res, next) => {
321320
if (task.taskData.status === TASK_STATUS.VERIFIED || req.body.status === TASK_STATUS.MERGED)
322321
return res.boom.forbidden("Status cannot be updated. Please contact admin.");
323322

324-
if (userStatusFlag) {
325-
if (task.taskData.status === TASK_STATUS.DONE && req.body.percentCompleted < 100) {
326-
if (req.body.status === TASK_STATUS.DONE || !req.body.status) {
327-
return res.boom.badRequest("Task percentCompleted can't updated as status is DONE");
328-
}
329-
}
330-
331-
if (
332-
(req.body.status === TASK_STATUS.DONE || req.body.status === TASK_STATUS.VERIFIED) &&
333-
task.taskData.percentCompleted !== 100
334-
) {
335-
if (req.body.percentCompleted !== 100) {
336-
return res.boom.badRequest("Status cannot be updated. Task is not done yet");
337-
}
323+
if (task.taskData.status === TASK_STATUS.DONE && req.body.percentCompleted < 100) {
324+
if (req.body.status === TASK_STATUS.DONE || !req.body.status) {
325+
return res.boom.badRequest("Task percentCompleted can't updated as status is DONE");
338326
}
339327
}
340328

341-
if (task.taskData.status === TASK_STATUS.COMPLETED && req.body.percentCompleted < 100) {
342-
if (req.body.status === TASK_STATUS.COMPLETED || !req.body.status) {
343-
return res.boom.badRequest("Task percentCompleted can't updated as status is COMPLETED");
344-
}
345-
}
346329
if (
347-
(req.body.status === TASK_STATUS.COMPLETED || req.body.status === TASK_STATUS.VERIFIED) &&
330+
(req.body.status === TASK_STATUS.DONE || req.body.status === TASK_STATUS.VERIFIED) &&
348331
task.taskData.percentCompleted !== 100
349332
) {
350333
if (req.body.percentCompleted !== 100) {
351-
return res.boom.badRequest("Status cannot be updated. Task is not completed yet");
334+
return res.boom.badRequest("Status cannot be updated. Task is not done yet");
352335
}
353336
}
354337

@@ -443,6 +426,16 @@ const assignTask = async (req, res) => {
443426
}
444427
};
445428

429+
const updateStatus = async (req, res) => {
430+
try {
431+
const response = await tasks.updateTaskStatus();
432+
return res.status(200).json(response);
433+
} catch (error) {
434+
logger.error("Error in migration scripts", error);
435+
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
436+
}
437+
};
438+
446439
module.exports = {
447440
addNewTask,
448441
fetchTasks,
@@ -453,4 +446,5 @@ module.exports = {
453446
updateTaskStatus,
454447
overdueTasks,
455448
assignTask,
449+
updateStatus,
456450
};

models/tasks.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ const tasksModel = firestore.collection("tasks");
33
const ItemModel = firestore.collection("itemTags");
44
const dependencyModel = firestore.collection("taskDependencies");
55
const userUtils = require("../utils/users");
6+
const { updateTaskStatusToDone } = require("../services/tasks");
7+
const { chunks } = require("../utils/array");
8+
const { DOCUMENT_WRITE_SIZE } = require("../constants/constants");
69
const { fromFirestoreData, toFirestoreData, buildTasks } = require("../utils/tasks");
710
const { TASK_TYPE, TASK_STATUS, TASK_STATUS_OLD, TASK_SIZE } = require("../constants/tasks");
811
const { IN_PROGRESS, NEEDS_REVIEW, IN_REVIEW, ASSIGNED, BLOCKED, SMOKE_TESTING, COMPLETED, SANITY_CHECK } = TASK_STATUS;
912
const { OLD_ACTIVE, OLD_BLOCKED, OLD_PENDING, OLD_COMPLETED } = TASK_STATUS_OLD;
13+
const { INTERNAL_SERVER_ERROR } = require("../constants/errorMessages");
1014

1115
/**
1216
* Adds and Updates tasks
@@ -575,6 +579,62 @@ const getOverdueTasks = async (days = 0) => {
575579
}
576580
};
577581

582+
const updateTaskStatus = async () => {
583+
try {
584+
const snapshot = await tasksModel.where("status", "==", "COMPLETED").get();
585+
const tasksStatusCompleted = [];
586+
let summary = {
587+
totalTasks: snapshot.size,
588+
totalUpdatedStatus: 0,
589+
totalOperationsFailed: 0,
590+
updatedTaskDetails: [],
591+
failedTaskDetails: [],
592+
};
593+
594+
if (snapshot.size === 0) {
595+
return summary;
596+
}
597+
598+
snapshot.forEach((task) => {
599+
const id = task.id;
600+
const taskData = task.data();
601+
tasksStatusCompleted.push({ ...taskData, id });
602+
});
603+
const taskStatusCompletedChunks = chunks(tasksStatusCompleted, DOCUMENT_WRITE_SIZE);
604+
605+
const updatedTasksPromises = await Promise.all(
606+
taskStatusCompletedChunks.map(async (tasks) => {
607+
const res = await updateTaskStatusToDone(tasks);
608+
return {
609+
totalUpdatedStatus: res.totalUpdatedStatus,
610+
totalOperationsFailed: res.totalOperationsFailed,
611+
updatedTaskDetails: res.updatedTaskDetails,
612+
failedTaskDetails: res.failedTaskDetails,
613+
};
614+
})
615+
);
616+
617+
updatedTasksPromises.forEach((res) => {
618+
summary = {
619+
...summary,
620+
totalUpdatedStatus: (summary.totalUpdatedStatus += res.totalUpdatedStatus),
621+
totalOperationsFailed: (summary.totalOperationsFailed += res.totalOperationsFailed),
622+
updatedTaskDetails: [...summary.updatedTaskDetails, ...res.updatedTaskDetails],
623+
failedTaskDetails: [...summary.failedTaskDetails, ...res.failedTaskDetails],
624+
};
625+
});
626+
627+
if (summary.totalOperationsFailed === summary.totalTasks) {
628+
throw Error(INTERNAL_SERVER_ERROR);
629+
}
630+
631+
return summary;
632+
} catch (error) {
633+
logger.error(`Error in updating task status: ${error}`);
634+
throw error;
635+
}
636+
};
637+
578638
module.exports = {
579639
updateTask,
580640
fetchTasks,
@@ -591,4 +651,5 @@ module.exports = {
591651
fetchPaginatedTasks,
592652
getBuiltTasks,
593653
getOverdueTasks,
654+
updateTaskStatus,
594655
};

routes/taskRequests.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ const taskRequests = require("../controllers/tasksRequests");
77
const { validateUser } = require("../middlewares/taskRequests");
88
const validators = require("../middlewares/validators/task-requests");
99

10-
router.get("/", authenticate, authorizeRoles([SUPERUSER]), validators.getTaskRequests, taskRequests.fetchTaskRequests);
11-
router.get("/:id", authenticate, authorizeRoles([SUPERUSER]), taskRequests.fetchTaskRequestById);
10+
router.get("/", authenticate, taskRequests.fetchTaskRequests);
11+
router.get("/:id", authenticate, taskRequests.fetchTaskRequestById);
1212
router.post("/addOrUpdate", authenticate, validateUser, taskRequests.addOrUpdate);
1313
router.patch("/approve", authenticate, authorizeRoles([SUPERUSER]), validateUser, taskRequests.approveTaskRequest);
1414
router.post("/", authenticate, validators.postTaskRequests, taskRequests.addTaskRequests);

routes/tasks.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@ router.patch(
4040
);
4141
router.patch("/assign/self", authenticate, invalidateCache({ invalidationKeys: [ALL_TASKS] }), tasks.assignTask);
4242

43+
router.post("/migration", authenticate, authorizeRoles([SUPERUSER]), tasks.updateStatus);
44+
4345
module.exports = router;

services/tasks.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const firestore = require("../utils/firestore");
2+
const tasksModel = firestore.collection("tasks");
3+
const updateTaskStatusToDone = async (tasksData) => {
4+
const batch = firestore.batch();
5+
const tasksBatch = [];
6+
const summary = {
7+
totalUpdatedStatus: 0,
8+
totalOperationsFailed: 0,
9+
updatedTaskDetails: [],
10+
failedTaskDetails: [],
11+
};
12+
tasksData.forEach((task) => {
13+
const updateTaskData = { ...task, status: "DONE" };
14+
batch.update(tasksModel.doc(task.id), updateTaskData);
15+
tasksBatch.push(task.id);
16+
});
17+
try {
18+
await batch.commit();
19+
summary.totalUpdatedStatus += tasksData.length;
20+
summary.updatedTaskDetails = [...tasksBatch];
21+
return { ...summary };
22+
} catch (err) {
23+
logger.error("Firebase batch Operation Failed!");
24+
summary.totalOperationsFailed += tasksData.length;
25+
summary.failedTaskDetails = [...tasksBatch];
26+
return { ...summary };
27+
}
28+
};
29+
module.exports = {
30+
updateTaskStatusToDone,
31+
};

test/integration/taskRequests.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ describe("Task Requests", function () {
119119
await taskRequestsModel.addOrUpdate(taskId, userId);
120120
});
121121

122-
it("should return 401 unauthorized user response", function (done) {
122+
it("should be successful when the user is not a super user", function (done) {
123123
chai
124124
.request(app)
125125
.get("/taskRequests")
@@ -129,7 +129,7 @@ describe("Task Requests", function () {
129129
return done(err);
130130
}
131131

132-
expect(res).to.have.status(401);
132+
expect(res).to.have.status(200);
133133
return done();
134134
});
135135
});
@@ -196,7 +196,7 @@ describe("Task Requests", function () {
196196
await taskRequestsModel.addOrUpdate(taskId, userId);
197197
});
198198

199-
it("should return 401 status code", function (done) {
199+
it("should be successful when the user is not a super user", function (done) {
200200
chai
201201
.request(app)
202202
.get(`/taskRequests/taskrequstid`)
@@ -206,7 +206,7 @@ describe("Task Requests", function () {
206206
return done(err);
207207
}
208208

209-
expect(res).to.have.status(401);
209+
expect(res).to.have.status(200);
210210
return done();
211211
});
212212
});

test/integration/tasks.test.js

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const sinon = require("sinon");
33
const { expect } = chai;
44
const chaiHttp = require("chai-http");
55

6+
const firestore = require("../../utils/firestore");
67
const app = require("../../server");
78
const tasks = require("../../models/tasks");
89
const authService = require("../../services/authService");
@@ -958,19 +959,7 @@ describe("Tasks", function () {
958959
expect(res.body.message).to.be.equal("Status cannot be updated. Please contact admin.");
959960
});
960961

961-
it("Should give 400 if percentCompleted is not 100 and new status is COMPLETED ", async function () {
962-
taskId = (await tasks.updateTask({ ...taskData, status: "REVIEW", assignee: appOwner.username })).taskId;
963-
const res = await chai
964-
.request(app)
965-
.patch(`/tasks/self/${taskId}`)
966-
.set("cookie", `${cookieName}=${jwt}`)
967-
.send({ ...taskStatusData, status: "COMPLETED" });
968-
969-
expect(res).to.have.status(400);
970-
expect(res.body.message).to.be.equal("Status cannot be updated. Task is not completed yet");
971-
});
972-
973-
it("Should give 400 if percentCompleted is not 100 and new status is DONE under feature flag ", async function () {
962+
it("Should give 400 if percentCompleted is not 100 and new status is DONE", async function () {
974963
taskId = (await tasks.updateTask({ ...taskData, status: "REVIEW", assignee: appOwner.username })).taskId;
975964
const res = await chai
976965
.request(app)
@@ -982,19 +971,7 @@ describe("Tasks", function () {
982971
expect(res.body.message).to.be.equal("Status cannot be updated. Task is not done yet");
983972
});
984973

985-
it("Should give 400 if percentCompleted is not 100 and new status is VERIFIED ", async function () {
986-
taskId = (await tasks.updateTask({ ...taskData, status: "REVIEW", assignee: appOwner.username })).taskId;
987-
const res = await chai
988-
.request(app)
989-
.patch(`/tasks/self/${taskId}`)
990-
.set("cookie", `${cookieName}=${jwt}`)
991-
.send({ ...taskStatusData, status: "VERIFIED" });
992-
993-
expect(res).to.have.status(400);
994-
expect(res.body.message).to.be.equal("Status cannot be updated. Task is not completed yet");
995-
});
996-
997-
it("Should give 400 if percentCompleted is not 100 and new status is VERIFIED under feature flag", async function () {
974+
it("Should give 400 if percentCompleted is not 100 and new status is VERIFIED", async function () {
998975
taskId = (await tasks.updateTask({ ...taskData, status: "REVIEW", assignee: appOwner.username })).taskId;
999976
const res = await chai
1000977
.request(app)
@@ -1006,32 +983,7 @@ describe("Tasks", function () {
1006983
expect(res.body.message).to.be.equal("Status cannot be updated. Task is not done yet");
1007984
});
1008985

1009-
it("Should give 400 if status is COMPLETED and newpercent is less than 100", async function () {
1010-
const taskData = {
1011-
title: "Test task",
1012-
type: "feature",
1013-
endsOn: 1234,
1014-
startedOn: 4567,
1015-
status: "COMPLETED",
1016-
percentCompleted: 100,
1017-
participants: [],
1018-
assignee: appOwner.username,
1019-
completionAward: { [DINERO]: 3, [NEELAM]: 300 },
1020-
lossRate: { [DINERO]: 1 },
1021-
isNoteworthy: true,
1022-
};
1023-
taskId = (await tasks.updateTask(taskData)).taskId;
1024-
const res = await chai
1025-
.request(app)
1026-
.patch(`/tasks/self/${taskId}`)
1027-
.set("cookie", `${cookieName}=${jwt}`)
1028-
.send({ percentCompleted: 80 });
1029-
1030-
expect(res).to.have.status(400);
1031-
expect(res.body.message).to.be.equal("Task percentCompleted can't updated as status is COMPLETED");
1032-
});
1033-
1034-
it("Should give 400 if status is DONE and newpercent is less than 100 under feature flag", async function () {
986+
it("Should give 400 if status is DONE and newpercent is less than 100", async function () {
1035987
taskId = (await tasks.updateTask(updateTaskStatus[0])).taskId;
1036988
const res = await chai
1037989
.request(app)
@@ -1070,4 +1022,51 @@ describe("Tasks", function () {
10701022
expect(res.body.message).to.be.equal("No overdue tasks found");
10711023
});
10721024
});
1025+
1026+
describe("POST /tasks/migration", function () {
1027+
it("Should update status COMPLETED to DONE successful", async function () {
1028+
const taskData1 = { status: "COMPLETED" };
1029+
await firestore.collection("tasks").doc("updateTaskStatus1").set(taskData1);
1030+
const res = await chai.request(app).post("/tasks/migration").set("cookie", `${cookieName}=${superUserJwt}`);
1031+
expect(res).to.have.status(200);
1032+
expect(res.body.totalTasks).to.be.equal(1);
1033+
expect(res.body.totalUpdatedStatus).to.be.equal(1);
1034+
expect(res.body.updatedTaskDetails).to.deep.equal(["updateTaskStatus1"]);
1035+
expect(res.body.totalOperationsFailed).to.be.equal(0);
1036+
expect(res.body.failedTaskDetails).to.deep.equal([]);
1037+
});
1038+
1039+
it("Should not update if not found any COMPLETED task status ", async function () {
1040+
const res = await chai.request(app).post("/tasks/migration").set("cookie", `${cookieName}=${superUserJwt}`);
1041+
expect(res).to.have.status(200);
1042+
expect(res.body.totalTasks).to.be.equal(0);
1043+
expect(res.body.totalUpdatedStatus).to.be.equal(0);
1044+
expect(res.body.updatedTaskDetails).to.deep.equal([]);
1045+
expect(res.body.totalOperationsFailed).to.be.equal(0);
1046+
expect(res.body.failedTaskDetails).to.deep.equal([]);
1047+
});
1048+
1049+
it("should throw an error if firestore batch operations fail", async function () {
1050+
const stub = sinon.stub(firestore, "batch");
1051+
stub.returns({
1052+
update: function () {},
1053+
commit: function () {
1054+
throw new Error("Firestore batch commit failed!");
1055+
},
1056+
});
1057+
const taskData1 = { status: "COMPLETED" };
1058+
await firestore.collection("tasks").doc("updateTaskStatus1").set(taskData1);
1059+
const res = await chai.request(app).post("/tasks/migration").set("cookie", `${cookieName}=${superUserJwt}`);
1060+
expect(res.status).to.equal(500);
1061+
const response = res.body;
1062+
expect(response.message).to.be.equal("An internal server error occurred");
1063+
});
1064+
1065+
it("Should return 401 if not super_user", async function () {
1066+
const nonSuperUserId = await addUser(appOwner);
1067+
const nonSuperUserJwt = authService.generateAuthToken({ userId: nonSuperUserId });
1068+
const res = await chai.request(app).post("/tasks/migration").set("cookie", `${cookieName}=${nonSuperUserJwt}`);
1069+
expect(res).to.have.status(401);
1070+
});
1071+
});
10731072
});

0 commit comments

Comments
 (0)