Skip to content

Commit 378879b

Browse files
Merge pull request #10 from imcaizheng/update-job-candidate-status-recruit-crm
Update the status of candidates in RecruitCRM
2 parents 4169090 + c44bc62 commit 378879b

File tree

8 files changed

+115
-32
lines changed

8 files changed

+115
-32
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ The following parameters can be set in config files or in env variables:
4747

4848
- `zapier.ZAPIER_COMPANYID_SLUG`: your company id in zapier; numeric value
4949
- `zapier.ZAPIER_CONTACTID_SLUG`: your contact id in zapier; numeric value
50-
- `zapier.ZAPIER_SWITCH`: decides whether posting message to zapier or not; possible values are `ON` and `OFF`, default is `OFF`
51-
- `zapier.ZAPIER_WEBHOOK`: the remote zapier zap webhook url for posting message
50+
- `zapier.ZAPIER_SWITCH`: decides whether posting job related message to zapier or not; possible values are `ON` and `OFF`, default is `OFF`
51+
- `zapier.ZAPIER_WEBHOOK`: the remote zapier zap webhook url for posting job related message
52+
- `zapier.ZAPIER_JOB_CANDIDATE_SWITCH`: decides whether posting job candidate related message to zapier or not; possible values are `ON` and `OFF`, default is `OFF`
53+
- `zapier.ZAPIER_JOB_CANDIDATE_WEBHOOK`: the remote zapier zap webhook url for posting job candidate related message
5254

5355
## Local Kafka and ElasticSearch setup
5456

config/default.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ module.exports = {
5858
ZAPIER_CONTACTID_SLUG: process.env.ZAPIER_CONTACTID_SLUG,
5959
ZAPIER_SWITCH: process.env.ZAPIER_SWITCH || 'OFF',
6060
ZAPIER_WEBHOOK: process.env.ZAPIER_WEBHOOK,
61+
ZAPIER_JOB_CANDIDATE_SWITCH: process.env.ZAPIER_JOB_CANDIDATE_SWITCH || 'OFF',
62+
ZAPIER_JOB_CANDIDATE_WEBHOOK: process.env.ZAPIER_JOB_CANDIDATE_WEBHOOK,
6163
TOPCODER_API_URL: process.env.TOPCODER_API_URL || 'http://api.topcoder-dev.com/v5'
6264
}
6365
}

src/app.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ const eventEmitter = new events.EventEmitter()
2121
process.env.PORT = config.PORT
2222

2323
const localLogger = {
24-
'info': (message) => logger.info({ component: 'app', message }),
25-
'debug': (message) => logger.debug({ component: 'app', message }),
26-
'error': (message) => logger.error({ component: 'app', message })
24+
info: (message) => logger.info({ component: 'app', message }),
25+
debug: (message) => logger.debug({ component: 'app', message }),
26+
error: (message) => logger.error({ component: 'app', message })
2727
}
2828

