From 32b650f9b212f2bc104491ee15a9d78ba5552808 Mon Sep 17 00:00:00 2001 From: Maksym Mykhailenko Date: Mon, 9 Aug 2021 10:27:36 +0300 Subject: [PATCH 01/16] add logs to email notifications scheduler --- src/services/EmailNotificationService.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/services/EmailNotificationService.js b/src/services/EmailNotificationService.js index 5572933c..d1a191e2 100644 --- a/src/services/EmailNotificationService.js +++ b/src/services/EmailNotificationService.js @@ -120,6 +120,9 @@ async function sendCandidatesAvailableEmails () { const jobs = _.map(jobsDao, dao => dao.dataValues) const projectIds = _.uniq(_.map(jobs, job => job.projectId)) + + localLogger.debug(`[sendCandidatesAvailableEmails]: Found ${projectIds.length} project with Job Candidates awaiting for review.`) + // for each unique project id, send an email for (const projectId of projectIds) { const project = await getProjectWithId(projectId) @@ -216,6 +219,8 @@ async function sendInterviewComingUpEmails () { raw: true }) + localLogger.debug(`[sendInterviewComingUpEmails]: Found ${interviews.length} Interviews which are coming soon.`) + for (const interview of interviews) { // send host email const data = await getDataForInterview(interview) @@ -288,6 +293,8 @@ async function sendInterviewCompletedEmails () { raw: true }) + localLogger.debug(`[sendInterviewCompletedEmails]: Found ${interviews.length} Interviews which must be ended by now.`) + for (const interview of interviews) { if (_.isEmpty(interview.hostEmail)) { localLogger.error(`Interview id: ${interview.id} host email not present`) @@ -330,6 +337,8 @@ async function sendPostInterviewActionEmails () { }] }) + localLogger.debug(`[sendPostInterviewActionEmails]: Found ${completedJobCandidates.length} Job Candidates with interview completed awaiting for an action.`) + // get all project ids for this job candidates const jobs = await Job.findAll({ where: { @@ -410,6 +419,8 @@ async function sendResourceBookingExpirationEmails () { }) const projectIds = _.uniq(_.map(expiringResourceBookings, rb => rb.projectId)) + localLogger.debug(`[sendResourceBookingExpirationEmails]: Found ${projectIds.length} project with ${expiringResourceBookings.length} Resource Bookings expiring in less than 3 weeks.`) + for (const projectId of projectIds) { const project = await getProjectWithId(projectId) if (!project) { continue } From d7f27b21d63361d0400b4f8923e4a99c5dbd1d3a Mon Sep 17 00:00:00 2001 From: Maksym Mykhailenko Date: Mon, 9 Aug 2021 13:06:58 +0300 Subject: [PATCH 02/16] fix handle server error text --- src/services/EmailNotificationService.js | 4 ++-- src/services/PaymentService.js | 8 ++++---- src/services/WorkPeriodPaymentService.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/services/EmailNotificationService.js b/src/services/EmailNotificationService.js index d1a191e2..e5dd4bb8 100644 --- a/src/services/EmailNotificationService.js +++ b/src/services/EmailNotificationService.js @@ -33,7 +33,7 @@ async function getProjectWithId (projectId) { project = await helper.getProjectById(helper.getAuditM2Muser(), projectId) } catch (err) { localLogger.error( - `exception fetching project with id: ${projectId} Status Code: ${err.status} message: ${err.response.text}`, 'getProjectWithId') + `exception fetching project with id: ${projectId} Status Code: ${err.status} message: ${_.get(err, 'response.text', err.toString())}`, 'getProjectWithId') } return project @@ -65,7 +65,7 @@ async function getUserWithId (userId) { user = await helper.ensureUserById(userId) } catch (err) { localLogger.error( - `exception fetching user with id: ${userId} Status Code: ${err.status} message: ${err.response.text}`, 'getUserWithId') + `exception fetching user with id: ${userId} Status Code: ${err.status} message: ${_.get(err, 'response.text', err.toString())}`, 'getUserWithId') } return user diff --git a/src/services/PaymentService.js b/src/services/PaymentService.js index 93d04e41..b588c9ce 100644 --- a/src/services/PaymentService.js +++ b/src/services/PaymentService.js @@ -96,7 +96,7 @@ async function createChallenge (challenge, token) { return challengeId } catch (err) { localLogger.error({ context: 'createChallenge', message: `Status Code: ${err.status}` }) - localLogger.error({ context: 'createChallenge', message: err.response.text }) + localLogger.error({ context: 'createChallenge', message: _.get(err, 'response.text', err.toString()) }) throw err } } @@ -126,7 +126,7 @@ async function addResourceToChallenge (id, handle, token) { } } localLogger.error({ context: 'addResourceToChallenge', message: `Status Code: ${err.status}` }) - localLogger.error({ context: 'addResourceToChallenge', message: err.response.text }) + localLogger.error({ context: 'addResourceToChallenge', message: _.get(err, 'response.text', err.toString()) }) throw err } } @@ -153,7 +153,7 @@ async function activateChallenge (id, token) { } } localLogger.error({ context: 'activateChallenge', message: `Status Code: ${err.status}` }) - localLogger.error({ context: 'activateChallenge', message: err.response.text }) + localLogger.error({ context: 'activateChallenge', message: _.get(err, 'response.text', err.toString()) }) throw err } } @@ -189,7 +189,7 @@ async function closeChallenge (id, userId, userHandle, token) { } } localLogger.error({ context: 'closeChallenge', message: `Status Code: ${err.status}` }) - localLogger.error({ context: 'closeChallenge', message: err.response.text }) + localLogger.error({ context: 'closeChallenge', message: _.get(err, 'response.text', err.toString()) }) throw err } } diff --git a/src/services/WorkPeriodPaymentService.js b/src/services/WorkPeriodPaymentService.js index ac0fbe19..81ca79e9 100644 --- a/src/services/WorkPeriodPaymentService.js +++ b/src/services/WorkPeriodPaymentService.js @@ -69,8 +69,8 @@ async function _updateChallenge (challengeId, data) { await helper.updateChallenge(challengeId, body) logger.debug({ component: 'WorkPeriodPaymentService', context: 'updateChallenge', message: `Challenge with id ${challengeId} is updated` }) } catch (err) { - logger.error({ component: 'WorkPeriodPaymentService', context: 'updateChallenge', message: err.response.text }) - throw new errors.BadRequestError(`Cannot update the the challenge: ${err.response.text}`) + logger.error({ component: 'WorkPeriodPaymentService', context: 'updateChallenge', message: _.get(err, 'response.text', err.toString()) }) + throw new errors.BadRequestError(`Cannot update the the challenge: ${_.get(err, 'response.text', err.toString())}`) } } } From 61c2cc8d79499b98ff97fd4d152c65176e4fa510 Mon Sep 17 00:00:00 2001 From: Maksym Mykhailenko Date: Mon, 9 Aug 2021 13:23:40 +0300 Subject: [PATCH 03/16] improved logs for email notifications --- src/services/EmailNotificationService.js | 40 ++++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/services/EmailNotificationService.js b/src/services/EmailNotificationService.js index e5dd4bb8..a561445e 100644 --- a/src/services/EmailNotificationService.js +++ b/src/services/EmailNotificationService.js @@ -121,9 +121,10 @@ async function sendCandidatesAvailableEmails () { const projectIds = _.uniq(_.map(jobs, job => job.projectId)) - localLogger.debug(`[sendCandidatesAvailableEmails]: Found ${projectIds.length} project with Job Candidates awaiting for review.`) + localLogger.debug(`[sendCandidatesAvailableEmails]: Found ${projectIds.length} projects with Job Candidates awaiting for review.`) // for each unique project id, send an email + let sentCount = 0 for (const projectId of projectIds) { const project = await getProjectWithId(projectId) if (!project) { continue } @@ -175,7 +176,10 @@ async function sendCandidatesAvailableEmails () { description: 'Candidates are available for review' } }) + + sentCount++ } + localLogger.debug(`[sendCandidatesAvailableEmails]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Job Candidates awaiting for review.`) } /** @@ -219,8 +223,10 @@ async function sendInterviewComingUpEmails () { raw: true }) - localLogger.debug(`[sendInterviewComingUpEmails]: Found ${interviews.length} Interviews which are coming soon.`) + localLogger.debug(`[sendInterviewComingUpEmails]: Found ${interviews.length} interviews which are coming soon.`) + let sentHostCount = 0 + let sentGuestCount = 0 for (const interview of interviews) { // send host email const data = await getDataForInterview(interview) @@ -238,6 +244,8 @@ async function sendInterviewComingUpEmails () { description: 'Interview Coming Up' } }) + + sentHostCount++ } else { localLogger.error(`Interview id: ${interview.id} host email not present`, 'sendInterviewComingUpEmails') } @@ -255,10 +263,14 @@ async function sendInterviewComingUpEmails () { description: 'Interview Coming Up' } }) + + sentGuestCount++ } else { localLogger.error(`Interview id: ${interview.id} guest emails not present`, 'sendInterviewComingUpEmails') } } + + localLogger.debug(`[sendInterviewComingUpEmails]: Sent notifications for ${sentHostCount} hosts and ${sentGuestCount} guest of ${interviews.length} interviews which are coming soon.`) } /** @@ -293,8 +305,9 @@ async function sendInterviewCompletedEmails () { raw: true }) - localLogger.debug(`[sendInterviewCompletedEmails]: Found ${interviews.length} Interviews which must be ended by now.`) + localLogger.debug(`[sendInterviewCompletedEmails]: Found ${interviews.length} interviews which must be ended by now.`) + let sentCount = 0 for (const interview of interviews) { if (_.isEmpty(interview.hostEmail)) { localLogger.error(`Interview id: ${interview.id} host email not present`) @@ -315,7 +328,11 @@ async function sendInterviewCompletedEmails () { description: 'Interview Completed' } }) + + sentCount++ } + + localLogger.debug(`[sendInterviewCompletedEmails]: Sent notifications for ${sentCount} of ${interviews.length} interviews which must be ended by now.`) } /** @@ -337,8 +354,6 @@ async function sendPostInterviewActionEmails () { }] }) - localLogger.debug(`[sendPostInterviewActionEmails]: Found ${completedJobCandidates.length} Job Candidates with interview completed awaiting for an action.`) - // get all project ids for this job candidates const jobs = await Job.findAll({ where: { @@ -350,6 +365,10 @@ async function sendPostInterviewActionEmails () { }) const projectIds = _.uniq(_.map(jobs, job => job.projectId)) + + localLogger.debug(`[sendPostInterviewActionEmails]: Found ${projectIds.length} projects with ${completedJobCandidates.length} Job Candidates with interview completed awaiting for an action.`) + + let sentCount = 0 for (const projectId of projectIds) { const project = await getProjectWithId(projectId) if (!project) { continue } @@ -383,7 +402,11 @@ async function sendPostInterviewActionEmails () { description: 'Post Interview Candidate Action Reminder' } }) + + sentCount++ } + + localLogger.debug(`[sendPostInterviewActionEmails]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Job Candidates with interview completed awaiting for an action.`) } /** @@ -419,8 +442,9 @@ async function sendResourceBookingExpirationEmails () { }) const projectIds = _.uniq(_.map(expiringResourceBookings, rb => rb.projectId)) - localLogger.debug(`[sendResourceBookingExpirationEmails]: Found ${projectIds.length} project with ${expiringResourceBookings.length} Resource Bookings expiring in less than 3 weeks.`) + localLogger.debug(`[sendResourceBookingExpirationEmails]: Found ${projectIds.length} projects with ${expiringResourceBookings.length} Resource Bookings expiring in less than 3 weeks.`) + let sentCount = 0 for (const projectId of projectIds) { const project = await getProjectWithId(projectId) if (!project) { continue } @@ -458,7 +482,11 @@ async function sendResourceBookingExpirationEmails () { description: 'Upcoming Resource Booking Expiration' } }) + + sentCount++ } + + localLogger.debug(`[sendResourceBookingExpirationEmails]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Resource Bookings expiring in less than 3 weeks.`) } /** From 013c8548e320b416ea4f752bdd8b87eda4e45261 Mon Sep 17 00:00:00 2001 From: urwithat Date: Mon, 9 Aug 2021 19:55:11 +0530 Subject: [PATCH 04/16] Stripe Config --- config/default.js | 5 ++++- src/services/TeamService.js | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/config/default.js b/config/default.js index 1ddb0594..52923d7f 100644 --- a/config/default.js +++ b/config/default.js @@ -265,5 +265,8 @@ module.exports = { // The interview completed past time for fetching interviews INTERVIEW_COMPLETED_PAST_TIME: process.env.INTERVIEW_COMPLETED_PAST_TIME || 'PT4H', // The time before resource booking expiry when we should start sending notifications - RESOURCE_BOOKING_EXPIRY_TIME: process.env.RESOURCE_BOOKING_EXPIRY_TIME || 'P21D' + RESOURCE_BOOKING_EXPIRY_TIME: process.env.RESOURCE_BOOKING_EXPIRY_TIME || 'P21D', + // The Stripe + STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY, + CURRENCY: process.env.CURRENCY || 'usd' } diff --git a/src/services/TeamService.js b/src/services/TeamService.js index cfac33db..da4edb4d 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -19,7 +19,7 @@ const { getAuditM2Muser } = require('../common/helper') const { matchedSkills, unMatchedSkills } = require('../../scripts/emsi-mapping/esmi-skills-mapping') const Role = models.Role const RoleSearchRequest = models.RoleSearchRequest -const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); +const stripe = require("stripe")(config.STRIPE_SECRET_KEY); const emailTemplates = helper.getEmailTemplatesForKey('teamTemplates') @@ -1174,7 +1174,7 @@ suggestMembers.schema = Joi.object().keys({ async function createPayment(totalAmount) { const paymentIntent = await stripe.paymentIntents.create({ amount: totalAmount, - currency: process.env.CURRENCY, + currency: config.CURRENCY, }); return { paymentIntentToken: paymentIntent.client_secret }; } From 619902ea20b3d769ce7a58f397b43aa56b3ddfa2 Mon Sep 17 00:00:00 2001 From: Arpitkumar Chaudhari Date: Tue, 10 Aug 2021 12:46:29 +0530 Subject: [PATCH 05/16] Updating amount logic --- src/services/TeamService.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 35269e8d..576f198b 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -1165,11 +1165,12 @@ suggestMembers.schema = Joi.object().keys({ /** * Calculates total amount - * @param {Object} body + * @param {Object} amount * @returns {int} totalAmount */ - async function calculateAmount(body) { - const totalAmount = body.numberOfResources * body.rates * body.durationWeeks; + async function calculateAmount(amount) { + let totalAmount = 0; + _.forEach(amount, amt => totalAmount += amt.numberOfResources * amt.rate * amt.durationWeeks) return { totalAmount }; } @@ -1179,8 +1180,9 @@ suggestMembers.schema = Joi.object().keys({ * @returns {string} paymentIntentToken */ async function createPayment(totalAmount) { + const dollarToCents = (totalAmount*100); const paymentIntent = await stripe.paymentIntents.create({ - amount: totalAmount, + amount: dollarToCents, currency: process.env.CURRENCY, }); return { paymentIntentToken: paymentIntent.client_secret }; From e7c70d69d9c460434d09359ac922734f20a2fef5 Mon Sep 17 00:00:00 2001 From: Arpitkumar Chaudhari Date: Tue, 10 Aug 2021 16:11:04 +0530 Subject: [PATCH 06/16] Added scopes for calculateAmount & createPayment APIs --- src/routes/TeamRoutes.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/routes/TeamRoutes.js b/src/routes/TeamRoutes.js index 3c83d5f2..afc4bf87 100644 --- a/src/routes/TeamRoutes.js +++ b/src/routes/TeamRoutes.js @@ -112,12 +112,16 @@ module.exports = { post: { controller: "TeamController", method: "calculateAmount", + auth: 'jwt', + scopes: [constants.Scopes.CREATE_TAAS_TEAM] }, }, "/taas-teams/createPayment": { post: { controller: "TeamController", method: "createPayment", + auth: 'jwt', + scopes: [constants.Scopes.CREATE_TAAS_TEAM] }, } } From 258340969351268a3958c15d7de1e791cb076558 Mon Sep 17 00:00:00 2001 From: Arpitkumar Chaudhari Date: Wed, 11 Aug 2021 09:06:45 +0530 Subject: [PATCH 07/16] #443 & Stripe Connectivity Issues --- docs/swagger.yaml | 5 +---- src/services/TeamService.js | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 2ab802b2..3332dfac 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -5698,12 +5698,9 @@ components: numberOfResources: type: number description: "No. of resources required." - rates: + rate: type: number description: "Weekly rates" - durationWeeks: - type: number - description: "No. of weeks" CalculateAmountResponse: properties: totalAmount: diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 576f198b..a76e2dac 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -20,7 +20,7 @@ const { getAuditM2Muser } = require('../common/helper') const { matchedSkills, unMatchedSkills } = require('../../scripts/emsi-mapping/esmi-skills-mapping') const Role = models.Role const RoleSearchRequest = models.RoleSearchRequest -const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); +const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY,{maxNetworkRetries: 5}); const emailTemplates = _.mapValues(emailTemplateConfig, (template) => { return { @@ -1170,7 +1170,7 @@ suggestMembers.schema = Joi.object().keys({ */ async function calculateAmount(amount) { let totalAmount = 0; - _.forEach(amount, amt => totalAmount += amt.numberOfResources * amt.rate * amt.durationWeeks) + _.forEach(amount, amt => totalAmount += amt.numberOfResources * amt.rate) return { totalAmount }; } From e14172b08f4fe31f47bd0693eafeefc23bf1354c Mon Sep 17 00:00:00 2001 From: Arpitkumar Chaudhari Date: Wed, 11 Aug 2021 09:06:45 +0530 Subject: [PATCH 08/16] https://github.com/topcoder-platform/taas-app/issues/443 & Stripe Connectivity Issues --- docs/swagger.yaml | 5 +---- src/services/TeamService.js | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 2ab802b2..3332dfac 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -5698,12 +5698,9 @@ components: numberOfResources: type: number description: "No. of resources required." - rates: + rate: type: number description: "Weekly rates" - durationWeeks: - type: number - description: "No. of weeks" CalculateAmountResponse: properties: totalAmount: diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 576f198b..a76e2dac 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -20,7 +20,7 @@ const { getAuditM2Muser } = require('../common/helper') const { matchedSkills, unMatchedSkills } = require('../../scripts/emsi-mapping/esmi-skills-mapping') const Role = models.Role const RoleSearchRequest = models.RoleSearchRequest -const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); +const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY,{maxNetworkRetries: 5}); const emailTemplates = _.mapValues(emailTemplateConfig, (template) => { return { @@ -1170,7 +1170,7 @@ suggestMembers.schema = Joi.object().keys({ */ async function calculateAmount(amount) { let totalAmount = 0; - _.forEach(amount, amt => totalAmount += amt.numberOfResources * amt.rate * amt.durationWeeks) + _.forEach(amount, amt => totalAmount += amt.numberOfResources * amt.rate) return { totalAmount }; } From cdbac5ede62015c39ae467c3e1ade6772a27691a Mon Sep 17 00:00:00 2001 From: yoution Date: Wed, 11 Aug 2021 15:59:33 +0800 Subject: [PATCH 09/16] fix: update ROLE_MATCHING_RATE to 0.66 --- config/default.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/default.js b/config/default.js index 52923d7f..1a012a6d 100644 --- a/config/default.js +++ b/config/default.js @@ -177,7 +177,7 @@ module.exports = { DEFAULT_TIMELINE_TEMPLATE_ID: process.env.DEFAULT_TIMELINE_TEMPLATE_ID || '53a307ce-b4b3-4d6f-b9a1-3741a58f77e6', DEFAULT_TRACK_ID: process.env.DEFAULT_TRACK_ID || '9b6fc876-f4d9-4ccb-9dfd-419247628825', // the minimum matching rate when searching roles by skills - ROLE_MATCHING_RATE: process.env.ROLE_MATCHING_RATE || 0.70, + ROLE_MATCHING_RATE: process.env.ROLE_MATCHING_RATE || 0.66, // member groups representing Wipro or TopCoder employee INTERNAL_MEMBER_GROUPS: process.env.INTERNAL_MEMBER_GROUPS || ['20000000', '20000001', '20000003', '20000010', '20000015'], // Topcoder skills cache time in minutes From 354b1c5ea54ecda95598becd68c27fa9362582b7 Mon Sep 17 00:00:00 2001 From: yoution Date: Wed, 11 Aug 2021 16:23:13 +0800 Subject: [PATCH 10/16] fix: taas 412 add skill and unmatch skills for role --- src/services/TeamService.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index a14b29df..f6cd6612 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -741,6 +741,8 @@ async function roleSearchRequest (currentUser, data) { if (!_.isUndefined(data.roleId)) { role = await Role.findById(data.roleId) role = role.toJSON() + role.matchedSkills = role.listOfSkills + role.unMatchedSkills = [] role.skillsMatch = 1 // if skills is provided then use skills to find role } else if (!_.isUndefined(data.skills)) { From 3282d3a87cdb03e94b12deacd54da6813349dd81 Mon Sep 17 00:00:00 2001 From: yoution Date: Thu, 12 Aug 2021 12:44:36 +0800 Subject: [PATCH 11/16] fix: issue taas#462 --- src/services/TeamService.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index f6cd6612..55bae9bd 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -793,7 +793,8 @@ async function getRoleBySkills (skills) { where: { listOfSkills: { [Op.overlap]: skills } }, raw: true } - const roles = await Role.findAll(queryCriteria) + let roles = await Role.findAll(queryCriteria) + roles = _.filter(roles, role => _.find(role.rates, r => r.global)) if (roles.length > 0) { let result = _.each(roles, role => { // role matched skills list From 9cd777e57156fb8f9f23509d59067e34107adc35 Mon Sep 17 00:00:00 2001 From: Arpitkumar Chaudhari Date: Thu, 12 Aug 2021 13:44:27 +0530 Subject: [PATCH 12/16] API to identify whether member is external or internal. --- docs/swagger.yaml | 61 ++++++++++++++++++++++++++++++- src/controllers/TeamController.js | 13 ++++++- src/routes/TeamRoutes.js | 8 +++- 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 6f67d13b..6c2c9cde 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -3538,7 +3538,56 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Error" + $ref: "#/components/schemas/Error" + /taas-teams/isExternalMember: + post: + tags: + - Teams + description: | + Finds whether member is internal or external + + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/IsExternalMemberRequestBody" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/IsExternalMemberResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "409": + description: Conflict + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" /taas-teams/members-suggest/{fragment}: get: tags: @@ -5772,6 +5821,16 @@ components: paymentIntentToken: type: string description: " Token required by stripe for completing payment." + IsExternalMemberRequestBody: + properties: + totalAmount: + type: number + description: "Member id" + IsExternalMemberResponse: + properties: + paymentIntentToken: + type: boolean + description: "Is the user external member" SubmitTeamRequestBody: properties: teamName: diff --git a/src/controllers/TeamController.js b/src/controllers/TeamController.js index e34fa943..addb01dd 100644 --- a/src/controllers/TeamController.js +++ b/src/controllers/TeamController.js @@ -173,6 +173,16 @@ async function createPayment(req, res) { res.send(await service.createPayment(req.body.totalAmount)); } +/** + * + * @param req the request + * @param res the response + */ + async function isExternalMember(req, res) { + res.send(await service.isExternalMember(req.body.memberId)); +} + + module.exports = { searchTeams, getTeam, @@ -189,5 +199,6 @@ module.exports = { searchSkills, suggestMembers, createPayment, - calculateAmount + calculateAmount, + isExternalMember } diff --git a/src/routes/TeamRoutes.js b/src/routes/TeamRoutes.js index afc4bf87..923feb8e 100644 --- a/src/routes/TeamRoutes.js +++ b/src/routes/TeamRoutes.js @@ -123,5 +123,11 @@ module.exports = { auth: 'jwt', scopes: [constants.Scopes.CREATE_TAAS_TEAM] }, -} + }, + "/taas-teams/isExternalMember": { + post: { + controller: "TeamController", + method: "isExternalMember" + } + }, } From 49580d92fab68032e37794f108f42bd18c564282 Mon Sep 17 00:00:00 2001 From: Arpitkumar Chaudhari Date: Thu, 12 Aug 2021 16:06:15 +0530 Subject: [PATCH 13/16] Adding Authentication to isExternalMember API --- src/routes/TeamRoutes.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/routes/TeamRoutes.js b/src/routes/TeamRoutes.js index 923feb8e..1412b9b9 100644 --- a/src/routes/TeamRoutes.js +++ b/src/routes/TeamRoutes.js @@ -127,7 +127,9 @@ module.exports = { "/taas-teams/isExternalMember": { post: { controller: "TeamController", - method: "isExternalMember" + method: "isExternalMember", + auth: 'jwt', + scopes: [] } }, } From c8019b189a71fafc783b7a4df0d292531a20543c Mon Sep 17 00:00:00 2001 From: yoution Date: Fri, 13 Aug 2021 09:21:35 +0800 Subject: [PATCH 14/16] fix: issue topcoder-platform/taas-app#475 --- src/services/TeamService.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 55bae9bd..c2d43f3d 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -794,7 +794,7 @@ async function getRoleBySkills (skills) { raw: true } let roles = await Role.findAll(queryCriteria) - roles = _.filter(roles, role => _.find(role.rates, r => r.global)) + roles = _.filter(roles, role => _.find(role.rates, r => r.global && r.rate20Global && r.rate30Global)) if (roles.length > 0) { let result = _.each(roles, role => { // role matched skills list @@ -813,7 +813,10 @@ async function getRoleBySkills (skills) { } } // if no matching role found then return Custom role or empty object - return await Role.findOne({ where: { name: { [Op.iLike]: 'Custom' } }, raw: true }) || {} + const customRole = await Role.findOne({ where: { name: { [Op.iLike]: 'Custom' } }, raw: true }) || {} + customRole.rates[0].rate20Global = customRole.rates[0].global * 0.75 + customRole.rates[0].rate30Global = customRole.rates[0].global * 0.5 + return customRole } getRoleBySkills.schema = Joi.object() From af3feff2e7ffafa05f0f8e9616e20e46fed750e3 Mon Sep 17 00:00:00 2001 From: yoution Date: Fri, 13 Aug 2021 14:21:36 +0800 Subject: [PATCH 15/16] fix issue topcoder-platform/taas-app#462 --- src/services/TeamService.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/TeamService.js b/src/services/TeamService.js index c2d43f3d..25d511b3 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -814,8 +814,8 @@ async function getRoleBySkills (skills) { } // if no matching role found then return Custom role or empty object const customRole = await Role.findOne({ where: { name: { [Op.iLike]: 'Custom' } }, raw: true }) || {} - customRole.rates[0].rate20Global = customRole.rates[0].global * 0.75 - customRole.rates[0].rate30Global = customRole.rates[0].global * 0.5 + customRole.rates[0].rate30Global = customRole.rates[0].global * 0.75 + customRole.rates[0].rate20Global = customRole.rates[0].global * 0.5 return customRole } From d9387cf0f7be7b849c13dbbf1eee649b4b7dda0d Mon Sep 17 00:00:00 2001 From: Cagdas U Date: Fri, 13 Aug 2021 17:45:54 +0300 Subject: [PATCH 16/16] feat(teams): accept `intakeSource` in `createTeam` request Accept the `intakeSource` in `createTeam` request. Addresses https://github.com/topcoder-platform/taas-app/issues/486 --- docs/swagger.yaml | 3 +++ src/services/TeamService.js | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 6c2c9cde..245f6abc 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -5842,6 +5842,9 @@ components: refCode: type: string description: "Optional referral code" + intakeSource: + type: string + description: "The source of the intake." positions: type: array description: "The array of positions" diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 25d511b3..d6870bfe 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -1038,7 +1038,8 @@ async function createTeam (currentUser, data) { details: { positions: data.positions, utm: { - code: data.refCode + code: data.refCode, + intakeSource: data.intakeSource } } } @@ -1077,6 +1078,7 @@ createTeam.schema = Joi.object() teamName: Joi.string().required(), teamDescription: Joi.string(), refCode: Joi.string(), + intakeSource: Joi.string(), positions: Joi.array().items( Joi.object().keys({ roleName: Joi.string().required(),