Skip to content

Commit 8f55b21

Browse files
authored
Merge pull request #233 from topcoder-platform/dev
Deploy to Production for Interview Scheduler
2 parents 2d0e55b + 813935b commit 8f55b21

36 files changed

+11888
-2312
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
AUTH0_AUDIENCE_UBAHN=
3535
AUTH0_CLIENT_ID=
3636
AUTH0_CLIENT_SECRET=
37-
37+
# necessary if you'll utilize email functionality of interviews
38+
INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID=
39+
INTERVIEW_INVITATION_SENDER_EMAIL=
3840
# Locally deployed services (via docker-compose)
3941
ES_HOST=dockerhost:9200
4042
DATABASE_URL=postgres://postgres:postgres@dockerhost:5432/postgres

app-constants.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,30 @@ const Scopes = {
4444
READ_WORK_PERIOD_PAYMENT: 'read:taas-workPeriodPayments',
4545
CREATE_WORK_PERIOD_PAYMENT: 'create:taas-workPeriodPayments',
4646
UPDATE_WORK_PERIOD_PAYMENT: 'update:taas-workPeriodPayments',
47-
ALL_WORK_PERIOD_PAYMENT: 'all:taas-workPeriodPayments'
47+
ALL_WORK_PERIOD_PAYMENT: 'all:taas-workPeriodPayments',
48+
// interview
49+
READ_INTERVIEW: 'read:taas-interviews',
50+
CREATE_INTERVIEW: 'create:taas-interviews',
51+
UPDATE_INTERVIEW: 'update:taas-interviews',
52+
ALL_INTERVIEW: 'all:taas-interviews'
53+
}
54+
55+
// Interview related constants
56+
const Interviews = {
57+
Status: {
58+
Scheduling: 'Scheduling',
59+
Scheduled: 'Scheduled',
60+
RequestedForReschedule: 'Requested for reschedule',
61+
Rescheduled: 'Rescheduled',
62+
Completed: 'Completed',
63+
Cancelled: 'Cancelled'
64+
},
65+
// key: template name in x.ai, value: duration
66+
XaiTemplate: {
67+
'interview-30': 30,
68+
'interview-60': 60
69+
},
70+
MaxAllowedCount: 3
4871
}
4972

