Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e356eb0
feat : adds function to reject task requests
Ajeyakrishna-k Nov 15, 2023
b7045ef
Merge remote-tracking branch 'origin/develop' into feat/reject-task-r…
Ajeyakrishna-k Nov 17, 2023
ab691c1
feat : adds tests and minor changes in validation
Ajeyakrishna-k Nov 17, 2023
e60da8e
chore : rename and add jsdoc for models function
Ajeyakrishna-k Nov 24, 2023
ad344d9
Merge remote-tracking branch 'origin/develop' into feat/reject-task-r…
Ajeyakrishna-k Nov 24, 2023
0fa0dfc
chore : update comment
Ajeyakrishna-k Nov 24, 2023
8685912
refactor: rename variables
Ajeyakrishna-k Nov 25, 2023
f0cd014
Merge branch 'develop' into feat/reject-task-requests
Ajeyakrishna-k Nov 25, 2023
55b1f52
feat: models function to fetch user discord id when they miss progres…
Ajeyakrishna-k Dec 5, 2023
b5b37c7
Merge remote-tracking branch 'origin/develop' into feat/missed-progre…
Ajeyakrishna-k Dec 5, 2023
c89a9fb
chore: lint fix
Ajeyakrishna-k Dec 5, 2023
410c03d
fix: failing tests
Ajeyakrishna-k Dec 5, 2023
7437a40
Merge branch 'develop' into feat/missed-progress-updates
Ajeyakrishna-k Dec 7, 2023
a244d76
chore: refactors and fix test
Ajeyakrishna-k Dec 7, 2023
4923499
Merge branch 'feat/missed-progress-updates' of https://github.com/Rea…
Ajeyakrishna-k Dec 7, 2023
6cbe27c
fix: failing tests
Ajeyakrishna-k Dec 7, 2023
8b28864
Merge branch 'develop' into feat/missed-progress-updates
Ajeyakrishna-k Dec 8, 2023
19b5ce5
feat: adds excluded days of week logic
Ajeyakrishna-k Dec 8, 2023
02bcdae
Merge branch 'feat/missed-progress-updates' of https://github.com/Rea…
Ajeyakrishna-k Dec 8, 2023
f7e4a9a
Merge branch 'develop' into feat/missed-progress-updates
Ajeyakrishna-k Dec 10, 2023
e4f3d30
fix: adds validation and improves comments
Ajeyakrishna-k Dec 10, 2023
3bc300d
Merge branch 'develop' into feat/missed-progress-updates
Ajeyakrishna-k Dec 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
discordUnverifiedRoleId: "<discordUnverifiedRoleId>",
discordDeveloperRoleId: "<discordDeveloperRoleId>",
discordMavenRoleId: "<discordMavenRoleId>",
discordMissedUpdatesRoleId: "discordMissedUpdatesRoleId",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to come from env?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No will add once it's generated.

