Skip to content

Commit 8cb97d5

Browse files
authored
Merge pull request #492 from tejad/feature/notifications-api
Tasks 476 and 477#issuecomment-898886697
2 parents 48b3625 + c090db8 commit 8cb97d5

9 files changed

+206
-137
lines changed

app.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const eventHandlers = require('./src/eventHandlers')
1515
const interviewService = require('./src/services/InterviewService')
1616
const { processScheduler } = require('./src/services/PaymentSchedulerService')
1717
const { sendSurveys } = require('./src/services/SurveyService')
18-
const emailNotificationService = require('./src/services/EmailNotificationService')
18+
const notificationSchedulerService = require('./src/services/NotificationsSchedulerService')
1919

2020
// setup express app
2121
const app = express()
@@ -105,11 +105,11 @@ const server = app.listen(app.get('port'), () => {
105105
// schedule payment processing
106106
schedule.scheduleJob(config.PAYMENT_PROCESSING.CRON, processScheduler)
107107

108-
schedule.scheduleJob(config.CRON_CANDIDATE_REVIEW, emailNotificationService.sendCandidatesAvailableEmails)
109-
schedule.scheduleJob(config.CRON_INTERVIEW_COMING_UP, emailNotificationService.sendInterviewComingUpEmails)
110-
schedule.scheduleJob(config.CRON_INTERVIEW_COMPLETED, emailNotificationService.sendInterviewCompletedEmails)
111-
schedule.scheduleJob(config.CRON_POST_INTERVIEW, emailNotificationService.sendPostInterviewActionEmails)
112-
schedule.scheduleJob(config.CRON_UPCOMING_RESOURCE_BOOKING, emailNotificationService.sendResourceBookingExpirationEmails)
108+
schedule.scheduleJob(config.CRON_CANDIDATE_REVIEW, notificationSchedulerService.sendCandidatesAvailableNotifications)
109+
schedule.scheduleJob(config.CRON_INTERVIEW_COMING_UP, notificationSchedulerService.sendInterviewComingUpNotifications)
110+
schedule.scheduleJob(config.CRON_INTERVIEW_COMPLETED, notificationSchedulerService.sendInterviewCompletedNotifications)
111+
schedule.scheduleJob(config.CRON_POST_INTERVIEW, notificationSchedulerService.sendPostInterviewActionNotifications)
112+
schedule.scheduleJob(config.CRON_UPCOMING_RESOURCE_BOOKING, notificationSchedulerService.sendResourceBookingExpirationNotifications)
113113
})
114114

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

