Repository: Real-Dev-Squad/website-backend
Pull request #2408: Refactor negligent tagging logic to exclude only OOO users
Author: login: pankajjs
Created: 2025-04-29T17:01:20Z | Merged: 2025-05-02T10:44:34Z

<!-- Date Here in dd mmm yyyy-->
Date: 29 April, 2025
<!--Developer Name Here-->
Developer Name: @pankajjs 

---

## Issue Ticket Number
- Closes #2390 
<!--Issue ticket this PR closes-->

## Description
 - This PR fixes a bug where negligent tag was not being applied on users who had status other than ```ACTIVE``` and their task's status were not ```Completed```, ```VERIFIED``` or ```Done```. Now, the changes will apply negligent tag to all users who have status other than ```OOO``` and their task's status is not ```Completed```, ```VERIFIED``` or ```Done```.
- The changes are not behind feature flag because cron job executes this API and there is no user or any service involvement directly for now.
- The changes also fixes the existing test-cases.
<!--Description of the changes made in this PR-->

### Documentation Updated?

- [ ] Yes
- [x] No

<!--Additional notes about documentation update if applicable-->

### Under Feature Flag

- [ ] Yes
- [x] No

<!--Indicate if changes are under a feature flag-->

### Database Changes

- [ ] Yes
- [x] No

<!--Notes on any database changes-->

### Breaking Changes

- [ ] Yes
- [x] No

<!--Notes on breaking changes or related issue tickets if applicable-->

### Development Tested?

- [x] Yes
- [ ] No

<!--Confirmation of local testing during development-->

## Screenshots
<details>
<summary>Working Video</summary>

https://github.com/user-attachments/assets/ccb6c9c9-273c-42fc-af8b-7afc899eaf08


https://github.com/user-attachments/assets/e73ad810-f151-4e1b-b7fc-003dd16cfa41


<!-- Attach your screenshots here👇-->

</details>

<!--Attach or link to relevant screenshots or visual aids-->

## Test Coverage
<details>
<summary>Screenshot</summary>
<img width="1238" alt="Screenshot 2025-05-01 at 6 53 36 PM" src="https://github.com/user-attachments/assets/1894a285-b4e5-4486-bac4-122127da8bdf" />
<img width="1206" alt="Screenshot 2025-05-01 at 6 54 07 PM" src="https://github.com/user-attachments/assets/c2849acc-60dd-4d9c-aa48-43ce7da13abc" />
<img width="989" alt="Screenshot 2025-05-01 at 6 54 16 PM" src="https://github.com/user-attachments/assets/40aa3021-2a7d-43f5-833a-6fed7294f019" />
<img width="1227" alt="Screenshot 2025-05-01 at 6 58 19 PM" src="https://github.com/user-attachments/assets/53d2251e-fe92-4aed-af0b-a30d051666fa" />
<img width="713" alt="Screenshot 2025-05-01 at 6 58 27 PM" src="https://github.com/user-attachments/assets/ba90d475-7fd1-44d0-960c-379078b92a1a" />
<img width="1024" alt="Screenshot 2025-04-29 at 9 48 42 PM" src="https://github.com/user-attachments/assets/9fd56768-7b95-4e4d-81f5-3e53f0f8443d" />


<!-- Attach your screenshots here👇-->

</details>

<!--Attach Details on test coverage and outcomes-->

## Additional Notes
- The reason for including `VERIFIED` status is because right now there is no way for developers to update their task status once it is marked as `VERIFIED`. In status-site, the dropdown doesn't appears which is a bug and only after it's fixed, logic will be modified to mark `VERIFIED` as negligent too.

<!--Any additional notes, considerations or explanations for reviewers-->


Linked issue #2390: Bug: Negligent Tag Not Applied to Users When Task Status Is "Approved"
### Issue Description
<!-- Provide a brief description of the issue here. -->
Users who change their task status to "Approved" do not receive the "Negligent" tag even if they miss updates for more than three days. Ideally, any task that is not marked as "Done" or "Complete" should result in the assignee receiving the "Negligent" tag if they fail to provide updates for three consecutive days.
### Expected Behavior
<!-- Describe what should happen when this issue is resolved. -->
- Any user whose task status is not "Done" or "Complete" should receive the "Negligent" tag if they miss their update for more than three days.

