diff --git a/app.js b/app.js
index 3e60e0e8..248c386e 100644
--- a/app.js
+++ b/app.js
@@ -15,7 +15,7 @@ const eventHandlers = require('./src/eventHandlers')
const interviewService = require('./src/services/InterviewService')
const { processScheduler } = require('./src/services/PaymentSchedulerService')
const { sendSurveys } = require('./src/services/SurveyService')
-const emailNotificationService = require('./src/services/EmailNotificationService')
+const notificationSchedulerService = require('./src/services/NotificationsSchedulerService')
// setup express app
const app = express()
@@ -105,11 +105,11 @@ const server = app.listen(app.get('port'), () => {
// schedule payment processing
schedule.scheduleJob(config.PAYMENT_PROCESSING.CRON, processScheduler)
- schedule.scheduleJob(config.CRON_CANDIDATE_REVIEW, emailNotificationService.sendCandidatesAvailableEmails)
- schedule.scheduleJob(config.CRON_INTERVIEW_COMING_UP, emailNotificationService.sendInterviewComingUpEmails)
- schedule.scheduleJob(config.CRON_INTERVIEW_COMPLETED, emailNotificationService.sendInterviewCompletedEmails)
- schedule.scheduleJob(config.CRON_POST_INTERVIEW, emailNotificationService.sendPostInterviewActionEmails)
- schedule.scheduleJob(config.CRON_UPCOMING_RESOURCE_BOOKING, emailNotificationService.sendResourceBookingExpirationEmails)
+ schedule.scheduleJob(config.CRON_CANDIDATE_REVIEW, notificationSchedulerService.sendCandidatesAvailableNotifications)
+ schedule.scheduleJob(config.CRON_INTERVIEW_COMING_UP, notificationSchedulerService.sendInterviewComingUpNotifications)
+ schedule.scheduleJob(config.CRON_INTERVIEW_COMPLETED, notificationSchedulerService.sendInterviewCompletedNotifications)
+ schedule.scheduleJob(config.CRON_POST_INTERVIEW, notificationSchedulerService.sendPostInterviewActionNotifications)
+ schedule.scheduleJob(config.CRON_UPCOMING_RESOURCE_BOOKING, notificationSchedulerService.sendResourceBookingExpirationNotifications)
})
if (process.env.NODE_ENV === 'test') {
diff --git a/config/email_template.config.js b/config/email_template.config.js
index a61cd355..524d54f1 100644
--- a/config/email_template.config.js
+++ b/config/email_template.config.js
@@ -112,7 +112,7 @@ module.exports = {
*/
notificationEmailTemplates: {
'taas.notification.job-candidate-resume-viewed': {
- subject: 'Topcoder - job candidate resume viewed',
+ subject: 'Topcoder - Client View Resume for Job {{jobName}}',
body: '',
recipients: [],
from: config.NOTIFICATION_SENDER_EMAIL,
@@ -161,14 +161,14 @@ module.exports = {
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
},
'taas.notification.team-created': {
- subject: 'Topcoder - Team Created',
+ subject: 'Topcoder - New Team {{teamName}} Created',
body: '',
recipients: [],
from: config.NOTIFICATION_SENDER_EMAIL,
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
},
'taas.notification.job-created': {
- subject: 'Topcoder - Job Created',
+ subject: 'Topcoder - New Job {{jobTitle}} Created in Team {{teamName}}',
body: '',
recipients: [],
from: config.NOTIFICATION_SENDER_EMAIL,
@@ -182,14 +182,14 @@ module.exports = {
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
},
'taas.notification.job-candidate-selected': {
- subject: 'Topcoder - Job Candidate Selected',
+ subject: 'Topcoder - Job Candidate {{userHandle}} Selected for {{jobTitle}} in Team {{teamName}}',
body: '',
recipients: config.NOTIFICATION_OPS_EMAILS,
from: config.NOTIFICATION_SENDER_EMAIL,
sendgridTemplateId: config.NOTIFICATION_SENDGRID_TEMPLATE_ID
},
'taas.notification.resource-booking-placed': {
- subject: 'Topcoder - Resource Booking Placed',
+ subject: 'Topcoder - Resource Booking {{userHandle}} Placed for Job {{jobTitle}} in Team {{teamName}}',
body: '',
recipients: [],
from: config.NOTIFICATION_SENDER_EMAIL,
diff --git a/data/notifications-email-template.html b/data/notifications-email-template.html
index df1032a5..f0da558d 100644
--- a/data/notifications-email-template.html
+++ b/data/notifications-email-template.html
@@ -101,25 +101,23 @@
- {{this.jobTitle}} |
+
+ {{this.jobTitle}}
+ |
{{this.handle}} |
{{this.startTime}} |
@@ -224,7 +230,7 @@
{{#if notificationType.upcomingResourceBookingExpiration}}
Team Name:
- {{teamName}}
+ {{teamName}}
Job title |
@@ -233,8 +239,12 @@
{{#each teamResourceBookings}}
- {{this.jobTitle}} |
- {{this.handle}} |
+
+ {{this.jobTitle}}
+ |
+
+ {{this.handle}}
+ |
{{this.endDate}} |
{{/each}}
@@ -246,7 +256,7 @@
Your resume for the job "{{jobName}}" has been viewed by the client.
{{/if}}
-
+
{{#if notificationType.newTeamCreated}}
Team:
{{teamName}}
diff --git a/src/eventHandlers/JobCandidateEventHandler.js b/src/eventHandlers/JobCandidateEventHandler.js
index 127366ee..c2aef63a 100644
--- a/src/eventHandlers/JobCandidateEventHandler.js
+++ b/src/eventHandlers/JobCandidateEventHandler.js
@@ -155,26 +155,28 @@ async function sendJobCandidateSelectedNotification (payload) {
const project = await helper.getProjectById({ isMachine: true }, job.projectId)
const jobUrl = `${config.TAAS_APP_URL}/${project.id}/positions/${job.id}`
const teamUrl = `${config.TAAS_APP_URL}/${project.id}`
+ const data = {
+ subject: template.subject,
+ teamName: project.name,
+ teamUrl,
+ jobTitle: job.title,
+ jobDuration: job.duration,
+ jobStartDate: helper.formatDateEDT(job.startDate),
+ userHandle: user.handle,
+ jobUrl,
+ notificationType: {
+ candidateSelected: true
+ },
+ description: 'Job Candidate Selected'
+ }
+ data.subject = await helper.substituteStringByObject(data.subject, data)
const emailData = {
serviceId: 'email',
type: 'taas.notification.job-candidate-selected',
details: {
from: template.from,
recipients: template.recipients,
- data: {
- subject: template.subject,
- teamName: project.name,
- teamUrl,
- jobTitle: job.title,
- jobDuration: job.duration,
- jobStartDate: helper.formatDateEDT(job.startDate),
- userHandle: user.handle,
- jobUrl,
- notificationType: {
- candidateSelected: true
- },
- description: 'Job Candidate Selected'
- },
+ data,
sendgridTemplateId: template.sendgridTemplateId,
version: 'v3'
}
diff --git a/src/eventHandlers/JobEventHandler.js b/src/eventHandlers/JobEventHandler.js
index 8f2b75c1..53d7ba13 100644
--- a/src/eventHandlers/JobEventHandler.js
+++ b/src/eventHandlers/JobEventHandler.js
@@ -84,25 +84,28 @@ async function sendNotifications (payload) {
}
const template = helper.getEmailTemplatesForKey('notificationEmailTemplates')['taas.notification.job-created']
const project = await helper.getProjectById({ isMachine: true }, payload.value.projectId)
+ const data = {
+ subject: template.subject,
+ teamName: project.name,
+ teamURL: `${config.TAAS_APP_URL}/${project.id}`,
+ jobTitle: payload.value.title,
+ jobURL: `${config.TAAS_APP_URL}/${project.id}/positions/${payload.value.id}`,
+ jobDuration: payload.value.duration,
+ jobStartDate: helper.formatDateEDT(payload.value.startDate),
+ notificationType: {
+ newJobCreated: true
+ },
+ description: 'New Job Created'
+ }
+ data.subject = await helper.substituteStringByObject(data.subject, data)
+
const emailData = {
serviceId: 'email',
type: 'taas.notification.job-created',
details: {
from: template.from,
recipients: _.map(project.members, m => _.pick(m, 'email')),
- data: {
- subject: template.subject,
- teamName: project.name,
- teamURL: `${config.TAAS_APP_URL}/${project.id}`,
- jobTitle: payload.value.title,
- jobURL: `${config.TAAS_APP_URL}/${project.id}/positions/${payload.value.id}`,
- jobDuration: payload.value.duration,
- jobStartDate: helper.formatDateEDT(payload.value.startDate),
- notificationType: {
- newJobCreated: true
- },
- description: 'New Job Created'
- },
+ data,
sendgridTemplateId: template.sendgridTemplateId,
version: 'v3'
}
diff --git a/src/eventHandlers/ResourceBookingEventHandler.js b/src/eventHandlers/ResourceBookingEventHandler.js
index 5a1f15a0..67adfeea 100644
--- a/src/eventHandlers/ResourceBookingEventHandler.js
+++ b/src/eventHandlers/ResourceBookingEventHandler.js
@@ -89,26 +89,28 @@ async function sendPlacedNotifications (payload) {
const recipients = _.map(project.members, m => _.pick(m, 'email'))
const jobUrl = `${config.TAAS_APP_URL}/${project.id}/positions/${job.id}`
const teamUrl = `${config.TAAS_APP_URL}/${project.id}`
+ const data = {
+ subject: template.subject,
+ teamName: project.name,
+ teamUrl,
+ jobTitle: job.title,
+ jobUrl,
+ userHandle: user.handle,
+ startDate: resourceBooking.startDate,
+ endDate: resourceBooking.endDate,
+ notificationType: {
+ resourceBookingPlaced: true
+ },
+ description: 'Resource Booking is Placed'
+ }
+ data.subject = await helper.substituteStringByObject(data.subject, data)
const emailData = {
serviceId: 'email',
type: 'taas.notification.resource-booking-placed',
details: {
from: template.from,
recipients,
- data: {
- subject: template.subject,
- teamName: project.name,
- teamUrl,
- jobTitle: job.title,
- jobUrl,
- userHandle: user.handle,
- startDate: resourceBooking.startDate,
- endDate: resourceBooking.endDate,
- notificationType: {
- resourceBookingPlaced: true
- },
- description: 'Resource Booking is Placed'
- },
+ data,
sendgridTemplateId: template.sendgridTemplateId,
version: 'v3'
}
diff --git a/src/eventHandlers/TeamEventHandler.js b/src/eventHandlers/TeamEventHandler.js
index 7bd11eab..d5ee4b15 100644
--- a/src/eventHandlers/TeamEventHandler.js
+++ b/src/eventHandlers/TeamEventHandler.js
@@ -15,27 +15,30 @@ const helper = require('../common/helper')
*/
async function sendNotificationEmail (payload) {
const template = helper.getEmailTemplatesForKey('notificationEmailTemplates')['taas.notification.team-created']
+ const data = {
+ subject: template.subject,
+ teamName: payload.project.name,
+ teamUrl: `${config.TAAS_APP_URL}/${payload.project.id}`,
+ jobList: _.map(payload.jobs, j => ({
+ title: j.title,
+ duration: j.duration,
+ startDate: helper.formatDateEDT(j.startDate),
+ jobUrl: `${config.TAAS_APP_URL}/${payload.project.id}/positions/${j.id}`
+ })),
+ notificationType: {
+ newTeamCreated: true
+ },
+ description: 'New Team Created'
+ }
+ data.subject = await helper.substituteStringByObject(data.subject, data)
+
const emailData = {
serviceId: 'email',
type: 'taas.notification.team-created',
details: {
from: template.from,
recipients: _.map(payload.project.members, m => _.pick(m, 'email')),
- data: {
- subject: template.subject,
- teamName: payload.project.name,
- teamUrl: `${config.TAAS_APP_URL}/${payload.project.id}`,
- jobList: _.map(payload.jobs, j => ({
- title: j.title,
- duration: j.duration,
- startDate: helper.formatDateEDT(j.startDate),
- jobUrl: `${config.TAAS_APP_URL}/${payload.project.id}/positions/${j.id}`
- })),
- notificationType: {
- newTeamCreated: true
- },
- description: 'New Team Created'
- },
+ data,
sendgridTemplateId: template.sendgridTemplateId,
version: 'v3'
}
diff --git a/src/services/JobCandidateService.js b/src/services/JobCandidateService.js
index 8f90da08..e142fbc4 100644
--- a/src/services/JobCandidateService.js
+++ b/src/services/JobCandidateService.js
@@ -14,7 +14,7 @@ const logger = require('../common/logger')
const errors = require('../common/errors')
const models = require('../models')
const JobService = require('./JobService')
-const EmailNotificationService = require('./EmailNotificationService')
+const NotificationSchedulerService = require('./NotificationsSchedulerService')
const JobCandidate = models.JobCandidate
const esClient = helper.getESClient()
@@ -376,7 +376,7 @@ async function downloadJobCandidateResume (currentUser, id) {
const { handle } = await helper.getUserById(jobCandidate.userId, true)
const { email } = await helper.getMemberDetailsByHandle(handle)
- await EmailNotificationService.sendEmail(currentUser, {
+ await NotificationSchedulerService.sendNotification(currentUser, {
template: 'taas.notification.job-candidate-resume-viewed',
recipients: [email],
data: {
diff --git a/src/services/EmailNotificationService.js b/src/services/NotificationsSchedulerService.js
similarity index 69%
rename from src/services/EmailNotificationService.js
rename to src/services/NotificationsSchedulerService.js
index 10921668..e0c2610b 100644
--- a/src/services/EmailNotificationService.js
+++ b/src/services/NotificationsSchedulerService.js
@@ -1,5 +1,5 @@
/**
- * Email notification service - has the cron handlers for sending different types of email notifications
+ * Notification scheduler service - has the cron handlers for sending different types of notifications (email, web etc)
*/
const _ = require('lodash')
const { Op } = require('sequelize')
@@ -15,9 +15,9 @@ const constants = require('../../app-constants')
const logger = require('../common/logger')
const localLogger = {
- debug: (message, context) => logger.debug({ component: 'EmailNotificationService', context, message }),
- error: (message, context) => logger.error({ component: 'EmailNotificationService', context, message }),
- info: (message, context) => logger.info({ component: 'EmailNotificationService', context, message })
+ debug: (message, context) => logger.debug({ component: 'NotificationSchedulerService', context, message }),
+ error: (message, context) => logger.error({ component: 'NotificationSchedulerService', context, message }),
+ info: (message, context) => logger.info({ component: 'NotificationSchedulerService', context, message })
}
const emailTemplates = helper.getEmailTemplatesForKey('notificationEmailTemplates')
@@ -88,7 +88,8 @@ async function getDataForInterview (interview, jobCandidate, job) {
const interviewLink = `${config.TAAS_APP_URL}/${job.projectId}/positions/${job.id}/candidates/interviews`
const guestName = _.isEmpty(interview.guestNames) ? '' : interview.guestNames[0]
- const startTime = interview.startTimestamp ? interview.startTimestamp.toUTCString() : ''
+ const startTime = interview.startTimestamp ? helper.formatDateTimeEDT(interview.startTimestamp) : ''
+ const jobUrl = `${config.TAAS_APP_URL}/${job.projectId}/positions/${job.id}`
return {
jobTitle: job.title,
@@ -99,14 +100,15 @@ async function getDataForInterview (interview, jobCandidate, job) {
attendees: interview.guestNames,
startTime: startTime,
duration: interview.duration,
- interviewLink
+ interviewLink,
+ jobUrl
}
}
/**
- * Sends email notifications to all the teams which have candidates available for review
+ * Sends notifications to all the teams which have candidates available for review
*/
-async function sendCandidatesAvailableEmails () {
+async function sendCandidatesAvailableNotifications () {
const jobsDao = await Job.findAll({
include: [{
model: JobCandidate,
@@ -121,7 +123,7 @@ async function sendCandidatesAvailableEmails () {
const projectIds = _.uniq(_.map(jobs, job => job.projectId))
- localLogger.debug(`[sendCandidatesAvailableEmails]: Found ${projectIds.length} projects with Job Candidates awaiting for review.`)
+ localLogger.debug(`[sendCandidatesAvailableNotifications]: Found ${projectIds.length} projects with Job Candidates awaiting for review.`)
// for each unique project id, send an email
let sentCount = 0
@@ -156,15 +158,17 @@ async function sendCandidatesAvailableEmails () {
}
})
+ const jobUrl = `${config.TAAS_APP_URL}/${projectId}/positions/${projectJob.id}`
teamJobs.push({
title: projectJob.title,
nResourceBookings,
jobCandidates,
- reviewLink
+ reviewLink,
+ jobUrl
})
}
- sendEmail({}, {
+ sendNotification({}, {
template: 'taas.notification.candidates-available-for-review',
recipients: recipientEmails,
data: {
@@ -179,13 +183,13 @@ async function sendCandidatesAvailableEmails () {
sentCount++
}
- localLogger.debug(`[sendCandidatesAvailableEmails]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Job Candidates awaiting for review.`)
+ localLogger.debug(`[sendCandidatesAvailableNotifications]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Job Candidates awaiting for review.`)
}
/**
- * Sends email reminders to the hosts and guests about their upcoming interview(s)
+ * Sends reminders to the hosts and guests about their upcoming interview(s)
*/
-async function sendInterviewComingUpEmails () {
+async function sendInterviewComingUpNotifications () {
const currentTime = moment.utc()
const timestampFilter = {
[Op.or]: []
@@ -223,7 +227,7 @@ async function sendInterviewComingUpEmails () {
raw: true
})
- localLogger.debug(`[sendInterviewComingUpEmails]: Found ${interviews.length} interviews which are coming soon.`)
+ localLogger.debug(`[sendInterviewComingUpNotifications]: Found ${interviews.length} interviews which are coming soon.`)
let sentHostCount = 0
let sentGuestCount = 0
@@ -233,7 +237,7 @@ async function sendInterviewComingUpEmails () {
if (!data) { continue }
if (!_.isEmpty(interview.hostEmail)) {
- sendEmail({}, {
+ sendNotification({}, {
template: 'taas.notification.interview-coming-up-host',
recipients: [interview.hostEmail],
data: {
@@ -247,12 +251,12 @@ async function sendInterviewComingUpEmails () {
sentHostCount++
} else {
- localLogger.error(`Interview id: ${interview.id} host email not present`, 'sendInterviewComingUpEmails')
+ localLogger.error(`Interview id: ${interview.id} host email not present`, 'sendInterviewComingUpNotifications')
}
if (!_.isEmpty(interview.guestEmails)) {
// send guest emails
- sendEmail({}, {
+ sendNotification({}, {
template: 'taas.notification.interview-coming-up-guest',
recipients: interview.guestEmails,
data: {
@@ -266,17 +270,17 @@ async function sendInterviewComingUpEmails () {
sentGuestCount++
} else {
- localLogger.error(`Interview id: ${interview.id} guest emails not present`, 'sendInterviewComingUpEmails')
+ localLogger.error(`Interview id: ${interview.id} guest emails not present`, 'sendInterviewComingUpNotifications')
}
}
- localLogger.debug(`[sendInterviewComingUpEmails]: Sent notifications for ${sentHostCount} hosts and ${sentGuestCount} guest of ${interviews.length} interviews which are coming soon.`)
+ localLogger.debug(`[sendInterviewComingUpNotifications]: Sent notifications for ${sentHostCount} hosts and ${sentGuestCount} guest of ${interviews.length} interviews which are coming soon.`)
}
/**
- * Sends email reminder to the interview host after it ends to change the interview status
+ * Sends reminder to the interview host after it ends to change the interview status
*/
-async function sendInterviewCompletedEmails () {
+async function sendInterviewCompletedNotifications () {
const window = moment.duration(config.INTERVIEW_COMPLETED_MATCH_WINDOW)
const rangeStart = moment.utc().subtract(moment.duration(config.INTERVIEW_COMPLETED_PAST_TIME))
const rangeEnd = rangeStart.clone().add(window)
@@ -305,7 +309,7 @@ async function sendInterviewCompletedEmails () {
raw: true
})
- localLogger.debug(`[sendInterviewCompletedEmails]: Found ${interviews.length} interviews which must be ended by now.`)
+ localLogger.debug(`[sendInterviewCompletedNotifications]: Found ${interviews.length} interviews which must be ended by now.`)
let sentCount = 0
for (const interview of interviews) {
@@ -317,7 +321,7 @@ async function sendInterviewCompletedEmails () {
const data = await getDataForInterview(interview)
if (!data) { continue }
- sendEmail({}, {
+ sendNotification({}, {
template: 'taas.notification.interview-awaits-resolution',
recipients: [interview.hostEmail],
data: {
@@ -332,14 +336,14 @@ async function sendInterviewCompletedEmails () {
sentCount++
}
- localLogger.debug(`[sendInterviewCompletedEmails]: Sent notifications for ${sentCount} of ${interviews.length} interviews which must be ended by now.`)
+ localLogger.debug(`[sendInterviewCompletedNotifications]: Sent notifications for ${sentCount} of ${interviews.length} interviews which must be ended by now.`)
}
/**
- * Sends email reminder to the all members of teams which have interview completed to take action
+ * Sends reminder to the all members of teams which have interview completed to take action
* to update the job candidate status
*/
-async function sendPostInterviewActionEmails () {
+async function sendPostInterviewActionNotifications () {
const completedJobCandidates = await JobCandidate.findAll({
where: {
status: constants.JobCandidateStatus.INTERVIEW
@@ -366,13 +370,15 @@ 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.`)
+ localLogger.debug(`[sendPostInterviewActionNotifications]: Found ${projectIds.length} projects with ${completedJobCandidates.length} Job Candidates with interview completed awaiting for an action.`)
let sentCount = 0
+ const template = 'taas.notification.post-interview-action-required'
+
for (const projectId of projectIds) {
const project = await getProjectWithId(projectId)
if (!project) { continue }
-
+ const webNotifications = []
const recipientEmails = getProjectMembersEmails(project)
const projectJobs = _.filter(jobs, job => job.projectId === projectId)
const teamInterviews = []
@@ -384,13 +390,30 @@ async function sendPostInterviewActionEmails () {
for (const interview of projectJc.interviews) {
const d = await getDataForInterview(interview, projectJc, projectJob)
if (!d) { continue }
+ d.jobUrl = `${config.TAAS_APP_URL}/${projectId}/positions/${projectJob.id}`
+ webNotifications.push({
+ serviceId: 'web',
+ type: template,
+ details: {
+ recipients: _.map(_.uniq(recipientEmails), function (re) { return { email: re } }),
+ contents: {
+ jobTitle: d.jobTitle,
+ teamName: project.name,
+ projectId,
+ jobId: projectJob.id,
+ userHandle: d.handle
+ },
+ version: 1
+ }
+ })
+
teamInterviews.push(d)
}
}
}
- sendEmail({}, {
- template: 'taas.notification.post-interview-action-required',
+ sendNotification({}, {
+ template,
recipients: recipientEmails,
data: {
teamName: project.name,
@@ -401,18 +424,18 @@ async function sendPostInterviewActionEmails () {
},
description: 'Post Interview Candidate Action Reminder'
}
- })
+ }, webNotifications)
sentCount++
}
- localLogger.debug(`[sendPostInterviewActionEmails]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Job Candidates with interview completed awaiting for an action.`)
+ localLogger.debug(`[sendPostInterviewActionNotifications]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Job Candidates with interview completed awaiting for an action.`)
}
/**
- * Sends reminder emails to all members of teams which have atleast one upcoming resource booking expiration
+ * Sends reminders to all members of teams which have atleast one upcoming resource booking expiration
*/
-async function sendResourceBookingExpirationEmails () {
+async function sendResourceBookingExpirationNotifications () {
const currentTime = moment.utc()
const maxEndDate = currentTime.clone().add(moment.duration(config.RESOURCE_BOOKING_EXPIRY_TIME))
@@ -442,9 +465,10 @@ async function sendResourceBookingExpirationEmails () {
})
const projectIds = _.uniq(_.map(expiringResourceBookings, rb => rb.projectId))
- localLogger.debug(`[sendResourceBookingExpirationEmails]: Found ${projectIds.length} projects with ${expiringResourceBookings.length} Resource Bookings expiring in less than 3 weeks.`)
+ localLogger.debug(`[sendResourceBookingExpirationNotifications]: Found ${projectIds.length} projects with ${expiringResourceBookings.length} Resource Bookings expiring in less than 3 weeks.`)
let sentCount = 0
+ const template = 'taas.notification.resource-booking-expiration'
for (const projectId of projectIds) {
const project = await getProjectWithId(projectId)
if (!project) { continue }
@@ -461,16 +485,36 @@ async function sendResourceBookingExpirationEmails () {
const user = await getUserWithId(booking.userId)
if (!user) { continue }
+ const jobUrl = `${config.TAAS_APP_URL}/${projectId}/positions/${projectJob.id}`
+ const resourceBookingUrl = `${config.TAAS_APP_URL}/${projectId}/rb/${booking.id}`
teamResourceBookings.push({
jobTitle: projectJob.title,
handle: user.handle,
- endDate: booking.endDate
+ endDate: booking.endDate,
+ jobUrl,
+ resourceBookingUrl
})
}
}
- sendEmail({}, {
- template: 'taas.notification.resource-booking-expiration',
+ const webData = {
+ serviceId: 'web',
+ type: template,
+ details: {
+ recipients: _.map(_.uniq(recipientEmails), function (re) { return { email: re } }),
+ contents: {
+ teamName: project.name,
+ projectId,
+ numOfExpiringResourceBookings: numResourceBookings
+ },
+ version: 1
+ }
+ }
+
+ const teamUrl = `${config.TAAS_APP_URL}/${project.id}`
+
+ sendNotification({}, {
+ template,
recipients: recipientEmails,
data: {
teamName: project.name,
@@ -479,23 +523,24 @@ async function sendResourceBookingExpirationEmails () {
notificationType: {
upcomingResourceBookingExpiration: true
},
+ teamUrl,
description: 'Upcoming Resource Booking Expiration'
}
- })
+ }, [webData])
sentCount++
}
- localLogger.debug(`[sendResourceBookingExpirationEmails]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Resource Bookings expiring in less than 3 weeks.`)
+ localLogger.debug(`[sendResourceBookingExpirationNotifications]: Sent notifications for ${sentCount} of ${projectIds.length} projects with Resource Bookings expiring in less than 3 weeks.`)
}
/**
- * Send email through a particular template
+ * Send notification through a particular template
* @param {Object} currentUser the user who perform this operation
* @param {Object} data the email object
- * @returns {undefined}
+ * @param {Array} webNotifications the optional list of web notifications
*/
-async function sendEmail (currentUser, data) {
+async function sendNotification (currentUser, data, webNotifications = []) {
const template = emailTemplates[data.template]
const dataCC = data.cc || []
const templateCC = template.cc || []
@@ -511,28 +556,32 @@ async function sendEmail (currentUser, data) {
data.data
)
}
+
+ const recipients = _.map(_.uniq([...dataRecipients, ...templateRecipients]), function (r) { return { email: r } })
const emailData = {
serviceId: 'email',
type: data.template,
details: {
from: data.from || template.from,
- recipients: _.map(_.uniq([...dataRecipients, ...templateRecipients]), function (r) { return { email: r } }),
+ recipients,
cc: _.map(_.uniq([...dataCC, ...templateCC]), function (r) { return { email: r } }),
data: { ...data.data, ...subjectBody },
sendgridTemplateId: template.sendgridTemplateId,
version: 'v3'
}
}
+
+ const notifications = [emailData, ...webNotifications]
await helper.postEvent(config.NOTIFICATIONS_CREATE_TOPIC, {
- notifications: [emailData]
+ notifications
})
}
module.exports = {
- sendEmail,
- sendCandidatesAvailableEmails,
- sendInterviewComingUpEmails,
- sendInterviewCompletedEmails,
- sendPostInterviewActionEmails,
- sendResourceBookingExpirationEmails
+ sendNotification,
+ sendCandidatesAvailableNotifications,
+ sendInterviewComingUpNotifications,
+ sendInterviewCompletedNotifications,
+ sendPostInterviewActionNotifications,
+ sendResourceBookingExpirationNotifications
}
|