config/email_template.config.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ module.exports = {
112112
*/
113113
notificationEmailTemplates: {
114114
'taas.notification.job-candidate-resume-viewed': {
115-
subject: 'Topcoder - job candidate resume viewed',
115+
subject: 'Topcoder - Client View Resume for Job {{jobName}}',
116116
body: '',
117117
recipients: [],
118118
from: config.NOTIFICATION_SENDER_EMAIL,
@@ -161,14 +161,14 @@ module.exports = {
161161
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
162162
},
163163
'taas.notification.team-created': {
164-
subject: 'Topcoder - Team Created',
164+
subject: 'Topcoder - New Team {{teamName}} Created',
165165
body: '',
166166
recipients: [],
167167
from: config.NOTIFICATION_SENDER_EMAIL,
168168
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
169169
},
170170
'taas.notification.job-created': {
171-
subject: 'Topcoder - Job Created',
171+
subject: 'Topcoder - New Job {{jobTitle}} Created in Team {{teamName}}',
172172
body: '',
173173
recipients: [],
174174
from: config.NOTIFICATION_SENDER_EMAIL,
@@ -182,14 +182,14 @@ module.exports = {
182182
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
183183
},
184184
'taas.notification.job-candidate-selected': {
185-
subject: 'Topcoder - Job Candidate Selected',
185+
subject: 'Topcoder - Job Candidate {{userHandle}} Selected for {{jobTitle}} in Team {{teamName}}',
186186
body: '',
187187
recipients: config.NOTIFICATION_OPS_EMAILS,
188188
from: config.NOTIFICATION_SENDER_EMAIL,
189189
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
190190
},
191191
'taas.notification.resource-booking-placed': {
192-
subject: 'Topcoder - Resource Booking Placed',
192+
subject: 'Topcoder - Resource Booking {{userHandle}} Placed for Job {{jobTitle}} in Team {{teamName}}',
193193
body: '',
194194
recipients: [],
195195
from: config.NOTIFICATION_SENDER_EMAIL,

data/notifications-email-template.html

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,25 +101,23 @@
101101
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Job title</td>
102102
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">No of resource bookings</td>
103103
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Candidates</td>
104-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Status</td>
104+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Review</td>
105105
</tr>
106106
{{#each teamJobs}}
107107
<tr style="border:1px solid black;border-collapse:collapse">
108-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.title}}</td>
108+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
109+
<a href={{this.jobUrl}} target="_blank" rel="noopener noreferrer">{{this.title}}</a>
110+
</td>
109111
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.nResourceBookings}}</td>
110112
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
111113
<ul style="list-style-type:none;margin:0;padding:0;">
112114
{{#each this.jobCandidates}}
113-
<li><a href={{../reviewLink}} target="_blank" rel="noopener noreferrer">{{this.handle}}</a></li>
115+
<li>{{this.handle}}</li>
114116
{{/each}}
115117
</ul>
116118
</td>
117119
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
118-
<ul style="list-style-type:none;margin:0;padding:0;">
119-
{{#each this.jobCandidates}}
120-
<li>{{this.status}}</li>
121-
{{/each}}
122-
</ul>
120+
<a href={{this.reviewLink}} target="_blank" rel="noopener noreferrer">Link</a>
123121
</td>
124122
</tr>
125123
{{/each}}
@@ -136,7 +134,9 @@
136134
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Date and Time</td>
137135
</tr>
138136
<tr>
139-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.jobTitle}}</td>
137+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
138+
<a href={{this.jobUrl}} target="_blank" rel="noopener noreferrer">{{this.jobTitle}}</a>
139+
</td>
140140
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.handle}}</td>
141141
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
142142
<a href={{this.interviewLink}} target="_blank" rel="noopener noreferrer">Link</a></td>
@@ -160,7 +160,9 @@
160160
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Interviews</td>
161161
</tr>
162162
<tr>
163-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.jobTitle}}</td>
163+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
164+
<a href={{this.jobUrl}} target="_blank" rel="noopener noreferrer">{{this.jobTitle}}</a>
165+
</td>
164166
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.startTime}}</td>
165167
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
166168
<a href={{this.interviewLink}} target="_blank" rel="noopener noreferrer">Link</a></td>
@@ -178,7 +180,9 @@
178180
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Interviews</td>
179181
</tr>
180182
<tr>
181-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.jobTitle}}</td>
183+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
184+
<a href={{this.jobUrl}} target="_blank" rel="noopener noreferrer">{{this.jobTitle}}</a>
185+
</td>
182186
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.handle}}</td>
183187
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.startTime}}</td>
184188
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
@@ -205,7 +209,9 @@
205209
</tr>
206210
{{#each teamInterviews}}
207211
<tr>
208-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.jobTitle}}</td>
212+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
213+
<a href={{this.jobUrl}} target="_blank" rel="noopener noreferrer">{{this.jobTitle}}</a>
214+
</td>
209215
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.handle}}</td>
210216
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.startTime}}</td>
211217
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
@@ -224,7 +230,7 @@
224230

225231
{{#if notificationType.upcomingResourceBookingExpiration}}
226232
<span style="font-weight:bold;">Team Name:</span>
227-
{{teamName}}
233+
<a href={{this.teamUrl}} target="_blank" rel="noopener noreferrer">{{teamName}}</a>
228234
<table style="font-size:13px;border:1px solid black;border-collapse:collapse;width:95%;">
229235
<tr style="font-weight:bold;border:1px solid black;border-collapse:collapse">
230236
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">Job title</td>
@@ -233,8 +239,12 @@
233239
</tr>
234240
{{#each teamResourceBookings}}
235241
<tr>
236-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.jobTitle}}</td>
237-
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.handle}}</td>
242+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
243+
<a href={{this.jobUrl}} target="_blank" rel="noopener noreferrer">{{this.jobTitle}}</a>
244+
</td>
245+
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">
246+
<a href={{this.resourceBookingUrl}} target="_blank" rel="noopener noreferrer">{{this.handle}}</a>
247+
</td>
238248
<td style="border:1px solid black;border-collapse:collapse;text-align:center;line-height:1.5;">{{this.endDate}}</td>
239249
</tr>
240250
{{/each}}
@@ -246,7 +256,7 @@
246256