### Current Behavior
<!-- Explain what currently happens when this issue is encountered. -->
- Users with the "Approved" status are not getting the "Negligent" tag when they miss their updates for more than three days.

### Screenshots
<!-- If applicable, add screenshots or images that help illustrate the issue. You can use the following Markdown syntax to embed images: -->

### Reproducibility

 - [x] This issue is reproducible
 - [ ] This issue is not reproducible

### Steps to Reproduce
- Set a task status to "Approved."

- Do not update the task for more than three days.

- Observe that the task does not receive the "Negligent" tag.

### Screenshot


### Severity/Priority
 - [ ] Critical
 - [x] High
 - [ ] Medium
 - [ ] Low

### Additional Information
<!-- Include any additional context, logs, or details that might be helpful in addressing the issue. -->

### Checklist

- [x] I have read and followed the project's code of conduct.
- [x] I have searched for similar issues before creating this one.
- [x] I have provided all the necessary information to understand and reproduce the issue.
- [x] I am willing to contribute to the resolution of this issue.

<!-- 
Thank you for contributing to our project! We appreciate your help in improving it.
--
Linked issue comments: user: login: mridxl
created_at: 2025-03-29T11:26:18Z
body: Hey @yesyash, please assign this issue to me.
author_association: NONE
user: login: Hariom01010
created_at: 2025-04-19T20:42:04Z
body: can you please reassign this issue to me @AnujChhikara 
author_association: CONTRIBUTOR