githubApi: {
baseUrl: "https://api.github.com",
org: "Real-Dev-Squad",
Expand Down
15 changes: 14 additions & 1 deletion constants/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ const MAPPED_TASK_STATUS = {
UNASSIGNED: "AVAILABLE",
};

const COMPLETED_TASK_STATUS = {
VERIFIED: "VERIFIED",
DONE: "DONE",
COMPLETED: "COMPLETED",
};
const TASK_SIZE = 5;

module.exports = { TASK_TYPE, TASK_STATUS, TASK_STATUS_OLD, MAPPED_TASK_STATUS, TASK_SIZE, DEFAULT_TASK_PRIORITY };
module.exports = {
TASK_TYPE,
TASK_STATUS,
TASK_STATUS_OLD,
MAPPED_TASK_STATUS,
TASK_SIZE,
DEFAULT_TASK_PRIORITY,
COMPLETED_TASK_STATUS,
};
179 changes: 179 additions & 0 deletions models/discordactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@ const dataAccess = require("../services/dataAccessLayer");
const { getDiscordMembers, addRoleToUser, removeRoleFromUser } = require("../services/discordService");
const discordDeveloperRoleId = config.get("discordDeveloperRoleId");
const discordMavenRoleId = config.get("discordMavenRoleId");
const discordMissedUpdatesRoleId = config.get("discordMissedUpdatesRoleId");

const userStatusModel = firestore.collection("usersStatus");
const usersUtils = require("../utils/users");
const { getUsersBasedOnFilter, fetchUser } = require("./users");
const { convertDaysToMilliseconds } = require("../utils/time");
const { chunks } = require("../utils/array");
const tasksModel = firestore.collection("tasks");
const { FIRESTORE_IN_CLAUSE_SIZE } = require("../constants/users");
const discordService = require("../services/discordService");
const { buildTasksQueryForMissedUpdates } = require("../utils/tasks");
const { buildProgressQueryForMissedUpdates } = require("../utils/progresses");

/**
*
Expand Down Expand Up @@ -836,6 +845,175 @@ const updateUsersWith31DaysPlusOnboarding = async () => {
}
};

const getMissedProgressUpdatesUsers = async (options = {}) => {
const { cursor, size = 500, excludedDates = [], excludedDays = [0], dateGap = 3 } = options;
const stats = {
tasks: 0,
missedUpdatesTasks: 0,
};
try {
const discordUsersPromise = discordService.getDiscordMembers();
const missedUpdatesRoleId = discordMissedUpdatesRoleId;

let gapWindowStart = Date.now() - convertDaysToMilliseconds(dateGap);
const gapWindowEnd = Date.now();
excludedDates.forEach((timestamp) => {
if (timestamp > gapWindowStart && timestamp < gapWindowEnd) {
gapWindowStart -= convertDaysToMilliseconds(1);
}
});

if (excludedDays.length === 7) {
return { usersToAddRole: [], ...stats };
}

for (let i = gapWindowEnd; i >= gapWindowStart; i -= convertDaysToMilliseconds(1)) {
const day = new Date(i).getDay();
if (excludedDays.includes(day)) {
gapWindowStart -= convertDaysToMilliseconds(1);
}
}

let taskQuery = buildTasksQueryForMissedUpdates(gapWindowStart, size);

if (cursor) {
const data = await tasksModel.doc(cursor).get();
if (!data.data()) {
return {
statusCode: 400,
error: "Bad Request",
message: `Invalid cursor: ${cursor}`,
};
}
taskQuery = taskQuery.startAfter(data);
}

const usersMap = new Map();
const progressCountPromise = [];
const tasksQuerySnapshot = await taskQuery.get();

stats.tasks = tasksQuerySnapshot.size;
tasksQuerySnapshot.forEach((doc) => {
const taskAssignee = doc.data().assignee;
const taskId = doc.id;

if (usersMap.has(taskAssignee)) {
const userData = usersMap.get(taskAssignee);
userData.tasksCount++;
} else {
usersMap.set(taskAssignee, {
tasksCount: 1,
latestProgressCount: dateGap + 1,
isActive: false,
});
}
const updateTasksIdMap = async () => {
const progressQuery = buildProgressQueryForMissedUpdates(taskId, gapWindowStart, gapWindowEnd);
const progressSnapshot = await progressQuery.get();
const userData = usersMap.get(taskAssignee);
userData.latestProgressCount = Math.min(progressSnapshot.data().count, userData.latestProgressCount);

if (userData.latestProgressCount === 0) {
stats.missedUpdatesTasks++;
}
};
progressCountPromise.push(updateTasksIdMap());
});

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()
);
const userDetailsPromise = userIdChunks.map(
async (userIdList) =>
await userModel
.where("roles.archived", "==", false)
.where(admin.firestore.FieldPath.documentId(), "in", userIdList)
.get()
);

const userStatusChunks = await Promise.all(userStatusSnapshotPromise);

userStatusChunks.forEach((userStatusList) =>
userStatusList.forEach((doc) => {
usersMap.get(doc.data().userId).isActive = true;
})
);

const userDetailsListChunks = await Promise.all(userDetailsPromise);
userDetailsListChunks.forEach((userList) => {
userList.forEach((doc) => {
const userData = usersMap.get(doc.id);
userData.discordId = doc.data().discordId;
});
});

const discordUserList = await Promise.all(discordUsersPromise);

const discordUserMap = new Map();
discordUserList.forEach((discordUser) => {
const discordUserData = { isBot: !!discordUser.user.bot };
discordUser.roles.forEach((roleId) => {
switch (roleId) {
case discordDeveloperRoleId: {
discordUserData.isDeveloper = true;
break;
}
case discordMavenRoleId: {
discordUserData.isMaven = true;
break;
}
case missedUpdatesRoleId: {
discordUserData.hasMissedUpdatesRole = true;
break;
}
}
});
discordUserMap.set(discordUser.user.id, discordUserData);
});

await Promise.all(progressCountPromise);

for (const [userId, userData] of usersMap.entries()) {
const discordUserData = discordUserMap.get(userData.discordId);
const isDiscordMember = !!discordUserData;
const shouldAddRole =
userData.latestProgressCount === 0 &&
userData.isActive &&
isDiscordMember &&
discordUserData.isDeveloper &&
!discordUserData.isMaven &&
!discordUserData.isBot &&
!discordUserData.hasMissedUpdatesRole;

if (!shouldAddRole) {
usersMap.delete(userId);
}
}

const usersToAddRole = [];
for (const userData of usersMap.values()) {
usersToAddRole.push(userData.discordId);
}
const resultDataLength = tasksQuerySnapshot.docs.length;
const isLast = size && resultDataLength === size;
const lastVisible = isLast && tasksQuerySnapshot.docs[resultDataLength - 1];

if (lastVisible) {
stats.cursor = lastVisible.id;
}

return { usersToAddRole, ...stats };
} catch (err) {
logger.error("Error while running the add missed roles script", err);
throw err;
}
};

const addInviteToInviteModel = async (inviteObject) => {
try {
const invite = await discordInvitesModel.add(inviteObject);
Expand Down Expand Up @@ -878,6 +1056,7 @@ module.exports = {
updateUsersNicknameStatus,
updateIdle7dUsersOnDiscord,
updateUsersWith31DaysPlusOnboarding,
getMissedProgressUpdatesUsers,
getUserDiscordInvite,
addInviteToInviteModel,
};
1 change: 0 additions & 1 deletion test/integration/taskRequests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,6 @@ describe("Task Requests", function () {
});
});
});

describe("POST /taskRequests", function () {
let fetchIssuesByIdStub;
let fetchTaskStub;
Expand Down
Loading