5073
const ChallengeStatus = {
@@ -62,6 +85,7 @@ module.exports = {
6285
UserRoles,
6386
FullManagePermissionRoles,
6487
Scopes,
88+
Interviews,
6589
ChallengeStatus,
6690
PaymentProcessingSwitch
6791
}

app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ const express = require('express')
99
const cors = require('cors')
1010
const HttpStatus = require('http-status-codes')
1111
const interceptor = require('express-interceptor')
12+
const schedule = require('node-schedule')
1213
const logger = require('./src/common/logger')
1314
const eventHandlers = require('./src/eventHandlers')
15+
const interviewService = require('./src/services/InterviewService')
1416

1517
// setup express app
1618
const app = express()
@@ -93,6 +95,8 @@ app.use((err, req, res, next) => {
9395
const server = app.listen(app.get('port'), () => {
9496
logger.info({ component: 'app', message: `Express server listening on port ${app.get('port')}` })
9597
eventHandlers.init()
98+
// schedule updateCompletedInterviews to run every hour
99+
schedule.scheduleJob('0 0 * * * *', interviewService.updateCompletedInterviews)
96100
})
97101

98102
if (process.env.NODE_ENV === 'test') {

config/default.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ module.exports = {
126126
TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC: process.env.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC || 'taas.workperiodpayment.update',
127127
// the delete work period payment entity Kafka message topic
128128
TAAS_WORK_PERIOD_PAYMENT_DELETE_TOPIC: process.env.TAAS_WORK_PERIOD_PAYMENT_DELETE_TOPIC || 'taas.workperiodpayment.delete',
129+
// topics for interview service
130+
// the request interview Kafka message topic
131+
TAAS_INTERVIEW_REQUEST_TOPIC: process.env.TAAS_INTERVIEW_REQUEST_TOPIC || 'taas.interview.requested',
132+
// the interview update Kafka message topic
133+
TAAS_INTERVIEW_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_UPDATE_TOPIC || 'taas.interview.update',
134+
// the interview bulk update Kafka message topic
135+
TAAS_INTERVIEW_BULK_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_BULK_UPDATE_TOPIC || 'taas.interview.bulkUpdate',
129136

130137
// the Kafka message topic for sending email
131138
EMAIL_TOPIC: process.env.EMAIL_TOPIC || 'external.action.email',
@@ -135,10 +142,20 @@ module.exports = {
135142
// the emails address for receiving the issue report
136143
// REPORT_ISSUE_EMAILS may contain comma-separated list of email which is converted to array
137144
REQUEST_EXTENSION_EMAILS: (process.env.REQUEST_EXTENSION_EMAILS || '').split(','),
145+
// the emails address for interview invitation
146+
// INTERVIEW_INVITATION_CC_LIST may contain comma-separated list of email which is converted to array
147+
INTERVIEW_INVITATION_CC_LIST: (process.env.INTERVIEW_INVITATION_CC_LIST || '').split(','),
148+
// INTERVIEW_INVITATION_RECIPIENTS_LIST may contain comma-separated list of email which is converted to array
149+
// scheduler@x.ai should be in the RECIPIENTS list
150+
INTERVIEW_INVITATION_RECIPIENTS_LIST: (process.env.INTERVIEW_INVITATION_RECIPIENTS_LIST || 'scheduler@topcoder.com').split(','),
138151
// SendGrid email template ID for reporting issue
139152
REPORT_ISSUE_SENDGRID_TEMPLATE_ID: process.env.REPORT_ISSUE_SENDGRID_TEMPLATE_ID,
140153
// SendGrid email template ID for requesting extension
141154
REQUEST_EXTENSION_SENDGRID_TEMPLATE_ID: process.env.REQUEST_EXTENSION_SENDGRID_TEMPLATE_ID,
155+
// SendGrid email template ID for interview invitation
156+
INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID: process.env.INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID,
157+
// The sender (aka `from`) email for invitation.
158+
INTERVIEW_INVITATION_SENDER_EMAIL: process.env.INTERVIEW_INVITATION_SENDER_EMAIL || 'talent@topcoder.com',
142159
// the URL where TaaS App is hosted
143160
TAAS_APP_URL: process.env.TAAS_APP_URL || 'https://platform.topcoder-dev.com/taas/myteams',
144161
// environment variables for Payment Service

config/email_template.config.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,44 @@ module.exports = {
5959
'{{text}}',
6060
recipients: config.REPORT_ISSUE_EMAILS,
6161
sendgridTemplateId: config.REQUEST_EXTENSION_SENDGRID_TEMPLATE_ID
62+
},
63+
64+
/* Request interview for a job candidate
65+
*
66+
* - interviewType: the x.ai interview type. Example: "interview-30"
67+
* - interviewRound: the round of the interview. Example: 2
68+
* - interviewDuration: duration of the interview, in minutes. Example: 30
69+
* - interviewerList: The list of interviewer email addresses. Example: "first@attendee.com, second@attendee.com"
70+
* - candidateId: the id of the jobCandidate. Example: "cc562545-7b75-48bf-87e7-50b3c57e41b1"
71+
* - candidateName: Full name of candidate. Example: "John Doe"
72+
* - jobName: The title of the job. Example: "TaaS API Misc Updates"
73+
*
74+
* Template (defined in SendGrid):
75+
* Subject: '{{interviewType}} tech interview with {{candidateName}} for {{jobName}} is requested by the Customer'
76+
* Body:
77+
* 'Hello!
78+
* <br /><br />
79+
* Congratulations, you have been selected to participate in a Topcoder Gig Work Interview!
80+
* <br /><br />
81+
* Please monitor your email for a response to this where you can coordinate your availability.
82+
* <br /><br />
83+
* Interviewee: {{candidateName}}<br />
84+
* Interviewer(s): {{interviewerList}}<br />
85+
* Interview Length: {{interviewDuration}} minutes
86+
* <br /><br />
87+
* /{{interviewType}}
88+
* <br /><br />
89+
* Topcoder Info:<br />
90+
* Note: "id: {{candidateId}}, round: {{interviewRound}}"'
91+
*
92+
* Note, that the template should be defined in SendGrid.
93+
* The subject & body above (identical to actual SendGrid template) is for reference purposes.
94+
* We won't pass subject & body but only substitutions (replacements in template subject/body).
95+
*/
96+
'interview-invitation': {
97+
from: config.INTERVIEW_INVITATION_SENDER_EMAIL,
98+
cc: config.INTERVIEW_INVITATION_CC_LIST,
99+
recipients: config.INTERVIEW_INVITATION_RECIPIENTS_LIST,
100+
sendgridTemplateId: config.INTERVIEW_INVITATION_SENDGRID_TEMPLATE_ID
62101
}
63102
}

data/demo-data.json

Lines changed: 2386 additions & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)