Skip to content

Commit

Permalink
Allow multiple extension request (#1563)
Browse files Browse the repository at this point in the history
* allow multiple extension request

* lint fix

* lint fix

* remove appowner from multiple extension test file

* refactor code

* refactor-controller

* replace userId with assigneeId

* move tasks data to fixture

* fix responses and test cases
  • Loading branch information
MayurLund authored Oct 14, 2023
1 parent 2e11076 commit 1293578
Show file tree
Hide file tree
Showing 5 changed files with 634 additions and 69 deletions.
239 changes: 175 additions & 64 deletions controllers/extensionRequests.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,73 +14,156 @@ const { parseQueryParams } = require("../utils/queryParser");
* @param res {Object} - Express response object
*/
const createTaskExtensionRequest = async (req, res) => {
try {
const extensionBody = req.body;

let assigneeUsername = await getUsernameElseUndefined(extensionBody.assignee);
let assigneeId = extensionBody.assignee;
if (!assigneeUsername) {
assigneeId = await getUserIdElseUndefined(extensionBody.assignee);
assigneeUsername = extensionBody.assignee;
extensionBody.assignee = assigneeId;
}
const dev = req.query.dev === "true";
if (dev) {
try {
let extensionBody = req.body;

if (!assigneeId) {
return res.boom.badRequest("User with this id or username doesn't exist.");
}
let assigneeUsername = await getUsernameElseUndefined(extensionBody.assignee);
let assigneeId = extensionBody.assignee;
if (!assigneeUsername) {
assigneeId = await getUserIdElseUndefined(extensionBody.assignee);
assigneeUsername = extensionBody.assignee;
extensionBody.assignee = assigneeId;
}

if (req.userData.id !== extensionBody.assignee && !req.userData.roles?.super_user) {
return res.boom.forbidden("Only assigned user and super user can create an extension request for this task.");
}
if (!assigneeId) {
return res.boom.badRequest("User Not Found");
}

const { taskData: task } = await tasks.fetchTask(extensionBody.taskId);
if (!task) {
return res.boom.badRequest("Task with this id or taskid doesn't exist.");
}
if (task.assignee !== assigneeUsername) {
return res.boom.badRequest("This task is assigned to some different user");
}
if (task.endsOn >= extensionBody.newEndsOn) {
return res.boom.badRequest("The value for newEndsOn should be greater than the previous ETA");
}
if (extensionBody.oldEndsOn !== task.endsOn) {
extensionBody.oldEndsOn = task.endsOn;
}
if (req.userData.id !== extensionBody.assignee && !req.userData.roles?.super_user) {
return res.boom.forbidden("Only assigned user and super user can create an extension request for this task.");
}

const prevExtensionRequest = await extensionRequestsQuery.fetchExtensionRequests({
taskId: extensionBody.taskId,
assignee: extensionBody.assignee,
});
if (prevExtensionRequest.length) {
return res.boom.forbidden("An extension request for this task already exists.");
const { taskData: task } = await tasks.fetchTask(extensionBody.taskId);
if (!task) {
return res.boom.badRequest("Task Not Found");
}
if (task.assignee !== assigneeUsername) {
return res.boom.badRequest("This task is assigned to some different user.");
}
if (task.endsOn >= extensionBody.newEndsOn) {
return res.boom.badRequest("New ETA must be greater than Old ETA");
}
if (extensionBody.oldEndsOn !== task.endsOn) {
extensionBody.oldEndsOn = task.endsOn;
}

const latestExtensionRequest = await extensionRequestsQuery.fetchLatestExtensionRequest({
taskId: extensionBody.taskId,
});

if (latestExtensionRequest && latestExtensionRequest.status === EXTENSION_REQUEST_STATUS.PENDING) {
return res.boom.badRequest("An extension request for this task already exists.");
}

let requestNumber;
if (latestExtensionRequest && latestExtensionRequest.assigneeId === assigneeId) {
if (latestExtensionRequest.requestNumber && latestExtensionRequest.requestNumber > 0) {
requestNumber = latestExtensionRequest.requestNumber + 1;
extensionBody = { ...extensionBody, requestNumber };
} else {
extensionBody = { ...extensionBody, requestNumber: 2 };
}
} else {
extensionBody = { ...extensionBody, requestNumber: 1 };
}

const extensionRequest = await extensionRequestsQuery.createExtensionRequest(extensionBody);
const extensionLog = {
type: "extensionRequests",
meta: {
taskId: extensionBody.taskId,
createdBy: req.userData.id,
},
body: {
extensionRequestId: extensionRequest.id,
oldEndsOn: task.endsOn,
newEndsOn: extensionBody.newEndsOn,
assignee: extensionBody.assignee,
status: EXTENSION_REQUEST_STATUS.PENDING,
},
};

await addLog(extensionLog.type, extensionLog.meta, extensionLog.body);

return res.json({
message: "Extension Request created successfully!",
extensionRequest: { ...extensionBody, id: extensionRequest.id },
});
} catch (err) {
logger.error(`Error while creating new extension request: ${err}`);
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
}
} else {
try {
const extensionBody = req.body;

const extensionRequest = await extensionRequestsQuery.createExtensionRequest(extensionBody);
let assigneeUsername = await getUsernameElseUndefined(extensionBody.assignee);
let assigneeId = extensionBody.assignee;
if (!assigneeUsername) {
assigneeId = await getUserIdElseUndefined(extensionBody.assignee);
assigneeUsername = extensionBody.assignee;
extensionBody.assignee = assigneeId;
}

const extensionLog = {
type: "extensionRequests",
meta: {
if (!assigneeId) {
return res.boom.badRequest("User with this id or username doesn't exist.");
}

if (req.userData.id !== extensionBody.assignee && !req.userData.roles?.super_user) {
return res.boom.forbidden("Only assigned user and super user can create an extension request for this task.");
}

const { taskData: task } = await tasks.fetchTask(extensionBody.taskId);
if (!task) {
return res.boom.badRequest("Task with this id or taskid doesn't exist.");
}
if (task.assignee !== assigneeUsername) {
return res.boom.badRequest("This task is assigned to some different user");
}
if (task.endsOn >= extensionBody.newEndsOn) {
return res.boom.badRequest("The value for newEndsOn should be greater than the previous ETA");
}
if (extensionBody.oldEndsOn !== task.endsOn) {
extensionBody.oldEndsOn = task.endsOn;
}

const prevExtensionRequest = await extensionRequestsQuery.fetchExtensionRequests({
taskId: extensionBody.taskId,
createdBy: req.userData.id,
},
body: {
extensionRequestId: extensionRequest.id,
oldEndsOn: task.endsOn,
newEndsOn: extensionBody.newEndsOn,
assignee: extensionBody.assignee,
status: EXTENSION_REQUEST_STATUS.PENDING,
},
};
});
if (prevExtensionRequest.length) {
return res.boom.forbidden("An extension request for this task already exists.");
}

await addLog(extensionLog.type, extensionLog.meta, extensionLog.body);
const extensionRequest = await extensionRequestsQuery.createExtensionRequest(extensionBody);

return res.json({
message: "Extension Request created successfully!",
extensionRequest: { ...extensionBody, id: extensionRequest.id },
});
} catch (err) {
logger.error(`Error while creating new extension request: ${err}`);
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
const extensionLog = {
type: "extensionRequests",
meta: {
taskId: extensionBody.taskId,
createdBy: req.userData.id,
},
body: {
extensionRequestId: extensionRequest.id,
oldEndsOn: task.endsOn,
newEndsOn: extensionBody.newEndsOn,
assignee: extensionBody.assignee,
status: EXTENSION_REQUEST_STATUS.PENDING,
},
};

await addLog(extensionLog.type, extensionLog.meta, extensionLog.body);

return res.json({
message: "Extension Request created successfully!",
extensionRequest: { ...extensionBody, id: extensionRequest.id },
});
} catch (err) {
logger.error(`Error while creating new extension request: ${err}`);
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
}
}
};

Expand Down Expand Up @@ -132,19 +215,47 @@ const getExtensionRequest = async (req, res) => {
* @param res {Object} - Express response object
*/
const getSelfExtensionRequests = async (req, res) => {
const dev = req.query.dev === "true";

try {
const { id: userId } = req.userData;
const { taskId, status } = req.query;

if (userId) {
const allExtensionRequests = await extensionRequestsQuery.fetchExtensionRequests({
status,
taskId,
assignee: userId,
});
return res.json({ message: "Extension Requests returned successfully!", allExtensionRequests });
if (dev) {
if (userId) {
let allExtensionRequests;
if (taskId) {
const latestExtensionRequest = await extensionRequestsQuery.fetchLatestExtensionRequest({
taskId,
});

if (latestExtensionRequest && latestExtensionRequest.assigneeId !== userId) {
allExtensionRequests = [];
} else {
allExtensionRequests = [latestExtensionRequest];
}
} else {
allExtensionRequests = await extensionRequestsQuery.fetchExtensionRequests({
assignee: userId,
status: status || undefined,
});
}
return res.json({ message: "Extension Requests returned successfully!", allExtensionRequests });
} else {
return res.boom.notFound("User doesn't exist");
}
} else {
if (userId) {
const allExtensionRequests = await extensionRequestsQuery.fetchExtensionRequests({
taskId,
assignee: userId,
status: status || undefined,
});
return res.json({ message: "Extension Requests returned successfully!", allExtensionRequests });
} else {
return res.boom.notFound("User doesn't exist");
}
}
return res.boom.notFound("User doesn't exist");
} catch (error) {
logger.error(`Error while fetching extension requests: ${error}`);
return res.boom.badImplementation(INTERNAL_SERVER_ERROR);
Expand Down
24 changes: 24 additions & 0 deletions models/extensionRequests.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,34 @@ const fetchExtensionRequest = async (extensionRequestId) => {
}
};

const fetchLatestExtensionRequest = async (ExtensionRequestQuery) => {
try {
let extensionRequestsSnapshot = extensionRequestsModel;
Object.entries(ExtensionRequestQuery).forEach(([key, value]) => {
if (value) {
extensionRequestsSnapshot = extensionRequestsSnapshot.where(key, "==", value);
}
});
const extensionRequestSnapshot = await extensionRequestsSnapshot.orderBy("timestamp", "desc").limit(1).get();

if (extensionRequestSnapshot.size === 0) {
return [];
}

const request = buildExtensionRequests(extensionRequestSnapshot);
const updatedRequests = await formatExtensionRequest(request[0]);
return updatedRequests;
} catch (err) {
logger.error("error getting extension requests", err);
throw err;
}
};

module.exports = {
createExtensionRequest,
fetchExtensionRequests,
fetchExtensionRequest,
updateExtensionRequest,
fetchPaginatedExtensionRequests,
fetchLatestExtensionRequest,
};
60 changes: 60 additions & 0 deletions test/fixtures/tasks/multiple-extension-requests-tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const userData = require("../../fixtures/user/user")();
const { DINERO, NEELAM } = require("../../../constants/wallets");
const user = userData[5];
const appOwner = userData[3];
module.exports = () => {
return [
{
title: "Test task 1",
type: "feature",
endsOn: 1234,
startedOn: 4567,
status: "active",
percentCompleted: 10,
assignee: user.username,
isNoteworthy: true,
completionAward: { [DINERO]: 3, [NEELAM]: 300 },
lossRate: { [DINERO]: 1 },
},
{
title: "Test task 2",
type: "feature",
endsOn: 1234,
startedOn: 4567,
status: "active",
percentCompleted: 10,
assignee: user.username,
isNoteworthy: true,
completionAward: { [DINERO]: 3, [NEELAM]: 300 },
lossRate: { [DINERO]: 1 },
},
{
title: "Test task 3",
purpose: "To Test mocha",
featureUrl: "<testUrl>",
type: "group",
links: ["test1"],
endsOn: 1234,
startedOn: 54321,
status: "active",
percentCompleted: 10,
dependsOn: ["d12", "d23"],
isNoteworthy: false,
assignee: appOwner.username,
completionAward: { [DINERO]: 3, [NEELAM]: 300 },
lossRate: { [DINERO]: 1 },
},
{
title: "Test task 4",
type: "feature",
endsOn: 1234,
startedOn: 4567,
status: "active",
percentCompleted: 10,
assignee: appOwner.username,
isNoteworthy: true,
completionAward: { [DINERO]: 3, [NEELAM]: 300 },
lossRate: { [DINERO]: 1 },
},
];
};
Loading

0 comments on commit 1293578

Please sign in to comment.