Diff:
diff --git a/models/discordactions.js b/models/discordactions.js
index 3ba9ee658..dabff6f2c 100644
--- a/models/discordactions.js
+++ b/models/discordactions.js
@@ -1019,7 +1019,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
         usersMap.set(taskAssignee, {
           tasksCount: 1,
           latestProgressCount: dateGap + 1,
-          isActive: false,
+          isOOO: false,
         });
       }
       const updateTasksIdMap = async () => {
@@ -1038,10 +1038,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
     const userIdChunks = chunks(Array.from(usersMap.keys()), FIRESTORE_IN_CLAUSE_SIZE);
     const userStatusSnapshotPromise = userIdChunks.map(
       async (userIdList) =>
-        await userStatusModel
-          .where("currentStatus.state", "==", userState.ACTIVE)
-          .where("userId", "in", userIdList)
-          .get()
+        await userStatusModel.where("currentStatus.state", "==", userState.OOO).where("userId", "in", userIdList).get()
     );
     const userDetailsPromise = userIdChunks.map(
       async (userIdList) =>
@@ -1055,7 +1052,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
 
     userStatusChunks.forEach((userStatusList) =>
       userStatusList.forEach((doc) => {
-        usersMap.get(doc.data().userId).isActive = true;
+        usersMap.get(doc.data().userId).isOOO = true;
       })
     );
 
@@ -1097,7 +1094,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
       const isDiscordMember = !!discordUserData;
       const shouldAddRole =
         userData.latestProgressCount === 0 &&
-        userData.isActive &&
+        !userData.isOOO &&
         isDiscordMember &&
         discordUserData.isDeveloper &&
         !discordUserData.isMaven &&
diff --git a/test/integration/tasks.test.js b/test/integration/tasks.test.js
index 1d384337d..5d61d48f7 100644
--- a/test/integration/tasks.test.js
+++ b/test/integration/tasks.test.js
@@ -1813,39 +1813,45 @@ describe("Tasks", function () {
   });
 
   describe("GET /tasks/users", function () {
-    let activeUserWithProgressUpdates;
+    let activeUserWithMissedProgressUpdates;
     let idleUser;
     let userNotInDiscord;
     let jwtToken;
     let getDiscordMembersStub;
+    let oooUserWithMissedUpdates;
+    let activeUserWithProgressUpdates;
 
     beforeEach(async function () {
       await cleanDb();
       idleUser = { ...userData[9], discordId: getDiscordMembers[0].user.id };
-      activeUserWithProgressUpdates = { ...userData[10], discordId: getDiscordMembers[1].user.id };
-      const activeUserWithNoUpdates = { ...userData[0], discordId: getDiscordMembers[2].user.id };
+      activeUserWithMissedProgressUpdates = { ...userData[10], discordId: getDiscordMembers[1].user.id };
+      activeUserWithProgressUpdates = { ...userData[0], discordId: getDiscordMembers[2].user.id };
       userNotInDiscord = { ...userData[4], discordId: "Not in discord" };
+      oooUserWithMissedUpdates = { ...userData[1], discordId: getDiscordMembers[3].user.id };
+
       const {
         idleStatus: idleUserStatus,
         activeStatus: activeUserStatus,
         userStatusDataForOooState: oooUserStatus,
       } = userStatusData;
       const userIdList = await Promise.all([
-        await addUser(idleUser), // idle user with no task progress updates
-        await addUser(activeUserWithProgressUpdates), // active user with task progress updates
-        await addUser(activeUserWithNoUpdates), // active user with no task progress updates
-        await addUser(userNotInDiscord), // OOO user with
+        await addUser(idleUser),
+        await addUser(activeUserWithMissedProgressUpdates),
+        await addUser(activeUserWithProgressUpdates),
+        await addUser(userNotInDiscord),
+        await addUser(oooUserWithMissedUpdates),
       ]);
       await Promise.all([
         await userStatusModel.updateUserStatus(userIdList[0], idleUserStatus),
         await userStatusModel.updateUserStatus(userIdList[1], activeUserStatus),
         await userStatusModel.updateUserStatus(userIdList[2], activeUserStatus),
         await userStatusModel.updateUserStatus(userIdList[3], oooUserStatus),
+        await userStatusModel.updateUserStatus(userIdList[4], oooUserStatus),
       ]);
 
       const tasksPromise = [];
 
-      for (let index = 0; index < 4; index++) {
+      for (let index = 0; index < 5; index++) {
         const task = tasksData[index];
         const validTask = {
           ...task,
@@ -1889,14 +1895,15 @@ describe("Tasks", function () {
         .get("/tasks/users/discord")
         .query({ q: `status:${tasksUsersStatus.MISSED_UPDATES}` })
         .set("Authorization", `Bearer ${jwtToken}`);
-      expect(response.body).to.be.deep.equal({
-        message: "Discord details of users with status missed updates fetched successfully",
-        data: {
-          usersToAddRole: [activeUserWithProgressUpdates.discordId],
-          tasks: 4,
-          missedUpdatesTasks: 3,
-        },
-      });
+
+      expect(response.body.message).to.equal(
+        "Discord details of users with status missed updates fetched successfully"
+      );
+      expect(response.body.data.tasks).to.equal(5);
+      expect(response.body.data.missedUpdatesTasks).to.equal(4);
+      expect(response.body.data.usersToAddRole.includes(activeUserWithMissedProgressUpdates.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(idleUser.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(oooUserWithMissedUpdates.discordId)).to.equal(false);
       expect(response.status).to.be.equal(200);
     });
 
@@ -1905,7 +1912,7 @@ describe("Tasks", function () {
         .request(app)
         .get("/tasks/users/discord")
         .query({
-          size: 5,
+          size: 6,
           q: `status:${tasksUsersStatus.MISSED_UPDATES} -weekday:sun -weekday:mon -weekday:tue -weekday:wed -weekday:thu -weekday:fri -date:231423432 -days-count:4`,
         })
         .set("Authorization", `Bearer ${jwtToken}`);
@@ -1913,7 +1920,7 @@ describe("Tasks", function () {
         message: "Discord details of users with status missed updates fetched successfully",
         data: {
           usersToAddRole: [],
-          tasks: 4,
+          tasks: 5,
           missedUpdatesTasks: 0,
         },
       });
diff --git a/test/unit/models/discordactions.test.js b/test/unit/models/discordactions.test.js
index 1a21c6f61..a1a721fc1 100644
--- a/test/unit/models/discordactions.test.js
+++ b/test/unit/models/discordactions.test.js
@@ -685,15 +685,16 @@ describe("discordactions", function () {
   });
 
   describe("getMissedProgressUpdatesUsers", function () {
-    let activeUserWithProgressUpdates;
+    let activeUserWithMissedProgressUpdates;
     let idleUser;
     let userNotInDiscord;
     let activeUserId;
+    let activeUserWithProgressUpdates;
 
     beforeEach(async function () {
       idleUser = { ...userData[9], discordId: getDiscordMembers[0].user.id };
-      activeUserWithProgressUpdates = { ...userData[10], discordId: getDiscordMembers[1].user.id };
-      const activeUserWithNoUpdates = { ...userData[0], discordId: getDiscordMembers[2].user.id };
+      activeUserWithMissedProgressUpdates = { ...userData[10], discordId: getDiscordMembers[1].user.id };
+      activeUserWithProgressUpdates = { ...userData[0], discordId: getDiscordMembers[2].user.id };
       userNotInDiscord = { ...userData[4], discordId: "Not in discord" };
       const {
         idleStatus: idleUserStatus,
@@ -701,10 +702,10 @@ describe("discordactions", function () {
         userStatusDataForOooState: oooUserStatus,
       } = userStatusData;
       const userIdList = await Promise.all([
-        await addUser(idleUser), // idle user with no task progress updates
-        await addUser(activeUserWithProgressUpdates), // active user with task progress updates
-        await addUser(activeUserWithNoUpdates), // active user with no task progress updates
-        await addUser(userNotInDiscord), // OOO user with no task progress updates
+        await addUser(idleUser),
+        await addUser(activeUserWithMissedProgressUpdates),
+        await addUser(activeUserWithProgressUpdates),
+        await addUser(userNotInDiscord),
       ]);
       activeUserId = userIdList[2];
       await Promise.all([
@@ -751,17 +752,17 @@ describe("discordactions", function () {
     it("should list of users who missed updating progress", async function () {
       const result = await getMissedProgressUpdatesUsers();
       expect(result).to.be.an("object");
-      expect(result).to.be.deep.equal({
-        tasks: 4,
-        missedUpdatesTasks: 3,
-        usersToAddRole: [activeUserWithProgressUpdates.discordId],
-      });
+      expect(result.tasks).to.not.equal(undefined);
+      expect(result.tasks).to.equal(4);
+      expect(result.missedUpdatesTasks).to.not.equal(undefined);
+      expect(result.missedUpdatesTasks).to.equal(3);
+      expect(result.usersToAddRole.includes(activeUserWithMissedProgressUpdates.discordId)).to.equal(true);
+      expect(result.usersToAddRole.includes(idleUser.discordId)).to.equal(true);
     });
 
     it("should not list of users who are not active and who missed updating progress", async function () {
       const result = await getMissedProgressUpdatesUsers();
       expect(result).to.be.an("object");
-      expect(result.usersToAddRole).to.not.contain(idleUser.discordId);
       expect(result.usersToAddRole).to.not.contain(userNotInDiscord.discordId);
     });
 


Reviews:
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T18:20:25Z
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T18:20:32Z
user: login: AnujChhikara
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T05:45:44Z
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T13:44:16Z
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T14:08:58Z
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T14:09:16Z
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T14:10:36Z
user: login: AnujChhikara
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T18:09:47Z
user: login: MayankBansal12
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-01T18:55:01Z
user: login: Achintya-Chatterjee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T19:49:19Z
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T19:50:53Z
user: login: Achintya-Chatterjee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T20:10:29Z
user: login: pankajjs
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T20:12:37Z
user: login: Achintya-Chatterjee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-01T20:38:16Z
user: login: tejaskh3
body: Can you please verify are you ignoring "Verified" to check for negligent? If yes please change that logic
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-02T05:34:06Z
user: login: iamitprakash
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-02T10:44:09Z

Review comments:
diff_hunk: @@ -1889,14 +1889,15 @@ describe("Tasks", function () {
         .get("/tasks/users/discord")
         .query({ q: `status:${tasksUsersStatus.MISSED_UPDATES}` })
         .set("Authorization", `Bearer ${jwtToken}`);
-      expect(response.body).to.be.deep.equal({
-        message: "Discord details of users with status missed updates fetched successfully",
-        data: {
-          usersToAddRole: [activeUserWithProgressUpdates.discordId],
-          tasks: 4,
-          missedUpdatesTasks: 3,
-        },
-      });
+
+      expect(response.body.message).to.equal(
+        "Discord details of users with status missed updates fetched successfully"
+      );
+      expect(response.body.data.tasks).to.equal(4);
+      expect(response.body.data.missedUpdatesTasks).to.equal(3);
+      expect(response.body.data.usersToAddRole.includes(activeUserWithProgressUpdates.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(idleUser.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(userNotInDiscord.discordId)).to.equal(false);
path: test/integration/tasks.test.js
user: login: pankajjs
body: deep equal does not work because the order of element in ```usersToAddRole``` can't be determine for multiple users. Therefore, I have verified the response by comparing individual field.
created_at: 2025-04-29T18:20:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -751,17 +751,17 @@ describe("discordactions", function () {
     it("should list of users who missed updating progress", async function () {
       const result = await getMissedProgressUpdatesUsers();
       expect(result).to.be.an("object");
-      expect(result).to.be.deep.equal({
-        tasks: 4,
-        missedUpdatesTasks: 3,
-        usersToAddRole: [activeUserWithProgressUpdates.discordId],
-      });
+      expect(result.tasks).to.not.equal(undefined);
+      expect(result.tasks).to.equal(4);
+      expect(result.missedUpdatesTasks).to.not.equal(undefined);
+      expect(result.missedUpdatesTasks).to.equal(3);
+      expect(result.usersToAddRole.includes(activeUserWithProgressUpdates.discordId)).to.equal(true);
path: test/unit/models/discordactions.test.js
user: login: pankajjs
body: deep equal does not work because the order of element in ```usersToAddRole``` can't be determine for multiple users. Therefore, I have verified the response by comparing individual field.
created_at: 2025-04-29T18:20:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1038,10 +1038,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
     const userIdChunks = chunks(Array.from(usersMap.keys()), FIRESTORE_IN_CLAUSE_SIZE);
     const userStatusSnapshotPromise = userIdChunks.map(
       async (userIdList) =>
-        await userStatusModel
-          .where("currentStatus.state", "==", userState.ACTIVE)
-          .where("userId", "in", userIdList)
-          .get()
+        await userStatusModel.where("currentStatus.state", "!=", userState.OOO).where("userId", "in", userIdList).get()
path: models/discordactions.js
user: login: AnujChhikara
body: This works for now but might be a bit confusing down the line. The array you're updating doesn’t really return active users, but we’re still setting isActive based on it. That could throw someone off when reading the code.

Maybe we can just rename isActive to something like isOOO to match what’s actually happening. Makes the logic clearer and avoids confusion later.
created_at: 2025-04-30T05:43:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1889,14 +1889,15 @@ describe("Tasks", function () {
         .get("/tasks/users/discord")
         .query({ q: `status:${tasksUsersStatus.MISSED_UPDATES}` })
         .set("Authorization", `Bearer ${jwtToken}`);
-      expect(response.body).to.be.deep.equal({
-        message: "Discord details of users with status missed updates fetched successfully",
-        data: {
-          usersToAddRole: [activeUserWithProgressUpdates.discordId],
-          tasks: 4,
-          missedUpdatesTasks: 3,
-        },
-      });
+
+      expect(response.body.message).to.equal(
+        "Discord details of users with status missed updates fetched successfully"
+      );
+      expect(response.body.data.tasks).to.equal(4);
+      expect(response.body.data.missedUpdatesTasks).to.equal(3);
+      expect(response.body.data.usersToAddRole.includes(activeUserWithProgressUpdates.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(idleUser.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(userNotInDiscord.discordId)).to.equal(false);
path: test/integration/tasks.test.js
user: login: pankajjs
body: Note: initially it was returning only one user due to which deep equal was working.
created_at: 2025-05-01T13:44:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -751,17 +752,17 @@ describe("discordactions", function () {
     it("should list of users who missed updating progress", async function () {
       const result = await getMissedProgressUpdatesUsers();
       expect(result).to.be.an("object");
-      expect(result).to.be.deep.equal({
-        tasks: 4,
-        missedUpdatesTasks: 3,
-        usersToAddRole: [activeUserWithProgressUpdates.discordId],
-      });
path: test/unit/models/discordactions.test.js
user: login: pankajjs
body: deep equal does not work because the order of element in usersToAddRole can't be determine for multiple users. Therefore, I have verified the response by comparing individual field.
Note: initially it was returning only one user due to which deep equal was working.
created_at: 2025-05-01T14:08:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1889,14 +1895,15 @@ describe("Tasks", function () {
         .get("/tasks/users/discord")
         .query({ q: `status:${tasksUsersStatus.MISSED_UPDATES}` })
         .set("Authorization", `Bearer ${jwtToken}`);
-      expect(response.body).to.be.deep.equal({
-        message: "Discord details of users with status missed updates fetched successfully",
-        data: {
-          usersToAddRole: [activeUserWithProgressUpdates.discordId],
-          tasks: 4,
-          missedUpdatesTasks: 3,
-        },
-      });
+
+      expect(response.body.message).to.equal(
+        "Discord details of users with status missed updates fetched successfully"
+      );
+      expect(response.body.data.tasks).to.equal(5);
+      expect(response.body.data.missedUpdatesTasks).to.equal(4);
+      expect(response.body.data.usersToAddRole.includes(activeUserWithMissedProgressUpdates.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(idleUser.discordId)).to.equal(true);
+      expect(response.body.data.usersToAddRole.includes(oooUserWithMissedUpdates.discordId)).to.equal(false);
path: test/integration/tasks.test.js
user: login: pankajjs
body: deep equal does not work because the order of element in usersToAddRole can't be determine for multiple users. Therefore, I have verified the response by comparing individual field.
Note: initially it was returning only one user due to which deep equal was working.
created_at: 2025-05-01T14:09:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -751,17 +752,17 @@ describe("discordactions", function () {
     it("should list of users who missed updating progress", async function () {
       const result = await getMissedProgressUpdatesUsers();
       expect(result).to.be.an("object");
-      expect(result).to.be.deep.equal({
-        tasks: 4,
-        missedUpdatesTasks: 3,
-        usersToAddRole: [activeUserWithProgressUpdates.discordId],
-      });
+      expect(result.tasks).to.not.equal(undefined);
+      expect(result.tasks).to.equal(4);
+      expect(result.missedUpdatesTasks).to.not.equal(undefined);
+      expect(result.missedUpdatesTasks).to.equal(3);
+      expect(result.usersToAddRole.includes(activeUserWithMissedProgressUpdates.discordId)).to.equal(true);
+      expect(result.usersToAddRole.includes(idleUser.discordId)).to.equal(true);
     });
 
     it("should not list of users who are not active and who missed updating progress", async function () {
       const result = await getMissedProgressUpdatesUsers();
       expect(result).to.be.an("object");
-      expect(result.usersToAddRole).to.not.contain(idleUser.discordId);
path: test/unit/models/discordactions.test.js
user: login: pankajjs
body: After the fix, idle users will be getting negligent tag if their task status is not completed, done or verified.
created_at: 2025-05-01T14:10:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1038,10 +1038,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
     const userIdChunks = chunks(Array.from(usersMap.keys()), FIRESTORE_IN_CLAUSE_SIZE);
     const userStatusSnapshotPromise = userIdChunks.map(
       async (userIdList) =>
-        await userStatusModel
-          .where("currentStatus.state", "==", userState.ACTIVE)
-          .where("userId", "in", userIdList)
-          .get()
+        await userStatusModel.where("currentStatus.state", "==", userState.OOO).where("userId", "in", userIdList).get()
path: models/discordactions.js
user: login: Achintya-Chatterjee
body: Did you run the lint? When do you push the code?
created_at: 2025-05-01T19:49:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1038,10 +1038,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
     const userIdChunks = chunks(Array.from(usersMap.keys()), FIRESTORE_IN_CLAUSE_SIZE);
     const userStatusSnapshotPromise = userIdChunks.map(
       async (userIdList) =>
-        await userStatusModel
-          .where("currentStatus.state", "==", userState.ACTIVE)
-          .where("userId", "in", userIdList)
-          .get()
+        await userStatusModel.where("currentStatus.state", "==", userState.OOO).where("userId", "in", userIdList).get()
path: models/discordactions.js
user: login: pankajjs
body: I did. I wasn't able to commit.
created_at: 2025-05-01T19:50:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1038,10 +1038,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
     const userIdChunks = chunks(Array.from(usersMap.keys()), FIRESTORE_IN_CLAUSE_SIZE);
     const userStatusSnapshotPromise = userIdChunks.map(
       async (userIdList) =>
-        await userStatusModel
-          .where("currentStatus.state", "==", userState.ACTIVE)
-          .where("userId", "in", userIdList)
-          .get()
+        await userStatusModel.where("currentStatus.state", "==", userState.OOO).where("userId", "in", userIdList).get()
path: models/discordactions.js
user: login: Achintya-Chatterjee
body: Why is that?
created_at: 2025-05-01T19:54:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1038,10 +1038,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
     const userIdChunks = chunks(Array.from(usersMap.keys()), FIRESTORE_IN_CLAUSE_SIZE);
     const userStatusSnapshotPromise = userIdChunks.map(
       async (userIdList) =>
-        await userStatusModel
-          .where("currentStatus.state", "==", userState.ACTIVE)
-          .where("userId", "in", userIdList)
-          .get()
+        await userStatusModel.where("currentStatus.state", "==", userState.OOO).where("userId", "in", userIdList).get()
path: models/discordactions.js
user: login: pankajjs
body: No idea. I was commiting changes and it gave me lint error. So, I had to run lint-fix command.
created_at: 2025-05-01T20:12:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1038,10 +1038,7 @@ const getMissedProgressUpdatesUsers = async (options = {}) => {
     const userIdChunks = chunks(Array.from(usersMap.keys()), FIRESTORE_IN_CLAUSE_SIZE);
     const userStatusSnapshotPromise = userIdChunks.map(
       async (userIdList) =>
-        await userStatusModel
-          .where("currentStatus.state", "==", userState.ACTIVE)
-          .where("userId", "in", userIdList)
-          .get()
+        await userStatusModel.where("currentStatus.state", "==", userState.OOO).where("userId", "in", userIdList).get()
path: models/discordactions.js
user: login: Achintya-Chatterjee
body: okay
created_at: 2025-05-01T20:38:16Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-29T17:01:26Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto incremental reviews are disabled on this repository.
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Summary by CodeRabbit

- **Bug Fixes**
	- Improved the criteria for identifying users with missed progress updates by excluding only those marked as Out Of Office (OOO), ensuring more accurate user status handling.

- **Tests**
	- Updated test cases to reflect the new user status filtering logic and enhanced assertion clarity for users identified with missed progress updates.
## Walkthrough

The changes update the logic in the `getMissedProgressUpdatesUsers` function to broaden the set of user statuses considered for missed progress updates. Instead of only including users with the `ACTIVE` state, the function now includes all users except those marked as `OOO` (Out Of Office). Corresponding integration and unit tests have been updated to reflect this new behavior, ensuring that users with statuses other than `OOO` are now considered in the missed updates logic and role assignment.

## Changes

| File(s)                                      | Change Summary                                                                                                                         |
|-----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| models/discordactions.js                     | Modified the filtering logic in `getMissedProgressUpdatesUsers` to include all user statuses except `OOO` instead of only `ACTIVE`.    |
| test/integration/tasks.test.js                | Updated assertions for `/tasks/users/discord?status=MISSED_UPDATES` to check for inclusion/exclusion of users based on new logic.      |
| test/unit/models/discordactions.test.js       | Adjusted tests for `getMissedProgressUpdatesUsers` to match the broadened user status inclusion and updated assertion checks.          |

## Assessment against linked issues

| Objective                                                                                   | Addressed | Explanation                                                                                      |
|---------------------------------------------------------------------------------------------|-----------|--------------------------------------------------------------------------------------------------|
| Apply "Negligent" tag to users who miss updates for >3 days on any task not "Done"/"Complete" (#2390) | ✅        |                                                                                                  |

## Poem

> A hop and a skip, the logic expands,  
> Now more bunnies are caught by the code's gentle hands.  
> No longer just "ACTIVE," but all in the race,  
> Except those on break, in their cozy OOO space.  
> With tests all refreshed, the carrots align—  
> Negligence tagged, in burrows we shine!  
> 🐇✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Real-Dev-Squad/website-backend&utm_content=2408):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: MayankBansal12
created_at: 2025-05-01T14:07:51Z
body: Hi @pankajjs 
![Screenshot](https://github.com/user-attachments/assets/168e7e4a-1204-453e-adc8-0309b26a5e42)

Why are we considering `VERIFIED` status here? As per my knowledge, we need to only consider for `COMPLETED` / `DONE` status
author_association: MEMBER
user: login: pankajjs
created_at: 2025-05-01T14:12:04Z
body: > Why are we considering `VERIFIED` status here? As per my knowledge, we need to only consider for `COMPLETED` / `DONE`

This is the existing status of code, where we are considering verified status. So not changing it in this PR.
author_association: CONTRIBUTOR
user: login: MayankBansal12
created_at: 2025-05-01T14:13:19Z
body: > > Why are we considering `VERIFIED` status here? As per my knowledge, we need to only consider for `COMPLETED` / `DONE`
> 
> This is the existing status of code, where we are considering verified status. So not changing it in this PR.

The title however mentions only completed tasks contradicting the point, why not make the changes here?
author_association: MEMBER
user: login: pankajjs
created_at: 2025-05-01T14:16:46Z
body: > > > Why are we considering `VERIFIED` status here? As per my knowledge, we need to only consider for `COMPLETED` / `DONE`
> > 
> > 
> > This is the existing status of code, where we are considering verified status. So not changing it in this PR.
> 
> The title however mentions only completed tasks contradicting the point, why not make the changes here?

Fixed the title
author_association: CONTRIBUTOR
user: login: MayankBansal12
created_at: 2025-05-01T18:50:04Z
body: @pankajjs we don't need to put this bug fix under feature flag?
author_association: MEMBER
user: login: pankajjs
created_at: 2025-05-01T18:54:31Z
body: > @pankajjs we don't need to put this bug fix under feature flag?

The changes are not behind feature flag because cron job executes this API and there is no user or any service involvement directly for now.
author_association: CONTRIBUTOR
user: login: tejaskh3
created_at: 2025-05-02T05:30:35Z
body: Hey @pankajjs, In your PR you have mentioned "Now, the changes will apply negligent tag to all users who have status other than OOO and their task's status is not Completed, VERIFIED or Done." But we don't count "Verifed" as "Completed" or "Done"
author_association: CONTRIBUTOR
user: login: MayankBansal12
created_at: 2025-05-02T07:15:53Z
body: > Can you please verify are you ignoring "Verified" to check for negligent? If yes please change that logic

@tejaskh3 Please go through the additional notes. `VERIFIED` status has been ignored on purpose.
author_association: MEMBER