Skip to content

Commit 0695367

Browse files
Merge pull request #419 from topcoder-platform/feature/jc-withdrawn
Add withdrawn job candidates automation logic
2 parents 43c0fa2 + d1ee884 commit 0695367

File tree

3 files changed

+102
-2
lines changed

3 files changed

+102
-2
lines changed

config/default.js

+12
Original file line numberDiff line numberDiff line change
@@ -214,5 +214,17 @@ module.exports = {
214214
FIX_DELAY_STEP_ASSIGN_MEMBER: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_ASSIGN_MEMBER || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500),
215215
// the fix delay after step of activate challenge, unit: ms
216216
FIX_DELAY_STEP_ACTIVATE_CHALLENGE: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_ACTIVATE_CHALLENGE || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500)
217+
},
218+
// if a job reach this critier, system will automatically withdrawn other job applications.
219+
JOBS_HOUR_PER_WEEK: 20,
220+
// the mapping includes the status transformation when auto-withdrawn feature is performed on job candidates.
221+
WITHDRAWN_STATUS_CHANGE_MAPPING: {
222+
applied: 'withdrawn-prescreen',
223+
'skills-test': 'withdrawn-prescreen',
224+
'phone-screen': 'withdrawn-prescreen',
225+
open: 'withdrawn',
226+
interview: 'withdrawn',
227+
selected: 'withdrawn',
228+
offered: 'withdrawn'
217229
}
218230
}

src/eventHandlers/JobCandidateEventHandler.js

+88-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
/*
22
* Handle events for JobCandidate.
33
*/
4-
4+
const { Op } = require('sequelize')
5+
const _ = require('lodash')
6+
const config = require('config')
57
const models = require('../models')
68
const logger = require('../common/logger')
79
const helper = require('../common/helper')
810
const JobService = require('../services/JobService')
11+
const JobCandidateService = require('../services/JobCandidateService')
912

1013
/**
1114
* Once we create at least one JobCandidate for a Job, the Job status should be changed to in-review.
@@ -44,6 +47,84 @@ async function inReviewJob (payload) {
4447
}
4548
}
4649

50+
/**
51+
* Actual Update Job Candidates
52+
*
53+
* @param {*} statuses the source status we'll update
54+
* @param {*} userId the userID
55+
*/
56+
async function updateJobCandidates (statuses, userId) {
57+
logger.info({
58+
component: 'JobCandidateEventHandler',
59+
context: 'updateJobCandidates',
60+
message: `Update jobCandidates for user ${userId}`
61+
})
62+
const filter = { [Op.and]: [] }
63+
filter[Op.and].push({ status: statuses })
64+
filter[Op.and].push({ userId: userId })
65+
const candidates = await models.JobCandidate.findAll({
66+
where: filter
67+
})
68+
if (candidates && candidates.length > 0) {
69+
_.each(candidates, async (candidate) => {
70+
logger.info({
71+
component: 'JobCandidateEventHandler',
72+
context: 'updateJobCandidates',
73+
message: `Begin update id: ${candidate.id}' candidate with ${candidate.status} status into ${config.WITHDRAWN_STATUS_CHANGE_MAPPING[candidate.status]} for userId: ${userId}`
74+
})
75+
await JobCandidateService.partiallyUpdateJobCandidate(
76+
helper.getAuditM2Muser(),
77+
candidate.id,
78+
{ status: config.WITHDRAWN_STATUS_CHANGE_MAPPING[candidate.status] }
79+
).then(result => {
80+
logger.info({
81+
component: 'JobCandidateEventHandler',
82+
context: 'updateJobCandidates',
83+
message: `Finish update id: ${result.id}' candidate into ${result.status} status for userId: ${userId}`
84+
})
85+
})
86+
})
87+
} else {
88+
logger.info({
89+
component: 'JobCandidateEventHandler',
90+
context: 'updateJobCandidates',
91+
message: `There are not jobCandidates for user ${userId} that required to be updated.`
92+
})
93+
}
94+
}
95+
96+
/**
97+
* Update Job Candidates based on business rules
98+
*
99+
* @param {*} payload the updated jobCandidate info
100+
*/
101+
async function withDrawnJobCandidates (payload) {
102+
const jobCandidate = payload.value
103+
if (jobCandidate.status === 'placed') {
104+
const job = await models.Job.findById(payload.value.jobId)
105+
if (job.hoursPerWeek > config.JOBS_HOUR_PER_WEEK) {
106+
// find all these user's open job Candidate and mark the status as withdrawn or withdrawn-prescreen
107+
logger.info({
108+
component: 'JobCandidateEventHandler',
109+
context: 'withDrawnJobCandidates',
110+
message: `Begin update jobCandidates as ${payload.value.id} candidate's new gig is requiring more than 20 hrs per week`
111+
})
112+
await updateJobCandidates(['applied', 'skills-test', 'phone-screen', 'open', 'interview', 'selected', 'offered'], payload.value.userId)
113+
logger.info({
114+
component: 'JobCandidateEventHandler',
115+
context: 'withDrawnJobCandidates',
116+
message: `Finish update jobCandidates as ${payload.value.id} candidate`
117+
})
118+
} else {
119+
logger.debug({
120+
component: 'JobCandidateEventHandler',
121+
context: 'withDrawnJobCandidates',
122+
message: `id: ${payload.value.id} candidate is not placing on a gig requiring 20 hrs per week`
123+
})
124+
}
125+
}
126+
}
127+
47128
/**
48129
* Process job candidate create event.
49130
*
@@ -52,6 +133,9 @@ async function inReviewJob (payload) {
52133
*/
53134
async function processCreate (payload) {
54135
await inReviewJob(payload)
136+
if (payload.value.status === 'placed') {
137+
await withDrawnJobCandidates(payload)
138+
}
55139
}
56140

57141
/**
@@ -62,6 +146,9 @@ async function processCreate (payload) {
62146
*/
63147
async function processUpdate (payload) {
64148
await inReviewJob(payload)
149+
if (payload.value.status === 'placed' && payload.options.oldValue.status !== 'placed') {
150+
await withDrawnJobCandidates(payload)
151+
}
65152
}
66153

67154
module.exports = {

src/services/JobCandidateService.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ createJobCandidate.schema = Joi.object().keys({
144144
*/
145145
async function updateJobCandidate (currentUser, id, data) {
146146
const jobCandidate = await JobCandidate.findById(id)
147+
const oldValue = jobCandidate.toJSON()
147148
const userId = await helper.getUserId(currentUser.userId)
148149

149150
// check user permission
@@ -155,7 +156,7 @@ async function updateJobCandidate (currentUser, id, data) {
155156
data.updatedBy = userId
156157

157158
const updated = await jobCandidate.update(data)
158-
await helper.postEvent(config.TAAS_JOB_CANDIDATE_UPDATE_TOPIC, updated.toJSON())
159+
await helper.postEvent(config.TAAS_JOB_CANDIDATE_UPDATE_TOPIC, updated.toJSON(), { oldValue: oldValue })
159160
const result = _.assign(jobCandidate.dataValues, data)
160161
return result
161162
}

0 commit comments

Comments
 (0)