247257
Your resume for the job "{{jobName}}" has been viewed by the client. <br/>
248258
{{/if}}
249-
259+
250260
{{#if notificationType.newTeamCreated}}
251261
<span style="font-weight:bold;">Team:</span>
252262
<a href={{teamUrl}} target="_blank" rel="noopener noreferrer">{{teamName}}</a>

src/eventHandlers/JobCandidateEventHandler.js

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -155,26 +155,28 @@ async function sendJobCandidateSelectedNotification (payload) {
155155
const project = await helper.getProjectById({ isMachine: true }, job.projectId)
156156
const jobUrl = `${config.TAAS_APP_URL}/${project.id}/positions/${job.id}`
157157
const teamUrl = `${config.TAAS_APP_URL}/${project.id}`
158+
const data = {
159+
subject: template.subject,
160+
teamName: project.name,
161+
teamUrl,
162+
jobTitle: job.title,
163+
jobDuration: job.duration,
164+
jobStartDate: helper.formatDateEDT(job.startDate),
165+
userHandle: user.handle,
166+
jobUrl,
167+
notificationType: {
168+
candidateSelected: true
169+
},
170+
description: 'Job Candidate Selected'
171+
}
172+
data.subject = await helper.substituteStringByObject(data.subject, data)
158173
const emailData = {
159174
serviceId: 'email',
160175
type: 'taas.notification.job-candidate-selected',
161176
details: {
162177
from: template.from,
163178
recipients: template.recipients,
164-
data: {
165-
subject: template.subject,
166-
teamName: project.name,
167-
teamUrl,
168-
jobTitle: job.title,
169-
jobDuration: job.duration,
170-
jobStartDate: helper.formatDateEDT(job.startDate),
171-
userHandle: user.handle,
172-
jobUrl,
173-
notificationType: {
174-
candidateSelected: true
175-
},
176-
description: 'Job Candidate Selected'
177-
},
179+
data,
178180
sendgridTemplateId: template.sendgridTemplateId,
179181
version: 'v3'
180182
}

src/eventHandlers/JobEventHandler.js

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,25 +84,28 @@ async function sendNotifications (payload) {
8484
}
8585
const template = helper.getEmailTemplatesForKey('notificationEmailTemplates')['taas.notification.job-created']
8686
const project = await helper.getProjectById({ isMachine: true }, payload.value.projectId)
87+
const data = {
88+
subject: template.subject,
89+
teamName: project.name,
90+
teamURL: `${config.TAAS_APP_URL}/${project.id}`,
91+
jobTitle: payload.value.title,
92+
jobURL: `${config.TAAS_APP_URL}/${project.id}/positions/${payload.value.id}`,
93+
jobDuration: payload.value.duration,
94+
jobStartDate: helper.formatDateEDT(payload.value.startDate),
95+
notificationType: {
96+
newJobCreated: true
97+
},
98+
description: 'New Job Created'
99+
}
100+
data.subject = await helper.substituteStringByObject(data.subject, data)
101+
87102
const emailData = {
88103
serviceId: 'email',
89104
type: 'taas.notification.job-created',
90105
details: {
91106
from: template.from,
92107
recipients: _.map(project.members, m => _.pick(m, 'email')),
93-
data: {
94-
subject: template.subject,
95-
teamName: project.name,
96-
teamURL: `${config.TAAS_APP_URL}/${project.id}`,
97-
jobTitle: payload.value.title,
98-
jobURL: `${config.TAAS_APP_URL}/${project.id}/positions/${payload.value.id}`,
99-
jobDuration: payload.value.duration,
100-
jobStartDate: helper.formatDateEDT(payload.value.startDate),
101-
notificationType: {
102-
newJobCreated: true
103-
},
104-
description: 'New Job Created'
105-
},
108+
data,
106109
sendgridTemplateId: template.sendgridTemplateId,
107110
version: 'v3'
108111
}

src/eventHandlers/ResourceBookingEventHandler.js

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,26 +89,28 @@ async function sendPlacedNotifications (payload) {
8989
const recipients = _.map(project.members, m => _.pick(m, 'email'))
9090
const jobUrl = `${config.TAAS_APP_URL}/${project.id}/positions/${job.id}`
9191
const teamUrl = `${config.TAAS_APP_URL}/${project.id}`
92+
const data = {
93+
subject: template.subject,
94+
teamName: project.name,
95+
teamUrl,
96+
jobTitle: job.title,
97+
jobUrl,
98+
userHandle: user.handle,
99+
startDate: resourceBooking.startDate,
100+
endDate: resourceBooking.endDate,
101+
notificationType: {
102+
resourceBookingPlaced: true
103+
},
104+
description: 'Resource Booking is Placed'
105+
}
106+
data.subject = await helper.substituteStringByObject(data.subject, data)
92107
const emailData = {
93108
serviceId: 'email',
94109
type: 'taas.notification.resource-booking-placed',
95110
details: {
96111
from: template.from,
97112
recipients,
98-
data: {
99-
subject: template.subject,
100-
teamName: project.name,
101-
teamUrl,
102-
jobTitle: job.title,
103-
jobUrl,
104-
userHandle: user.handle,
105-
startDate: resourceBooking.startDate,
106-
endDate: resourceBooking.endDate,
107-
notificationType: {
108-
resourceBookingPlaced: true
109-
},
110-
description: 'Resource Booking is Placed'
111-
},
113+
data,
112114
sendgridTemplateId: template.sendgridTemplateId,
113115
version: 'v3'
114116
}

src/eventHandlers/TeamEventHandler.js

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,30 @@ const helper = require('../common/helper')
1515
*/
1616
async function sendNotificationEmail (payload) {
1717
const template = helper.getEmailTemplatesForKey('notificationEmailTemplates')['taas.notification.team-created']
18+
const data = {
19+
subject: template.subject,
20+
teamName: payload.project.name,
21+
teamUrl: `${config.TAAS_APP_URL}/${payload.project.id}`,
22+
jobList: _.map(payload.jobs, j => ({
23+
title: j.title,
24+
duration: j.duration,
25+
startDate: helper.formatDateEDT(j.startDate),
26+
jobUrl: `${config.TAAS_APP_URL}/${payload.project.id}/positions/${j.id}`
27+
})),
28+
notificationType: {
29+
newTeamCreated: true
30+
},
31+
description: 'New Team Created'
32+
}
33+
data.subject = await helper.substituteStringByObject(data.subject, data)
34+
1835
const emailData = {
1936
serviceId: 'email',
2037
type: 'taas.notification.team-created',
2138
details: {
2239
from: template.from,
2340
recipients: _.map(payload.project.members, m => _.pick(m, 'email')),
24-
data: {
25-
subject: template.subject,
26-
teamName: payload.project.name,
27-
teamUrl: `${config.TAAS_APP_URL}/${payload.project.id}`,
28-
jobList: _.map(payload.jobs, j => ({
29-
title: j.title,
30-
duration: j.duration,
31-
startDate: helper.formatDateEDT(j.startDate),
32-
jobUrl: `${config.TAAS_APP_URL}/${payload.project.id}/positions/${j.id}`
33-
})),
34-
notificationType: {
35-
newTeamCreated: true
36-
},
37-
description: 'New Team Created'
38-
},
41+
data,
3942
sendgridTemplateId: template.sendgridTemplateId,
4043
version: 'v3'
4144
}

src/services/JobCandidateService.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const logger = require('../common/logger')
1414
const errors = require('../common/errors')
1515
const models = require('../models')
1616
const JobService = require('./JobService')
17-
const EmailNotificationService = require('./EmailNotificationService')
17+
const NotificationSchedulerService = require('./NotificationsSchedulerService')
1818
const JobCandidate = models.JobCandidate
1919
const esClient = helper.getESClient()
2020

@@ -376,7 +376,7 @@ async function downloadJobCandidateResume (currentUser, id) {
376376
const { handle } = await helper.getUserById(jobCandidate.userId, true)
377377
const { email } = await helper.getMemberDetailsByHandle(handle)
378378

379-
await EmailNotificationService.sendEmail(currentUser, {
379+
await NotificationSchedulerService.sendNotification(currentUser, {
380380
template: 'taas.notification.job-candidate-resume-viewed',
381381
recipients: [email],
382382
data: {

0 commit comments

Comments
 (0)