2929
const topicServiceMapping = {
@@ -47,7 +47,7 @@ localLogger.info('Starting kafka consumer')
4747
const consumer = new Kafka.GroupConsumer(helper.getKafkaOptions())
4848

4949
let count = 0
50-
let mutex = new Mutex()
50+
const mutex = new Mutex()
5151

5252
async function getLatestCount () {
5353
const release = await mutex.acquire()
@@ -71,7 +71,7 @@ const dataHandler = (messageSet, topic, partition) => Promise.each(messageSet, a
7171
localLogger.info(`Handle Kafka event message; Topic: ${topic}; Partition: ${partition}; Offset: ${
7272
m.offset}; Message: ${message}.`)
7373
let messageJSON
74-
let messageCount = await getLatestCount()
74+
const messageCount = await getLatestCount()
7575

7676
localLogger.debug(`Current message count: ${messageCount}`)
7777
try {

src/bootstrap.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const zapierSwitch = Joi.string().label('ZAPIER_SWITCH').valid(...Object.values(
1515
// validate configuration
1616
try {
1717
Joi.attempt(config.zapier.ZAPIER_SWITCH, zapierSwitch)
18+
Joi.attempt(config.zapier.ZAPIER_JOB_CANDIDATE_SWITCH, zapierSwitch)
1819
} catch (err) {
1920
console.error(err.message)
2021
process.exit(1)

src/common/constants.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ module.exports = {
1212
},
1313
MessageType: {
1414
JobCreate: 'job:create',
15-
JobUpdate: 'job:update'
15+
JobUpdate: 'job:update',
16+
JobCandidateCreate: 'jobcandidate:create',
17+
JobCandidateUpdate: 'jobcandidate:update'
1618
}
1719
}
1820
}

src/common/helper.js

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const elasticsearch = require('@elastic/elasticsearch')
1010
const _ = require('lodash')
1111
const { Mutex } = require('async-mutex')
1212
const m2mAuth = require('tc-core-library-js').auth.m2m
13-
const constants = require('./constants')
1413

1514
AWS.config.region = config.esConfig.AWS_REGION
1615

@@ -154,33 +153,19 @@ async function getM2MToken () {
154153
/**
155154
* Post message to zapier via webhook url.
156155
*
157-
* @param {Object} message the message object
156+
* @param {String} webhook the webhook url
157+
* @param {Object} message the message data
158158
* @returns {undefined}
159159
*/
160-
async function postMessageToZapier ({ type, payload }) {
161-
if (config.zapier.ZAPIER_SWITCH === constants.Zapier.Switch.OFF) {
162-
logger.debug({ component: 'helper', context: 'postMessageToZapier', message: 'Zapier Switch off via config, no messages sent' })
163-
return
164-
}
165-
const requestBody = {
166-
type,
167-
payload,
168-
companySlug: config.zapier.ZAPIER_COMPANYID_SLUG,
169-
contactSlug: config.zapier.ZAPIER_CONTACTID_SLUG
170-
}
171-
if (type === constants.Zapier.MessageType.JobCreate) {
172-
const token = await getM2MToken()
173-
requestBody.authToken = token
174-
requestBody.topcoderApiUrl = config.zapier.TOPCODER_API_URL
175-
}
176-
logger.debug({ component: 'helper', context: 'postMessageToZapier', message: `request body: ${JSON.stringify(requestBody)}` })
177-
await request.post(config.zapier.ZAPIER_WEBHOOK)
178-
.send(requestBody)
160+
async function postMessageViaWebhook (webhook, message) {
161+
logger.debug({ component: 'helper', context: 'postMessageToZapier', message: `message: ${JSON.stringify(message)}` })
162+
await request.post(webhook).send(message)
179163
}
180164

181165
module.exports = {
182166
getKafkaOptions,
183167
getESClient,
184168
checkEsMutexRelease,
185-
postMessageToZapier
169+
getM2MToken,
170+
postMessageViaWebhook
186171
}

src/services/JobCandidateProcessorService.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,64 @@ const config = require('config')
1111

1212
const esClient = helper.getESClient()
1313

14+
const localLogger = {
15+
debug: ({ context, message }) => logger.debug({ component: 'JobCandidateProcessorService', context, message })
16+
}
17+
18+
/**
19+
* Update job candidate status in recruit CRM.
20+
*
21+
* @param {Object} message the message object
22+
* @returns {undefined}
23+
*/
24+
async function updateCandidateStatus ({ type, payload }) {
25+
if (!payload.status) {
26+
localLogger.debug({ context: 'updateCandidateStatus', message: 'status not updated' })
27+
return
28+
}
29+
if (!['rejected', 'shortlist'].includes(payload.status)) {
30+
localLogger.debug({ context: 'updateCandidateStatus', message: `not interested status: ${payload.status}` })
31+
return
32+
}
33+
const { body: jobCandidate } = await esClient.getSource({
34+
index: config.get('esConfig.ES_INDEX_JOB_CANDIDATE'),
35+
id: payload.id
36+
})
37+
if (!jobCandidate.externalId) {
38+
localLogger.debug({ context: 'updateCandidateStatus', message: `id: ${jobCandidate.id} candidate without externalId - ignored` })
39+
return
40+
}
41+
const { body: job } = await esClient.getSource({
42+
index: config.get('esConfig.ES_INDEX_JOB'),
43+
id: jobCandidate.jobId
44+
})
45+
const message = {
46+
type,
47+
status: jobCandidate.status,
48+
jobCandidateSlug: jobCandidate.externalId,
49+
jobSlug: job.externalId
50+
}
51+
await helper.postMessageViaWebhook(config.zapier.ZAPIER_JOB_CANDIDATE_WEBHOOK, message)
52+
}
53+
54+
/**
55+
* Post message to zapier for JobCandidate.
56+
*
57+
* @param {Object} message the message object
58+
* @returns {undefined}
59+
*/
60+
async function postMessageToZapier ({ type, payload }) {
61+
if (config.zapier.ZAPIER_JOB_CANDIDATE_SWITCH === constants.Zapier.Switch.OFF) {
62+
localLogger.debug({ context: 'postMessageToZapier', message: 'Zapier Switch off via config, no messages sent' })
63+
return
64+
}
65+
if (type === constants.Zapier.MessageType.JobCandidateUpdate) {
66+
await updateCandidateStatus({ type, payload })
67+
return
68+
}
69+
throw new Error(`unrecognized message type: ${type}`)
70+
}
71+
1472
/**
1573
* Process create entity message
1674
* @param {Object} message the kafka message
@@ -63,6 +121,10 @@ async function processUpdate (message, transactionId) {
63121
},
64122
refresh: constants.esRefreshOption
65123
})
124+
await postMessageToZapier({
125+
type: constants.Zapier.MessageType.JobCandidateUpdate,
126+
payload: data
127+
})
66128
}
67129

68130
processUpdate.schema = {

src/services/JobProcessorService.js

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,35 @@ const config = require('config')
1111

1212
const esClient = helper.getESClient()
1313

14+
const localLogger = {
15+
debug: ({ context, message }) => logger.debug({ component: 'JobProcessorService', context, message })
16+
}
17+
18+
/**
19+
* Post message to zapier for Job.
20+
*
21+
* @param {Object} message the message object
22+
* @returns {undefined}
23+
*/
24+
async function postMessageToZapier ({ type, payload }) {
25+
if (config.zapier.ZAPIER_SWITCH === constants.Zapier.Switch.OFF) {
26+
localLogger.debug({ context: 'postMessageToZapier', message: 'Zapier Switch off via config, no messages sent' })
27+
return
28+
}
29+
const message = {
30+
type,
31+
payload,
32+
companySlug: config.zapier.ZAPIER_COMPANYID_SLUG,
33+
contactSlug: config.zapier.ZAPIER_CONTACTID_SLUG
34+
}
35+
if (type === constants.Zapier.MessageType.JobCreate) {
36+
const token = await helper.getM2MToken()
37+
message.authToken = token
38+
message.topcoderApiUrl = config.zapier.TOPCODER_API_URL
39+
}
40+
await helper.postMessageViaWebhook(config.zapier.ZAPIER_WEBHOOK, message)
41+
}
42+
1443
/**
1544
* Process create entity message
1645
* @param {Object} message the kafka message
@@ -25,7 +54,7 @@ async function processCreate (message, transactionId) {
2554
body: _.omit(job, 'id'),
2655
refresh: constants.esRefreshOption
2756
})
28-
await helper.postMessageToZapier({
57+
await postMessageToZapier({
2958
type: constants.Zapier.MessageType.JobCreate,
3059
payload: job
3160
})
@@ -74,7 +103,7 @@ async function processUpdate (message, transactionId) {
74103
},
75104
refresh: constants.esRefreshOption
76105
})
77-
await helper.postMessageToZapier({
106+
await postMessageToZapier({
78107
type: constants.Zapier.MessageType.JobUpdate,
79108
payload: data
80109
})

0 commit comments

Comments
 (0)