From 247418102207cda1d0b3ac9ed8e5d08a0d578f0e Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Sat, 16 Aug 2025 00:17:10 +0200 Subject: [PATCH 01/16] fix: paginated copilot request --- src/routes/copilotRequest/list.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/routes/copilotRequest/list.js b/src/routes/copilotRequest/list.js index a36a3d7b..3ca03fa5 100644 --- a/src/routes/copilotRequest/list.js +++ b/src/routes/copilotRequest/list.js @@ -1,8 +1,10 @@ import _ from 'lodash'; +import { Op, Sequelize } from 'sequelize'; import models from '../../models'; import util from '../../util'; import { PERMISSION } from '../../permissions/constants'; +import { DEFAULT_PAGE_SIZE } from '../../constants'; module.exports = [ (req, res, next) => { @@ -15,6 +17,10 @@ module.exports = [ return next(err); } + const page = parseInt(req.query.page, 10) || 1; + const pageSize = parseInt(req.query.pageSize, 10) || DEFAULT_PAGE_SIZE; + const offset = (page - 1) * pageSize; + const projectId = _.parseInt(req.params.projectId); let sort = req.query.sort ? decodeURIComponent(req.query.sort) : 'createdAt desc'; @@ -32,16 +38,16 @@ module.exports = [ return models.CopilotRequest.findAll({ where: whereCondition, include: [ - { - model: models.CopilotOpportunity, - as: 'copilotOpportunity', - }, + { model: models.CopilotOpportunity, as: 'copilotOpportunity', required: false }, ], - order: [[sortParams[0], sortParams[1]]], - }) - .then(copilotRequests => res.json(copilotRequests)) - .catch((err) => { - util.handleError('Error fetching copilot requests', err, req, next); - }); + order: [[sortParams[0], sortParams[1]]], // e.g. ['createdAt','DESC'] + limit: perPage, + offset, + }).then((copilotRequests) => util.setPaginationHeaders(req, res, { + count: copilotRequests.count, + rows: copilotRequests, + page, + pageSize, + })); }, ]; From e65a766a62a2b8d14997b1bde7a6cd42876101c6 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Sat, 16 Aug 2025 00:17:34 +0200 Subject: [PATCH 02/16] fix: paginated copilot request --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3ae3c51c..5a769156 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -149,7 +149,7 @@ workflows: context : org-global filters: branches: - only: ['develop', 'migration-setup', 'pm-1613'] + only: ['develop', 'migration-setup', 'paginate-copilot-request'] - deployProd: context : org-global filters: From e439cc8368c1d9a715738b5c6101f8b04208ae59 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Sat, 16 Aug 2025 00:35:31 +0200 Subject: [PATCH 03/16] fix: paginated copilot request --- src/routes/copilotRequest/list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/copilotRequest/list.js b/src/routes/copilotRequest/list.js index 3ca03fa5..fa3c12c4 100644 --- a/src/routes/copilotRequest/list.js +++ b/src/routes/copilotRequest/list.js @@ -40,8 +40,8 @@ module.exports = [ include: [ { model: models.CopilotOpportunity, as: 'copilotOpportunity', required: false }, ], - order: [[sortParams[0], sortParams[1]]], // e.g. ['createdAt','DESC'] - limit: perPage, + order: [[sortParams[0], sortParams[1]]], + limit: pageSize, offset, }).then((copilotRequests) => util.setPaginationHeaders(req, res, { count: copilotRequests.count, From e30591f423cee14bd5d1a3cf7d49609e86fe3b9e Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Sat, 16 Aug 2025 00:56:25 +0200 Subject: [PATCH 04/16] fix: paginated copilot request --- src/routes/copilotRequest/list.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/routes/copilotRequest/list.js b/src/routes/copilotRequest/list.js index fa3c12c4..d22c6041 100644 --- a/src/routes/copilotRequest/list.js +++ b/src/routes/copilotRequest/list.js @@ -35,7 +35,7 @@ module.exports = [ const whereCondition = projectId ? { projectId } : {}; - return models.CopilotRequest.findAll({ + return models.CopilotRequest.findAndCountAll({ where: whereCondition, include: [ { model: models.CopilotOpportunity, as: 'copilotOpportunity', required: false }, @@ -43,8 +43,10 @@ module.exports = [ order: [[sortParams[0], sortParams[1]]], limit: pageSize, offset, - }).then((copilotRequests) => util.setPaginationHeaders(req, res, { - count: copilotRequests.count, + distinct: true, + subQuery: false, + }).then((copilotRequests, count) => util.setPaginationHeaders(req, res, { + count: count, rows: copilotRequests, page, pageSize, From d4a88f4f0ef9eae38e01e102db78ea8e80ba5cc6 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Sat, 16 Aug 2025 01:12:27 +0200 Subject: [PATCH 05/16] fix: paginated copilot request --- src/routes/copilotRequest/list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/copilotRequest/list.js b/src/routes/copilotRequest/list.js index d22c6041..bb8e56be 100644 --- a/src/routes/copilotRequest/list.js +++ b/src/routes/copilotRequest/list.js @@ -45,7 +45,7 @@ module.exports = [ offset, distinct: true, subQuery: false, - }).then((copilotRequests, count) => util.setPaginationHeaders(req, res, { + }).then(({rows: copilotRequests, count}) => util.setPaginationHeaders(req, res, { count: count, rows: copilotRequests, page, From 902e2b389e3872d1f8117379e5f85418e5465782 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Sun, 17 Aug 2025 09:09:06 +0200 Subject: [PATCH 06/16] fix: add project in copilot request --- src/routes/copilotRequest/list.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/copilotRequest/list.js b/src/routes/copilotRequest/list.js index bb8e56be..27664733 100644 --- a/src/routes/copilotRequest/list.js +++ b/src/routes/copilotRequest/list.js @@ -39,6 +39,7 @@ module.exports = [ where: whereCondition, include: [ { model: models.CopilotOpportunity, as: 'copilotOpportunity', required: false }, + { model: models.Project, as: 'project', required: false }, ], order: [[sortParams[0], sortParams[1]]], limit: pageSize, From 44047b687f8e18dc55edf0e37744c0cd43ed7692 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Sun, 17 Aug 2025 23:05:29 +0200 Subject: [PATCH 07/16] fix: added project relation to copilot requests --- src/models/copilotRequest.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/models/copilotRequest.js b/src/models/copilotRequest.js index 7ddb924e..e82be1d3 100644 --- a/src/models/copilotRequest.js +++ b/src/models/copilotRequest.js @@ -32,6 +32,7 @@ module.exports = function defineCopilotRequest(sequelize, DataTypes) { CopliotRequest.associate = (models) => { CopliotRequest.hasMany(models.CopilotOpportunity, { as: 'copilotOpportunity', foreignKey: 'copilotRequestId' }); + CopliotRequest.belongsTo(models.Project, { as: 'project', foreignKey: 'projectId' }); }; return CopliotRequest; From e7888e9f515d89bbeafb5d43edba2c805db401fa Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Mon, 18 Aug 2025 17:39:45 +0200 Subject: [PATCH 08/16] feat: send email when opportunity is completed or canceled --- src/constants.js | 2 ++ src/routes/copilotOpportunity/assign.js | 38 +++++++++++++++++++++++++ src/routes/copilotOpportunity/delete.js | 30 ++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/constants.js b/src/constants.js index b2987e65..0dc8af26 100644 --- a/src/constants.js +++ b/src/constants.js @@ -314,6 +314,8 @@ export const TEMPLATE_IDS = { INFORM_PM_COPILOT_APPLICATION_ACCEPTED: 'd-b35d073e302b4279a1bd208fcfe96f58', COPILOT_ALREADY_PART_OF_PROJECT: 'd-003d41cdc9de4bbc9e14538e8f2e0585', COPILOT_APPLICATION_ACCEPTED: 'd-eef5e7568c644940b250e76d026ced5b', + COPILOT_OPPORTUNITY_COMPLETED: 'd-dc448919d11b4e7d8b4ba351c4b67b8b', + COPILOT_OPPORTUNITY_CANCELED: 'd-2a67ba71e82f4d70891fe6989c3522a3' } export const REGEX = { URL: /^(http(s?):\/\/)?(www\.)?[a-zA-Z0-9\.\-\_]+(\.[a-zA-Z]{2,15})+(\:[0-9]{2,5})?(\/[a-zA-Z0-9\_\-\s\.\/\?\%\#\&\=;]*)?$/, // eslint-disable-line diff --git a/src/routes/copilotOpportunity/assign.js b/src/routes/copilotOpportunity/assign.js index bf021bbb..e7e08f75 100644 --- a/src/routes/copilotOpportunity/assign.js +++ b/src/routes/copilotOpportunity/assign.js @@ -18,6 +18,41 @@ const assignCopilotOpportunityValidations = { }), }; +const sendEmailToAllApplicants = async (req, opportunity, copilotRequest, applicationId) => { + const allApplications = await models.Sequelize.CopilotApplication.findAll({ + where: { + opportunityId: opportunity.id, + id: { + [Op.notIn]: [applicationId], + } + } + }); + + const userIds = allApplications.map(item => item.userId); + + const users = await util.getMemberDetailsByUserIds(userIds, req.log, req.id); + + users.forEach(async (user) => { + req.log.debug(`Sending email notification to copilots who are not accepted`); + const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; + const copilotPortalUrl = config.get('copilotPortalUrl'); + const requestData = copilotRequest.data; + createEvent(emailEventType, { + data: { + opportunity_details_url: `${copilotPortalUrl}/opportunity`, + opportunity_title: requestData.opportunityTitle, + user_name: user ? user.handle : "", + }, + sendgrid_template_id: TEMPLATE_IDS.COPILOT_OPPORTUNITY_COMPLETED, + recipients: [user.email], + version: 'v3', + }, req.log); + + req.log.debug(`Email sent to copilots who are not accepted`); + }); + +}; + module.exports = [ validate(assignCopilotOpportunityValidations), async (req, res, next) => { @@ -134,6 +169,9 @@ module.exports = [ }, req.log); req.log.debug(`Email sent`); + + // Send email to all applicants about opportunity completion + await sendEmailToAllApplicants(req, opportunity, copilotRequest, application.id); }; const existingMember = activeMembers.find(item => item.userId === userId); diff --git a/src/routes/copilotOpportunity/delete.js b/src/routes/copilotOpportunity/delete.js index 5336807f..dab246ef 100644 --- a/src/routes/copilotOpportunity/delete.js +++ b/src/routes/copilotOpportunity/delete.js @@ -3,10 +3,36 @@ import { Op } from 'sequelize'; import models from '../../models'; import util from '../../util'; -import { COPILOT_APPLICATION_STATUS, COPILOT_OPPORTUNITY_STATUS, COPILOT_REQUEST_STATUS, EVENT, INVITE_STATUS, RESOURCES } from '../../constants'; +import { CONNECT_NOTIFICATION_EVENT, COPILOT_APPLICATION_STATUS, COPILOT_OPPORTUNITY_STATUS, COPILOT_REQUEST_STATUS, EVENT, INVITE_STATUS, RESOURCES, TEMPLATE_IDS } from '../../constants'; +import { createEvent } from '../../services/busApi'; import { PERMISSION } from '../../permissions/constants'; +const sendEmailToAllApplicants = async (req, copilotRequest, applications) => { + const userIds = applications.map(item => item.userId); + const users = await util.getMemberDetailsByUserIds(userIds, req.log, req.id); + + users.forEach(async (user) => { + req.log.debug(`Sending email notification to copilots who applied`); + const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; + const copilotPortalUrl = config.get('copilotPortalUrl'); + const requestData = copilotRequest.data; + createEvent(emailEventType, { + data: { + opportunity_details_url: `${copilotPortalUrl}/opportunity`, + opportunity_title: requestData.opportunityTitle, + user_name: user ? user.handle : "", + }, + sendgrid_template_id: TEMPLATE_IDS.COPILOT_OPPORTUNITY_CANCELED, + recipients: [user.email], + version: 'v3', + }, req.log); + + req.log.debug(`Email sent to copilots who applied`); + }); + +}; + module.exports = [ (req, res, next) => { if (!util.hasPermissionByReq(PERMISSION.CANCEL_COPILOT_OPPORTUNITY, req)) { @@ -93,6 +119,8 @@ module.exports = [ invite.toJSON()); } + await sendEmailToAllApplicants(req, copilotRequest, applications) + res.status(200).send({ id: opportunity.id }); }) From 4aa668ccbbf90d4098eddd09a10c43c7f4229344 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Mon, 18 Aug 2025 17:40:04 +0200 Subject: [PATCH 09/16] feat: send email when opportunity is completed or canceled --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3ae3c51c..3f9d7062 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -149,7 +149,7 @@ workflows: context : org-global filters: branches: - only: ['develop', 'migration-setup', 'pm-1613'] + only: ['develop', 'migration-setup', 'pm-1611'] - deployProd: context : org-global filters: From 83c6db973562ecaa194718bf3e5361e267d6b53a Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Mon, 18 Aug 2025 17:42:12 +0200 Subject: [PATCH 10/16] feat: send email when opportunity is completed or canceled --- src/routes/copilotOpportunity/delete.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/copilotOpportunity/delete.js b/src/routes/copilotOpportunity/delete.js index dab246ef..22307d58 100644 --- a/src/routes/copilotOpportunity/delete.js +++ b/src/routes/copilotOpportunity/delete.js @@ -1,5 +1,6 @@ import _ from 'lodash'; import { Op } from 'sequelize'; +import config from 'config'; import models from '../../models'; import util from '../../util'; From 5071cb833c9c9e954d1b5511e5003f929164b25b Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Mon, 18 Aug 2025 21:43:40 +0200 Subject: [PATCH 11/16] fix: build --- src/routes/copilotOpportunity/assign.js | 72 ++++++++++++------------- src/routes/copilotOpportunity/delete.js | 52 +++++++++--------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/routes/copilotOpportunity/assign.js b/src/routes/copilotOpportunity/assign.js index e7e08f75..4f226d2e 100644 --- a/src/routes/copilotOpportunity/assign.js +++ b/src/routes/copilotOpportunity/assign.js @@ -18,41 +18,6 @@ const assignCopilotOpportunityValidations = { }), }; -const sendEmailToAllApplicants = async (req, opportunity, copilotRequest, applicationId) => { - const allApplications = await models.Sequelize.CopilotApplication.findAll({ - where: { - opportunityId: opportunity.id, - id: { - [Op.notIn]: [applicationId], - } - } - }); - - const userIds = allApplications.map(item => item.userId); - - const users = await util.getMemberDetailsByUserIds(userIds, req.log, req.id); - - users.forEach(async (user) => { - req.log.debug(`Sending email notification to copilots who are not accepted`); - const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; - const copilotPortalUrl = config.get('copilotPortalUrl'); - const requestData = copilotRequest.data; - createEvent(emailEventType, { - data: { - opportunity_details_url: `${copilotPortalUrl}/opportunity`, - opportunity_title: requestData.opportunityTitle, - user_name: user ? user.handle : "", - }, - sendgrid_template_id: TEMPLATE_IDS.COPILOT_OPPORTUNITY_COMPLETED, - recipients: [user.email], - version: 'v3', - }, req.log); - - req.log.debug(`Email sent to copilots who are not accepted`); - }); - -}; - module.exports = [ validate(assignCopilotOpportunityValidations), async (req, res, next) => { @@ -67,6 +32,41 @@ module.exports = [ return next(err); } + const sendEmailToAllApplicants = async (opportunity, copilotRequest, applicationId) => { + const allApplications = await models.Sequelize.CopilotApplication.findAll({ + where: { + opportunityId: opportunity.id, + id: { + [Op.notIn]: [applicationId], + } + } + }); + + const userIds = allApplications.map(item => item.userId); + + const users = await util.getMemberDetailsByUserIds(userIds, req.log, req.id); + + users.forEach(async (user) => { + req.log.debug(`Sending email notification to copilots who are not accepted`); + const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; + const copilotPortalUrl = config.get('copilotPortalUrl'); + const requestData = copilotRequest.data; + createEvent(emailEventType, { + data: { + opportunity_details_url: `${copilotPortalUrl}/opportunity`, + opportunity_title: requestData.opportunityTitle, + user_name: user ? user.handle : "", + }, + sendgrid_template_id: TEMPLATE_IDS.COPILOT_OPPORTUNITY_COMPLETED, + recipients: [user.email], + version: 'v3', + }, req.log); + + req.log.debug(`Email sent to copilots who are not accepted`); + }); + + }; + return models.sequelize.transaction(async (t) => { const opportunity = await models.CopilotOpportunity.findOne({ where: { id: copilotOpportunityId }, @@ -171,7 +171,7 @@ module.exports = [ req.log.debug(`Email sent`); // Send email to all applicants about opportunity completion - await sendEmailToAllApplicants(req, opportunity, copilotRequest, application.id); + await sendEmailToAllApplicants(opportunity, copilotRequest, application.id); }; const existingMember = activeMembers.find(item => item.userId === userId); diff --git a/src/routes/copilotOpportunity/delete.js b/src/routes/copilotOpportunity/delete.js index 22307d58..90ff830c 100644 --- a/src/routes/copilotOpportunity/delete.js +++ b/src/routes/copilotOpportunity/delete.js @@ -9,31 +9,6 @@ import { createEvent } from '../../services/busApi'; import { PERMISSION } from '../../permissions/constants'; -const sendEmailToAllApplicants = async (req, copilotRequest, applications) => { - const userIds = applications.map(item => item.userId); - const users = await util.getMemberDetailsByUserIds(userIds, req.log, req.id); - - users.forEach(async (user) => { - req.log.debug(`Sending email notification to copilots who applied`); - const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; - const copilotPortalUrl = config.get('copilotPortalUrl'); - const requestData = copilotRequest.data; - createEvent(emailEventType, { - data: { - opportunity_details_url: `${copilotPortalUrl}/opportunity`, - opportunity_title: requestData.opportunityTitle, - user_name: user ? user.handle : "", - }, - sendgrid_template_id: TEMPLATE_IDS.COPILOT_OPPORTUNITY_CANCELED, - recipients: [user.email], - version: 'v3', - }, req.log); - - req.log.debug(`Email sent to copilots who applied`); - }); - -}; - module.exports = [ (req, res, next) => { if (!util.hasPermissionByReq(PERMISSION.CANCEL_COPILOT_OPPORTUNITY, req)) { @@ -47,6 +22,31 @@ module.exports = [ // default values const opportunityId = _.parseInt(req.params.id); + const sendEmailToAllApplicants = async (copilotRequest, applications) => { + const userIds = applications.map(item => item.userId); + const users = await util.getMemberDetailsByUserIds(userIds, req.log, req.id); + + users.forEach(async (user) => { + req.log.debug(`Sending email notification to copilots who applied`); + const emailEventType = CONNECT_NOTIFICATION_EVENT.EXTERNAL_ACTION_EMAIL; + const copilotPortalUrl = config.get('copilotPortalUrl'); + const requestData = copilotRequest.data; + createEvent(emailEventType, { + data: { + opportunity_details_url: `${copilotPortalUrl}/opportunity`, + opportunity_title: requestData.opportunityTitle, + user_name: user ? user.handle : "", + }, + sendgrid_template_id: TEMPLATE_IDS.COPILOT_OPPORTUNITY_CANCELED, + recipients: [user.email], + version: 'v3', + }, req.log); + + req.log.debug(`Email sent to copilots who applied`); + }); + + }; + return models.sequelize.transaction(async (transaction) => { req.log.debug('Canceling Copilot opportunity transaction', opportunityId); const opportunity = await models.CopilotOpportunity.findOne({ @@ -120,7 +120,7 @@ module.exports = [ invite.toJSON()); } - await sendEmailToAllApplicants(req, copilotRequest, applications) + await sendEmailToAllApplicants(copilotRequest, applications) res.status(200).send({ id: opportunity.id }); }) From c55231ac59a29e0c6c63f89180082752a72bf0d7 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Mon, 18 Aug 2025 23:12:26 +0200 Subject: [PATCH 12/16] debug --- src/routes/copilotOpportunity/get.js | 2 +- src/routes/index.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/copilotOpportunity/get.js b/src/routes/copilotOpportunity/get.js index 9202a845..f3ae9801 100644 --- a/src/routes/copilotOpportunity/get.js +++ b/src/routes/copilotOpportunity/get.js @@ -4,7 +4,7 @@ import util from '../../util'; module.exports = [ (req, res, next) => { const { id } = req.params; - + req.log.info("Reached get endpoint"); if (!id || isNaN(id)) { return util.handleError('Invalid opportunity ID', null, req, next, 400); } diff --git a/src/routes/index.js b/src/routes/index.js index 87e48a86..4fdc336a 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -473,6 +473,7 @@ router.use((err, req, res, next) => { // eslint-disable-line no-unused-vars // catch 404 and forward to error handler router.use((req, res, next) => { + req.log.info("reached middleware") const err = new Error('Not Found'); err.status = 404; next(err); From 4e0bf894ed552cbea6c4bf555cb55032efa70343 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Tue, 19 Aug 2025 00:50:23 +0200 Subject: [PATCH 13/16] fix: assign email --- src/routes/copilotOpportunity/assign.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/copilotOpportunity/assign.js b/src/routes/copilotOpportunity/assign.js index 4f226d2e..3728927e 100644 --- a/src/routes/copilotOpportunity/assign.js +++ b/src/routes/copilotOpportunity/assign.js @@ -169,9 +169,6 @@ module.exports = [ }, req.log); req.log.debug(`Email sent`); - - // Send email to all applicants about opportunity completion - await sendEmailToAllApplicants(opportunity, copilotRequest, application.id); }; const existingMember = activeMembers.find(item => item.userId === userId); @@ -265,6 +262,9 @@ module.exports = [ await sendEmailToCopilot(); + // Send email to all applicants about opportunity completion + await sendEmailToAllApplicants(opportunity, copilotRequest, application.id); + // Cancel other applications const otherApplications = await models.CopilotApplication.findAll({ where: { From 39acdfa44e409408efe100bf1336cabbf70aa016 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Tue, 19 Aug 2025 00:56:27 +0200 Subject: [PATCH 14/16] fix: assign email --- src/routes/copilotOpportunity/assign.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/routes/copilotOpportunity/assign.js b/src/routes/copilotOpportunity/assign.js index 3728927e..0756491a 100644 --- a/src/routes/copilotOpportunity/assign.js +++ b/src/routes/copilotOpportunity/assign.js @@ -32,15 +32,7 @@ module.exports = [ return next(err); } - const sendEmailToAllApplicants = async (opportunity, copilotRequest, applicationId) => { - const allApplications = await models.Sequelize.CopilotApplication.findAll({ - where: { - opportunityId: opportunity.id, - id: { - [Op.notIn]: [applicationId], - } - } - }); + const sendEmailToAllApplicants = async (copilotRequest, allApplications) => { const userIds = allApplications.map(item => item.userId); @@ -262,9 +254,6 @@ module.exports = [ await sendEmailToCopilot(); - // Send email to all applicants about opportunity completion - await sendEmailToAllApplicants(opportunity, copilotRequest, application.id); - // Cancel other applications const otherApplications = await models.CopilotApplication.findAll({ where: { @@ -276,6 +265,9 @@ module.exports = [ transaction: t, }); + // Send email to all applicants about opportunity completion + await sendEmailToAllApplicants(copilotRequest, otherApplications); + for (const otherApplication of otherApplications) { await otherApplication.update({ status: COPILOT_APPLICATION_STATUS.CANCELED, From 76ec16c1a5b127736d60834e87639211ad8a996b Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Tue, 19 Aug 2025 17:15:40 +0200 Subject: [PATCH 15/16] removed debug messages --- src/routes/copilotOpportunity/get.js | 1 - src/routes/index.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/routes/copilotOpportunity/get.js b/src/routes/copilotOpportunity/get.js index f3ae9801..e4bad5c8 100644 --- a/src/routes/copilotOpportunity/get.js +++ b/src/routes/copilotOpportunity/get.js @@ -4,7 +4,6 @@ import util from '../../util'; module.exports = [ (req, res, next) => { const { id } = req.params; - req.log.info("Reached get endpoint"); if (!id || isNaN(id)) { return util.handleError('Invalid opportunity ID', null, req, next, 400); } diff --git a/src/routes/index.js b/src/routes/index.js index 4fdc336a..87e48a86 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -473,7 +473,6 @@ router.use((err, req, res, next) => { // eslint-disable-line no-unused-vars // catch 404 and forward to error handler router.use((req, res, next) => { - req.log.info("reached middleware") const err = new Error('Not Found'); err.status = 404; next(err); From d2425b4a12814764e7b31bcd5e1787a59c586146 Mon Sep 17 00:00:00 2001 From: Hentry Martin Date: Tue, 19 Aug 2025 17:58:05 +0200 Subject: [PATCH 16/16] fix: typo --- src/models/copilotRequest.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/models/copilotRequest.js b/src/models/copilotRequest.js index e82be1d3..c566073e 100644 --- a/src/models/copilotRequest.js +++ b/src/models/copilotRequest.js @@ -2,7 +2,7 @@ import _ from 'lodash'; import { COPILOT_REQUEST_STATUS } from '../constants'; module.exports = function defineCopilotRequest(sequelize, DataTypes) { - const CopliotRequest = sequelize.define('CopilotRequest', { + const CopilotRequest = sequelize.define('CopilotRequest', { id: { type: DataTypes.BIGINT, primaryKey: true, autoIncrement: true }, status: { type: DataTypes.STRING(16), @@ -30,10 +30,10 @@ module.exports = function defineCopilotRequest(sequelize, DataTypes) { indexes: [], }); - CopliotRequest.associate = (models) => { - CopliotRequest.hasMany(models.CopilotOpportunity, { as: 'copilotOpportunity', foreignKey: 'copilotRequestId' }); - CopliotRequest.belongsTo(models.Project, { as: 'project', foreignKey: 'projectId' }); + CopilotRequest.associate = (models) => { + CopilotRequest.hasMany(models.CopilotOpportunity, { as: 'copilotOpportunity', foreignKey: 'copilotRequestId' }); + CopilotRequest.belongsTo(models.Project, { as: 'project', foreignKey: 'projectId' }); }; - return CopliotRequest; + return CopilotRequest; };