-
Notifications
You must be signed in to change notification settings - Fork 56
feat(PM-1173): Notify all copilots on copilot opportunity #815
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
Conversation
@@ -52,6 +53,12 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) | |||
.then((opportunity) => { | |||
console.log(opportunity); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid using console.log
for debugging in production code. Consider using a logging library to handle logs appropriately.
.then((opportunity) => { | ||
console.log(opportunity); | ||
const roles = util.getRolesByRoleName('copilot'); | ||
console.log(roles, 'roles by copilot'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove console.log
statements before merging to ensure cleaner code and avoid exposing potentially sensitive information.
@@ -815,6 +815,27 @@ const projectServiceUtils = { | |||
} | |||
}, | |||
|
|||
getRolesByRoleName: Promise.coroutine(function* (roleName, logger, requestId) { // eslint-disable-line func-names |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using async/await instead of Promise.coroutine for better readability and modern syntax.
return _.get(res, 'data.result.content', []).map(r => r.roleName); | ||
}); | ||
} catch (err) { | ||
return Promise.reject(err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of catching the error and returning a rejected promise, consider allowing the error to propagate naturally. This will make the function easier to handle with async/await syntax.
.then((opportunity) => { | ||
console.log(opportunity); | ||
const roles = util.getRolesByRoleName('copilot'); | ||
const roleInfo = util.getRoleInfo(roles[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider checking if roles
is not empty before accessing roles[0]
to avoid potential runtime errors.
@@ -815,6 +815,48 @@ const projectServiceUtils = { | |||
} | |||
}, | |||
|
|||
getRoleInfo: Promise.coroutine(function* (roleId, logger, requestId) { // eslint-disable-line func-names |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using async/await syntax instead of Promise.coroutine for better readability and modern JavaScript practices.
}, | ||
}).then((res) => { | ||
logger.debug(`Role info by ${roleId}: ${JSON.stringify(res.data.result.content)}`); | ||
return _.get(res, 'data.result.content', []); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of _.get
is good for safely accessing nested properties, but ensure that lodash is imported as _
at the top of the file if not already done.
return _.get(res, 'data.result.content', []); | ||
}); | ||
} catch (err) { | ||
return Promise.reject(err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of returning Promise.reject(err)
, consider using throw err;
to maintain consistency with async/await error handling patterns.
src/util.js
Outdated
}, | ||
}).then((res) => { | ||
logger.debug(`Roles by ${roleName}: ${JSON.stringify(res.data.result.content)}`); | ||
return _.get(res, 'data.result.content', []).map(r => r.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change from r.roleName
to r.id
alters the data being returned by the map function. Ensure that this change aligns with the intended functionality and that any dependent code is updated accordingly to handle the new data structure.
@@ -52,6 +53,14 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) | |||
.then(async (opportunity) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider removing the console.log(opportunity);
statement if it's not needed for debugging purposes. Leaving console logs in production code can lead to performance issues and cluttered logs.
console.log(opportunity); | ||
const roles = await util.getRolesByRoleName('copilot'); | ||
const roleInfo = await util.getRoleInfo(roles[0]); | ||
console.log(roles, roleInfo, 'roles by copilot'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider removing the console.log(roles, roleInfo, 'roles by copilot');
statement if it's not necessary for debugging. Console logs can clutter the output and should be avoided in production code.
@@ -35,7 +35,7 @@ module.exports = [ | |||
updatedBy: req.authUser.userId, | |||
}); | |||
|
|||
return approveRequest(data) | |||
return approveRequest(req, data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The approveRequest
function signature has changed to include req
as a parameter. Ensure that the approveRequest
function is updated to handle this new parameter correctly. If req
is not needed in the function, consider removing it to maintain the original function signature.
@@ -11,7 +12,7 @@ const resolveTransaction = (transaction, callback) => { | |||
return models.sequelize.transaction(callback); | |||
}; | |||
|
|||
module.exports = (data, existingTransaction) => { | |||
module.exports = (req, data, existingTransaction) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function signature has been changed to include req
as a parameter. Ensure that req
is used appropriately within the function. If req
is not used, consider removing it to avoid confusion.
@@ -52,6 +53,14 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) | |||
.then(async (opportunity) => { | |||
console.log(opportunity); | |||
const roles = await util.getRolesByRoleName('copilot', req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function getRolesByRoleName
now takes additional parameters req.log
and req.id
. Ensure that req
is defined and available in this context to avoid potential runtime errors.
.then(async (opportunity) => { | ||
console.log(opportunity); | ||
const roles = await util.getRolesByRoleName('copilot', req.log, req.id); | ||
const roleInfo = await util.getRoleInfo(roles[0], req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, the function getRoleInfo
now takes additional parameters req.log
and req.id
. Verify that req
is correctly passed and accessible here to prevent any issues.
@@ -98,7 +98,7 @@ module.exports = [ | |||
updatedBy: req.authUser.userId, | |||
type: copilotRequest.data.projectType, | |||
}); | |||
return approveRequest(approveData, transaction).then(() => copilotRequest); | |||
return approveRequest(req, approveData, transaction).then(() => copilotRequest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The approveRequest
function signature has changed to include req
as an additional parameter. Ensure that the approveRequest
function is updated accordingly to handle this new parameter, and verify that all calls to approveRequest
throughout the codebase are updated to match this new signature.
@@ -1,7 +1,10 @@ | |||
import _ from 'lodash'; | |||
import config from 'config'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a check to ensure that the 'config' module is correctly configured and contains the necessary properties before using it. This can help prevent runtime errors if the configuration is missing or incorrect.
import { COPILOT_REQUEST_STATUS } from '../../constants'; | ||
import { CONNECT_NOTIFICATION_EVENT, COPILOT_REQUEST_STATUS } from '../../constants'; | ||
import util from '../../util'; | ||
import { createEvent } from '../../services/busApi'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure that the 'createEvent' function from 'busApi' is used correctly later in the code. If not already done, verify that it handles errors and edge cases appropriately.
@@ -52,6 +55,34 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The console.log(opportunity);
statement has been removed, which is good for production code, but ensure that any necessary logging is still in place for debugging purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason to use console here instead of the req.log?
@@ -52,6 +55,34 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) | |||
.then(async (opportunity) => { | |||
const roles = await util.getRolesByRoleName('copilot', req.log, req.id); | |||
const { subjects = [] } = await util.getRoleInfo(roles[0], req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The console.log(roles, roleInfo, 'roles by copilot');
statement has been removed. Make sure that the necessary information is logged elsewhere if needed for debugging or auditing purposes.
const emailEventType = CONNECT_NOTIFICATION_EVENT.COPILOT_OPPORTUNITY_CREATED; | ||
const copilotPortalUrl = config.get('copilotPortalUrl'); | ||
req.log.info("Sending emails to all copilots about new opportunity"); | ||
subjects.forEach(subject => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider handling the case where subjects
might be an empty array to avoid unnecessary log entries or operations.
const copilotPortalUrl = config.get('copilotPortalUrl'); | ||
req.log.info("Sending emails to all copilots about new opportunity"); | ||
subjects.forEach(subject => { | ||
req.log.info("Each copilot members", subject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log message 'Each copilot members' could be more descriptive. Consider including more context, such as the copilot's handle or email, to make the logs more informative.
name: config.get('EMAIL_INVITE_FROM_NAME'), | ||
email: config.get('EMAIL_INVITE_FROM_EMAIL'), | ||
}, | ||
categories: [`${process.env.NODE_ENV}:${emailEventType}`.toLowerCase()], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure that the category string is correctly formatted and consistent with other parts of the application to avoid issues with event categorization.
}).then((res) => { | ||
logger.debug(`Roles by ${roleName}: ${JSON.stringify(res.data.result.content)}`); | ||
return _.get(res, 'data.result.content', []) | ||
.filter(item => item.roleName === roleName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using a more descriptive variable name than item
to improve code readability. For example, you could use role
or roleItem
to indicate that this represents a role object.
try { | ||
const token = yield this.getM2MToken(); | ||
const httpClient = this.getHttpClient({ id: requestId, log: logger }); | ||
httpClient.defaults.timeout = 6000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting a timeout for the HTTP client is a good practice to prevent hanging requests. However, consider making the timeout value configurable through an environment variable or configuration file instead of hardcoding it. This would allow for easier adjustments in different environments or scenarios.
try { | ||
const token = yield this.getM2MToken(); | ||
const httpClient = this.getHttpClient({ id: requestId, log: logger }); | ||
httpClient.defaults.timeout = 6000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting a timeout for the HTTP client is a good practice to prevent hanging requests. However, ensure that 6000 milliseconds is an appropriate timeout for all expected network conditions and use cases. Consider making this configurable if different timeouts might be needed in different environments.
return _.get(res, 'data.result.content', []); | ||
}); | ||
} catch (err) { | ||
logger.debug(err, "error on getting role info"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using a more descriptive error message to provide better context for debugging. For example, include information about the operation that failed or the parameters involved.
@@ -302,6 +302,9 @@ export const CONNECT_NOTIFICATION_EVENT = { | |||
TOPIC_UPDATED: 'connect.notification.project.topic.updated', | |||
POST_CREATED: 'connect.notification.project.post.created', | |||
POST_UPDATED: 'connect.notification.project.post.edited', | |||
|
|||
// External action email | |||
EXTERNAL_ACTION_EMAIL: 'external.action.email', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change from COPILOT_OPPORTUNITY_CREATED
to EXTERNAL_ACTION_EMAIL
seems to alter the meaning of the event. Ensure that this change aligns with the intended functionality described in the pull request. If the intention is to notify all copilots, verify that the event name accurately reflects this purpose.
const roles = await util.getRolesByRoleName('copilot', req.log, req.id); | ||
req.log.info("getting subjects for roles", roles[0]); | ||
const { subjects = [] } = await util.getRoleInfo(roles[0], req.log, req.id); | ||
const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change of emailEventType
from CONNECT_NOTIFICATION_EVENT.COPILOT_OPPORTUNITY_CREATED
to CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL
should be verified to ensure it aligns with the intended notification logic. This change might affect how the event is categorized or processed.
req.log.info("Each copilot members", subject); | ||
createEvent(emailEventType, { | ||
data: { | ||
user_name: subject.handle, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key handle
has been changed to user_name
. Ensure that this change is compatible with the rest of the system and that any downstream dependencies are updated accordingly.
user_name: subject.handle, | ||
opportunityDetailsUrl: `${copilotPortalUrl}/opportunity/${opportunity.id}`, | ||
}, | ||
sendgrid_template_id: "d-3efdc91da580479d810c7acd50a4c17f", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of sendgrid_template_id
should be checked to confirm that the template ID d-3efdc91da580479d810c7acd50a4c17f
is correct and that it exists in SendGrid. Also, verify that it matches the intended email format and content.
}, | ||
sendgrid_template_id: "d-3efdc91da580479d810c7acd50a4c17f", | ||
recipients: [subject.email], | ||
version: '433b1688-c543-4656-a295-efcbea57444d', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version
field has been changed from 'v3'
to '433b1688-c543-4656-a295-efcbea57444d'
. Ensure that this version identifier is correct and that it corresponds to the expected versioning system or API.
const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; | ||
const copilotPortalUrl = config.get('copilotPortalUrl'); | ||
req.log.info("Sending emails to all copilots about new opportunity"); | ||
req.log.info(`${copilotPortalUrl}/opportunity/${opportunity.id}`, '`${copilotPortalUrl}/opportunity/${opportunity.id}`'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log statement seems to have a redundant string repetition. The second argument appears to be a duplicate of the first. Consider removing the duplicate string to avoid unnecessary repetition.
req.log.info("Each copilot members", subject); | ||
createEvent(emailEventType, { | ||
data: { | ||
userName: subject.handle, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key user_name
was changed to userName
. Ensure that this change is reflected in all parts of the codebase where this key is used, including any documentation or external systems that might rely on the previous key format.
req.log.info("Each copilot members", subject); | ||
createEvent(emailEventType, { | ||
data: { | ||
user_name: subject.handle, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using camelCase for consistency with JavaScript naming conventions. Change user_name
to userName
.
createEvent(emailEventType, { | ||
data: { | ||
user_name: subject.handle, | ||
opportunity_details_url: `${copilotPortalUrl}/opportunity/${opportunity.id}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using camelCase for consistency with JavaScript naming conventions. Change opportunity_details_url
to opportunityDetailsUrl
.
}, | ||
sendgrid_template_id: "d-3efdc91da580479d810c7acd50a4c17f", | ||
recipients: [subject.email], | ||
version: 'v3', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The version identifier has been changed from a specific UUID to 'v3'. Ensure that 'v3' is the correct and intended version for the sendgrid template. If 'v3' is a placeholder or not a valid version, it may cause issues in the notification process.
@@ -65,7 +66,36 @@ module.exports = [ | |||
} | |||
|
|||
return models.CopilotApplication.create(data) | |||
.then((result) => { | |||
.then(async (result) => { | |||
const pmRole = await util.getRolesByRoleName('Project Manager', req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding error handling for the await util.getRolesByRoleName
call to manage potential failures or exceptions.
.then((result) => { | ||
.then(async (result) => { | ||
const pmRole = await util.getRolesByRoleName('Project Manager', req.log, req.id); | ||
const { subjects = [] } = await util.getRoleInfo(pmRole[0], req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding error handling for the await util.getRoleInfo
call to manage potential failures or exceptions.
const pmRole = await util.getRolesByRoleName('Project Manager', req.log, req.id); | ||
const { subjects = [] } = await util.getRoleInfo(pmRole[0], req.log, req.id); | ||
|
||
const creator = await util.getMemberDetailsByUserIds([req.authUser.userId], req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding error handling for the await util.getMemberDetailsByUserIds
call to manage potential failures or exceptions.
const creator = await util.getMemberDetailsByUserIds([req.authUser.userId], req.log, req.id); | ||
const listOfSubjects = subjects; | ||
if (creator) { | ||
const isCreatorPartofSubjects = subjects.find(item => item.email === creator[0].email); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable isCreatorPartofSubjects
could be renamed to isCreatorPartOfSubjects
to follow camelCase convention.
const isCreatorPartofSubjects = subjects.find(item => item.email === creator[0].email); | ||
if (!isCreatorPartofSubjects) { | ||
listOfSubjects.push({ | ||
email: creator.email, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a potential issue here: creator.email
should be creator[0].email
to match the structure used in the isCreatorPartofSubjects
check.
|
||
const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; | ||
const copilotPortalUrl = config.get('copilotPortalUrl'); | ||
listOfSubjects.forEach((subject) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding error handling for the createEvent
function call to manage potential failures or exceptions.
@@ -52,6 +55,29 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) | |||
.then(async (opportunity) => { | |||
const roles = await util.getRolesByRoleName('copilot', req.log, req.id); | |||
const { subjects = [] } = await util.getRoleInfo(roles[0], req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log message for getting subjects for roles has been removed. If this was intentional, ensure that the removal does not affect the debugging process. If not, consider reinstating it for better traceability.
const copilotPortalUrl = config.get('copilotPortalUrl'); | ||
req.log.info("Sending emails to all copilots about new opportunity"); | ||
subjects.forEach(subject => { | ||
req.log.info("Each copilot members", subject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log message for the copilot portal URL has been removed. If this was intentional, ensure that the removal does not affect the ability to trace the URL being used. If not, consider reinstating it for better traceability.
const pmRole = await util.getRolesByRoleName('Project Manager', req.log, req.id); | ||
const { subjects = [] } = await util.getRoleInfo(pmRole[0], req.log, req.id); | ||
|
||
const creator = await util.getMemberDetailsByUserIds([opportunity.userId], req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change from req.authUser.userId
to opportunity.userId
may affect the logic of fetching the creator's details. Ensure that opportunity.userId
correctly represents the intended user in the context of notifying all copilots.
if (creator) { | ||
const isCreatorPartofSubjects = subjects.find(item => item.email === creator[0].email); | ||
if (!isCreatorPartofSubjects) { | ||
listOfSubjects.push({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like creator
is being accessed as an array with creator[0]
, but previously it was accessed as an object with creator.email
. Ensure that creator
is consistently treated as an array or an object throughout the code to avoid potential runtime errors.
@@ -65,7 +67,36 @@ module.exports = [ | |||
} | |||
|
|||
return models.CopilotApplication.create(data) | |||
.then((result) => { | |||
.then(async (result) => { | |||
const pmRole = await util.getRolesByRoleName('Project Manager', req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use enum/constant for the role name. Hardcoding it isn't good practice.
const creator = await util.getMemberDetailsByUserIds([opportunity.userId], req.log, req.id); | ||
const listOfSubjects = subjects; | ||
if (creator) { | ||
const isCreatorPartofSubjects = subjects.find(item => item.email === creator[0].email); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we compare lower case values here? Coul be some issues if we are not.
user_name: subject.handle, | ||
opportunity_details_url: `${copilotPortalUrl}/opportunity/${opportunity.id}#applications`, | ||
}, | ||
sendgrid_template_id: "d-d7c1f48628654798a05c8e09e52db14f", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please conver sendgrid remplate id to constant.
@@ -52,6 +55,29 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) | |||
.then(async (opportunity) => { | |||
const roles = await util.getRolesByRoleName('copilot', req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conver role name to enum/constant. Do not use hardcoded names.
user_name: subject.handle, | ||
opportunity_details_url: `${copilotPortalUrl}/opportunity/${opportunity.id}`, | ||
}, | ||
sendgrid_template_id: "d-3efdc91da580479d810c7acd50a4c17f", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move the template id to constant.
export const TEMPLATE_IDS = { | ||
APPLY_COPILOT: 'd-d7c1f48628654798a05c8e09e52db14f', | ||
CREATE_REQUEST: 'd-3efdc91da580479d810c7acd50a4c17f' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a semicolon at the end of the object declaration for consistency with the rest of the codebase.
@@ -65,7 +67,36 @@ module.exports = [ | |||
} | |||
|
|||
return models.CopilotApplication.create(data) | |||
.then((result) => { | |||
.then(async (result) => { | |||
const pmRole = await util.getRolesByRoleName(USER_ROLE.PROJECT_MANAGER, req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change from a string to a constant USER_ROLE.PROJECT_MANAGER
is a good practice for maintainability, but ensure that USER_ROLE
is properly imported or defined in this file.
const creator = await util.getMemberDetailsByUserIds([opportunity.userId], req.log, req.id); | ||
const listOfSubjects = subjects; | ||
if (creator) { | ||
const isCreatorPartofSubjects = subjects.find(item => item.email.toLowerCase() === creator[0].email.toLowerCase()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Converting emails to lowercase for comparison is a good practice to ensure case-insensitive matching. However, ensure that both subjects
and creator
arrays are consistently handling email casing throughout the application to avoid any potential mismatches.
@@ -52,6 +55,28 @@ module.exports = (data, existingTransaction) => { | |||
return models.CopilotOpportunity | |||
.create(data, { transaction }); | |||
})) | |||
.then(async (opportunity) => { | |||
const roles = await util.getRolesByRoleName(USER_ROLE.TC_COPILOT, req.log, req.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change from a string 'copilot' to USER_ROLE.TC_COPILOT
is good for consistency and maintainability, but ensure that USER_ROLE.TC_COPILOT
is defined and correctly imported in this file.
user_name: subject.handle, | ||
opportunity_details_url: `${copilotPortalUrl}/opportunity/${opportunity.id}`, | ||
}, | ||
sendgrid_template_id: TEMPLATE_IDS.CREATE_REQUEST, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change to use TEMPLATE_IDS.CREATE_REQUEST
instead of a hardcoded string is a good practice for maintainability. Ensure that TEMPLATE_IDS.CREATE_REQUEST
is defined and correctly imported in this file.
const copilotPortalUrl = config.get('copilotPortalUrl'); | ||
req.log.info("Sending emails to all copilots about new opportunity"); | ||
subjects.forEach(subject => { | ||
createEvent(emailEventType, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log statement 'Each copilot members' was removed. If this was intentional, ensure that the logging is still sufficient for debugging purposes. If not, consider adding a relevant log statement to track each copilot being notified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
What's in this PR?