-
Notifications
You must be signed in to change notification settings - Fork 273
feat: implement OOO approve/reject functionality #2462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 3 commits
a30d990
83d07c7
2a97501
e8a0693
040055f
49af584
47a6b98
bb74cdd
eb67111
308818b
8a9f257
ffd8abf
8773599
301c5ea
1a89944
debfebe
7a4cc24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,7 +1,7 @@ | ||||||
import joi from "joi"; | ||||||
import { NextFunction } from "express"; | ||||||
import { REQUEST_STATE, REQUEST_TYPE } from "../../constants/requests"; | ||||||
import { OooRequestCreateRequest, OooRequestResponse } from "../../types/oooRequest"; | ||||||
import { AcknowledgeOooRequest, OooRequestCreateRequest, OooRequestResponse } from "../../types/oooRequest"; | ||||||
|
||||||
export const createOooStatusRequestValidator = async ( | ||||||
req: OooRequestCreateRequest, | ||||||
|
@@ -38,3 +38,46 @@ export const createOooStatusRequestValidator = async ( | |||||
|
||||||
await schema.validateAsync(req.body, { abortEarly: false }); | ||||||
}; | ||||||
|
||||||
const schema = joi | ||||||
.object() | ||||||
.strict() | ||||||
.keys({ | ||||||
comment: joi.string().optional() | ||||||
.messages({ | ||||||
"string.empty": "comment cannot be empty", | ||||||
}), | ||||||
status: joi | ||||||
.string() | ||||||
.valid(REQUEST_STATE.APPROVED, REQUEST_STATE.REJECTED) | ||||||
.required() | ||||||
.messages({ | ||||||
"any.only": "status must be APPROVED or REJECTED", | ||||||
}), | ||||||
type: joi.string().equal(REQUEST_TYPE.OOO).required().messages({ | ||||||
"type.any": "type is required", | ||||||
}) | ||||||
RishiChaubey31 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
}); | ||||||
|
||||||
/** | ||||||
* Middleware to validate the acknowledge Out-Of-Office (OOO) request payload. | ||||||
* | ||||||
* @param {AcknowledgeOooRequest} req - The request object containing the body to be validated. | ||||||
* @param {OooRequestResponse} res - The response object used to send error responses if validation fails. | ||||||
* @param {NextFunction} next - The next middleware function to call if validation succeeds. | ||||||
* @returns {Promise<void>} Resolves or sends errors. | ||||||
*/ | ||||||
export const acknowledgeOooRequest = async ( | ||||||
req: AcknowledgeOooRequest, | ||||||
res: OooRequestResponse, | ||||||
next: NextFunction | ||||||
): Promise<void> => { | ||||||
try { | ||||||
await schema.validateAsync(req.body, { abortEarly: false }); | ||||||
next(); | ||||||
} catch (error) { | ||||||
const errorMessages = error.details.map((detail:{message: string}) => detail.message); | ||||||
|
const errorMessages = error.details.map((detail:{message: string}) => detail.message); | |
const errorMessages = error.details.map((detail) => detail.message); |
🤖 Prompt for AI Agents
In middlewares/validators/oooRequests.ts at line 79, replace the inline type
annotation for the map callback parameter with Joi's built-in
ValidationErrorItem type to improve type safety. Import ValidationErrorItem from
Joi and use it to type the detail parameter in the map function. This leverages
Joi's existing typings and ensures consistency and correctness.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
import firestore from "../utils/firestore"; | ||
const requestModel = firestore.collection("requests"); | ||
import { REQUEST_ALREADY_APPROVED, REQUEST_ALREADY_REJECTED, REQUEST_STATE } from "../constants/requests"; | ||
import { REQUEST_ALREADY_APPROVED, REQUEST_ALREADY_REJECTED, REQUEST_STATE, REQUEST_TYPE } from "../constants/requests"; | ||
import { | ||
ERROR_WHILE_FETCHING_REQUEST, | ||
ERROR_WHILE_CREATING_REQUEST, | ||
ERROR_WHILE_UPDATING_REQUEST, | ||
REQUEST_DOES_NOT_EXIST, | ||
} from "../constants/requests"; | ||
import { getUserId } from "../utils/users"; | ||
import { NotFound } from "http-errors"; | ||
import { fetchUser } from "./users"; | ||
RishiChaubey31 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
const SIZE = 5; | ||
|
||
export const createRequest = async (body: any) => { | ||
|
@@ -29,7 +31,7 @@ export const createRequest = async (body: any) => { | |
} | ||
}; | ||
|
||
export const updateRequest = async (id: string, body: any, lastModifiedBy: string, type:string) => { | ||
export const updateRequest = async (id: string, body: any, lastModifiedBy: string, type: string) => { | ||
try { | ||
const existingRequestDoc = await requestModel.doc(id).get(); | ||
if (!existingRequestDoc.exists) { | ||
|
@@ -69,6 +71,21 @@ export const updateRequest = async (id: string, body: any, lastModifiedBy: strin | |
} | ||
}; | ||
|
||
export const getRequestById = async (id: string) => { | ||
try { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please check with @Suvidh-kaushik what function he used for the impersonation feature to get request? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fetch by id was handled in a seperate model function |
||
const requestDoc = await requestModel.doc(id).get(); | ||
|
||
if (!requestDoc.exists) { | ||
throw new NotFound(REQUEST_DOES_NOT_EXIST); | ||
RishiChaubey31 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
return requestDoc.data(); | ||
} catch (error) { | ||
logger.error(ERROR_WHILE_FETCHING_REQUEST, error); | ||
throw error; | ||
} | ||
}; | ||
RishiChaubey31 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
export const getRequests = async (query: any) => { | ||
let { id, type, requestedBy, state, prev, next, page, size = SIZE } = query; | ||
const dev = query.dev === "true"; | ||
|
@@ -88,11 +105,10 @@ export const getRequests = async (query: any) => { | |
...requestDoc.data(), | ||
}; | ||
} | ||
RishiChaubey31 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if(requestedBy && dev){ | ||
|
||
if (requestedBy && dev) { | ||
requestQuery = requestQuery.where("requestedBy", "==", requestedBy); | ||
} | ||
else if (requestedBy) { | ||
} else if (requestedBy) { | ||
const requestedByUserId = await getUserId(requestedBy); | ||
requestQuery = requestQuery.where("requestedBy", "==", requestedByUserId); | ||
} | ||
|
@@ -149,6 +165,59 @@ export const getRequests = async (query: any) => { | |
return null; | ||
} | ||
|
||
// todo: remove this once previous OOO requests are removed form the database | ||
RishiChaubey31 marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// @ankush and @suraj had a discussion to manually update or remove the previous OOO requests | ||
if (type === REQUEST_TYPE.OOO) { | ||
const oooRequests = []; | ||
if (!dev) { | ||
for (const request of allRequests) { | ||
if (request.status) { | ||
const modifiedRequest = { | ||
id: request.id, | ||
type: request.type, | ||
from: request.from, | ||
until: request.until, | ||
message: request.reason, | ||
state: request.status, | ||
lastModifiedBy: request.lastModifiedBy ?? "", | ||
requestedBy: request.userId, | ||
reason: request.comment ?? "", | ||
createdAt: request.createdAt, | ||
updatedAt: request.updatedAt, | ||
}; | ||
oooRequests.push(modifiedRequest); | ||
} else { | ||
oooRequests.push(request); | ||
} | ||
} | ||
} else { | ||
for (const request of allRequests) { | ||
if (request.state) { | ||
const userResponse: any = await fetchUser({ userId: request.requestedBy }); | ||
const username = userResponse.user.username; | ||
RishiChaubey31 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
RishiChaubey31 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
const modifiedRequest = { | ||
id: request.id, | ||
type: request.type, | ||
from: request.from, | ||
until: request.until, | ||
RishiChaubey31 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
reason: request.message, | ||
status: request.state, | ||
lastModifiedBy: request.lastModifiedBy ?? null, | ||
requestedBy: username, | ||
RishiChaubey31 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
comment: request.reason ?? null, | ||
createdAt: request.createdAt, | ||
updatedAt: request.updatedAt, | ||
userId: request.requestedBy, | ||
}; | ||
oooRequests.push(modifiedRequest); | ||
} else { | ||
oooRequests.push(request); | ||
} | ||
} | ||
} | ||
allRequests = oooRequests; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please cross-check that we are sending the requestedBy userId. As per my understanding, when we created the OOO request earlier, we were storing the username in the DB, so there might be some bad data that could cause issues. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
} | ||
return { | ||
allRequests, | ||
prev: prevDoc.empty ? null : prevDoc.docs[0].id, | ||
|
@@ -190,4 +259,3 @@ export const getRequestByKeyValues = async (keyValues: KeyValues) => { | |
throw error; | ||
} | ||
}; | ||
|
Uh oh!
There was an error while loading. Please reload this page.