Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…ackend into BUG-2340/logs-query
  • Loading branch information
vinit717 committed Jan 17, 2025
2 parents 7b90e76 + 900ee7d commit 49a3e1b
Show file tree
Hide file tree
Showing 8 changed files with 388 additions and 100 deletions.
86 changes: 82 additions & 4 deletions controllers/onboardingExtension.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import {
ERROR_WHILE_CREATING_REQUEST,
ERROR_WHILE_UPDATING_REQUEST,
LOG_ACTION,
ONBOARDING_REQUEST_CREATED_SUCCESSFULLY,
REQUEST_ALREADY_PENDING,
REQUEST_APPROVED_SUCCESSFULLY,
REQUEST_DOES_NOT_EXIST,
REQUEST_LOG_TYPE,
REQUEST_REJECTED_SUCCESSFULLY,
REQUEST_STATE,
REQUEST_TYPE,
UNAUTHORIZED_TO_CREATE_ONBOARDING_EXTENSION_REQUEST,
} from "../constants/requests";
import { userState } from "../constants/userStatus";
import { addLog } from "../services/logService";
import { createRequest, getRequestByKeyValues } from "../models/requests";
import { createRequest, getRequestByKeyValues, updateRequest } from "../models/requests";
import { fetchUser } from "../models/users";
import { getUserStatus } from "../models/userStatus";
import { User } from "../typeDefinitions/users";
import {
CreateOnboardingExtensionBody,
OnboardingExtension,
OnboardingExtensionCreateRequest,
OnboardingExtensionResponse
OnboardingExtensionResponse,
UpdateOnboardingExtensionStateRequest,
UpdateOnboardingExtensionStateRequestBody
} from "../types/onboardingExtension";
import { convertDateStringToMilliseconds, getNewDeadline } from "../utils/requests";
import { convertDaysToMilliseconds } from "../utils/time";
Expand All @@ -34,7 +40,11 @@ import { convertDaysToMilliseconds } from "../utils/time";
* @param {OnboardingExtensionResponse} res - The Express response object used to send back the response.
* @returns {Promise<OnboardingExtensionResponse>} Resolves to a response with the status and data or an error message.
*/
export const createOnboardingExtensionRequestController = async (req: OnboardingExtensionCreateRequest, res: OnboardingExtensionResponse): Promise<OnboardingExtensionResponse> => {
export const createOnboardingExtensionRequestController = async (
req: OnboardingExtensionCreateRequest,
res: OnboardingExtensionResponse )
: Promise<OnboardingExtensionResponse> => {

try {

const data = req.body as CreateOnboardingExtensionBody;
Expand Down Expand Up @@ -121,4 +131,72 @@ export const createOnboardingExtensionRequestController = async (req: Onboarding
logger.error(ERROR_WHILE_CREATING_REQUEST, err);
return res.boom.badImplementation(ERROR_WHILE_CREATING_REQUEST);
}
};
};

/**
* Updates the state of an onboarding extension request.
*
* @param {UpdateOnboardingExtensionStateRequest} req - The request object containing the update details.
* @param {OnboardingExtensionResponse} res - The response object to send the result of the update.
* @returns {Promise<OnboardingExtensionResponse>} Sends the response with the result of the update operation.
*/
export const updateOnboardingExtensionRequestState = async (
req: UpdateOnboardingExtensionStateRequest,
res: OnboardingExtensionResponse )
: Promise<OnboardingExtensionResponse> => {

const dev = req.query.dev === "true";

if(!dev) return res.boom.notImplemented("Feature not implemented");

const body = req.body as UpdateOnboardingExtensionStateRequestBody;
const lastModifiedBy = req?.userData?.id;
const extensionId = req.params.id;

let requestBody: UpdateOnboardingExtensionStateRequestBody = {
state: body.state,
type: body.type,
}

if(body.message){
requestBody = { ...requestBody, message: body.message };
}

try {
const response = await updateRequest(extensionId, requestBody, lastModifiedBy, REQUEST_TYPE.ONBOARDING);

if ("error" in response) {
if (response.error === REQUEST_DOES_NOT_EXIST) {
return res.boom.notFound(response.error);
}
return res.boom.badRequest(response.error);
}

const [logType, returnMessage] = response.state === REQUEST_STATE.APPROVED
? [REQUEST_LOG_TYPE.REQUEST_APPROVED, REQUEST_APPROVED_SUCCESSFULLY]
: [REQUEST_LOG_TYPE.REQUEST_REJECTED, REQUEST_REJECTED_SUCCESSFULLY];

const requestLog = {
type: logType,
meta: {
requestId: extensionId,
action: LOG_ACTION.UPDATE,
createdBy: lastModifiedBy,
},
body: response,
};

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

return res.status(200).json({
message: returnMessage,
data: {
id: response.id,
...response,
},
});
}catch(error){
logger.error(ERROR_WHILE_UPDATING_REQUEST, error);
return res.boom.badImplementation(ERROR_WHILE_UPDATING_REQUEST);
}
}
6 changes: 4 additions & 2 deletions controllers/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { createTaskExtensionRequest, updateTaskExtensionRequest } from "./extens
import { UpdateRequest } from "../types/requests";
import { TaskRequestRequest } from "../types/taskRequests";
import { createTaskRequestController } from "./taskRequestsv2";
import { OnboardingExtensionCreateRequest, OnboardingExtensionResponse } from "../types/onboardingExtension";
import { createOnboardingExtensionRequestController } from "./onboardingExtension";
import { OnboardingExtensionCreateRequest, OnboardingExtensionResponse, UpdateOnboardingExtensionStateRequest } from "../types/onboardingExtension";
import { createOnboardingExtensionRequestController, updateOnboardingExtensionRequestState } from "./onboardingExtension";

export const createRequestController = async (
req: OooRequestCreateRequest | ExtensionRequestRequest | TaskRequestRequest | OnboardingExtensionCreateRequest,
Expand Down Expand Up @@ -42,6 +42,8 @@ export const updateRequestController = async (req: UpdateRequest, res: CustomRes
return await updateOooRequestController(req as UpdateRequest, res as ExtensionRequestResponse);
case REQUEST_TYPE.EXTENSION:
return await updateTaskExtensionRequest(req as UpdateRequest, res as ExtensionRequestResponse);
case REQUEST_TYPE.ONBOARDING:
return await updateOnboardingExtensionRequestState(req as unknown as UpdateOnboardingExtensionStateRequest, res as OnboardingExtensionResponse);
default:
return res.boom.badRequest("Invalid request type");
}
Expand Down
3 changes: 2 additions & 1 deletion middlewares/validators/requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ export const updateRequestsMiddleware = async (
.messages({
"any.only": "state must be APPROVED or REJECTED",
}),
type: joi.string().valid(REQUEST_TYPE.OOO, REQUEST_TYPE.EXTENSION).required(),
type: joi.string().valid(REQUEST_TYPE.OOO, REQUEST_TYPE.EXTENSION, REQUEST_TYPE.ONBOARDING).required(),
message: joi.string().optional()
});

try {
Expand Down
138 changes: 53 additions & 85 deletions models/taskRequests.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const { RQLQueryParser } = require("../utils/RQLParser");
const firestore = require("../utils/firestore");
const { buildTaskRequests, generateLink, transformTaskRequests } = require("../utils/task-requests");
const { getCurrentEpochTime } = require("../utils/time");
const { convertMillisToSeconds } = require("../utils/time");
const taskRequestsCollection = firestore.collection("taskRequests");
const tasksModel = require("./tasks");
const userModel = require("./users");
Expand Down Expand Up @@ -399,94 +400,61 @@ const approveTaskRequest = async (taskRequestId, user, authorUserId) => {
) {
return { isTaskRequestInvalid: true };
}
if (taskRequestData.requestType === TASK_REQUEST_TYPE.CREATION) {
// TODO : extract the common code after the migration of the task request model. https://github.com/Real-Dev-Squad/website-backend/issues/1613
let userRequestData;
taskRequestData.users.forEach((userElement) => {
if (userElement.userId === user.id) {
userElement.status = TASK_REQUEST_STATUS.APPROVED;
userRequestData = userElement;
}
});
const updatedTaskRequest = {
users: taskRequestData.users,
approvedTo: user.id,
status: TASK_REQUEST_STATUS.APPROVED,
lastModifiedBy: authorUserId,
lastModifiedAt: Date.now(),
};
// End of TODO
const updateTaskRequestPromise = transaction.update(taskRequestDocRef, updatedTaskRequest);
const currentEpochTime = getCurrentEpochTime();
const newTaskRequestData = {
assignee: user.id,
title: taskRequestData.taskTitle,
type: TASK_TYPE.FEATURE,
percentCompleted: 0,
status: TASK_STATUS.ASSIGNED,
priority: DEFAULT_TASK_PRIORITY,
createdAt: currentEpochTime,
updatedAt: currentEpochTime,
startedOn: userRequestData.proposedStartDate / 1000,
endsOn: userRequestData.proposedDeadline / 1000,
github: {
issue: {
url: taskRequestData.externalIssueUrl,
html_url: taskRequestData.externalIssueHtmlUrl,
},
},
};
const newTaskDocRef = tasksCollection.doc();
const addTaskPromise = transaction.set(newTaskDocRef, newTaskRequestData);
await Promise.all([updateTaskRequestPromise, addTaskPromise]);
return {
approvedTo: user.username,
taskRequest: {
...updatedTaskRequest,
taskId: newTaskDocRef.id,
},
};
} else {
// TODO : extract the common code and remove the unnecessary if-condition after the migration of the task request model. https://github.com/Real-Dev-Squad/website-backend/issues/1613
const updatedTaskRequest = {
approvedTo: user.id,
status: TASK_REQUEST_STATUS.APPROVED,
lastModifiedBy: authorUserId,
lastModifiedAt: Date.now(),
};
let userRequestData;
if (taskRequestData.users) {
taskRequestData.users.forEach((userElement) => {
if (userElement.userId === user.id) {
userElement.status = TASK_REQUEST_STATUS.APPROVED;
userRequestData = userElement;
}
});
updatedTaskRequest.users = taskRequestData.users;
}
// End of TODO
const updateTaskRequestPromise = transaction.update(taskRequestDocRef, updatedTaskRequest);
const updatedTaskData = { assignee: user.id, status: TASK_STATUS.ASSIGNED, updatedAt: getCurrentEpochTime() };
// TODO : remove the unnecessary if-condition after the migration of the task request model. https://github.com/Real-Dev-Squad/website-backend/issues/1613
if (userRequestData) {
updatedTaskData.startedOn = userRequestData.proposedStartDate / 1000;
updatedTaskData.endsOn = userRequestData.proposedDeadline / 1000;
}
// End of TODO
const oldTaskDocRef = tasksCollection.doc(taskRequestData.taskId);
const updateTaskPromise = transaction.update(oldTaskDocRef, updatedTaskData);
await Promise.all([updateTaskRequestPromise, updateTaskPromise]);
return {
approvedTo: user.username,
taskRequest: {
...updatedTaskRequest,
taskId: oldTaskDocRef.id,
},
};

let userRequestData;
if (taskRequestData.users) {
userRequestData = taskRequestData.users.find((userElement) => userElement.userId === user.id);
if (userRequestData) userRequestData.status = TASK_REQUEST_STATUS.APPROVED;
}

const updatedTaskRequest = {
users: taskRequestData.users,
approvedTo: user.id,
status: TASK_REQUEST_STATUS.APPROVED,
lastModifiedBy: authorUserId,
lastModifiedAt: Date.now(),
};

const currentEpochTime = getCurrentEpochTime();
const newTaskRequestData = {
assignee: user.id,
title: taskRequestData.taskTitle,
type: TASK_TYPE.FEATURE,
percentCompleted: 0,
status: TASK_STATUS.ASSIGNED,
priority: DEFAULT_TASK_PRIORITY,
createdAt: currentEpochTime,
updatedAt: currentEpochTime,
startedOn: convertMillisToSeconds(userRequestData?.createdAt || Date.now()),
endsOn: convertMillisToSeconds(userRequestData?.proposedDeadline || Date.now()),
github: {
issue: {
url: taskRequestData.externalIssueUrl,
html_url: taskRequestData.externalIssueHtmlUrl,
},
},
};

const newTaskDocRef = tasksCollection.doc();
const updateTaskRequestPromise = transaction.update(taskRequestDocRef, updatedTaskRequest);
const addTaskPromise = transaction.set(newTaskDocRef, newTaskRequestData);

await Promise.all([updateTaskRequestPromise, addTaskPromise]);

return {
approvedTo: user.username,
taskRequest: {
...updatedTaskRequest,
taskId: newTaskDocRef.id,
},
};
});
} catch (err) {
logger.error("Error in approving task", err);
logger.error("Error in approving task", err, {
taskRequestId,
user,
errorDetails: err.message,
});
throw err;
}
};
Expand Down
Loading

0 comments on commit 49a3e1b

Please sign in to comment.