Skip to content

Commit f559204

Browse files
authored
Merge pull request #432 from eisbilir/fix/job-import-script
fix: script to import job from RCRM
2 parents 3204533 + 60d476e commit f559204

File tree

5 files changed

+68
-34
lines changed

5 files changed

+68
-34
lines changed

scripts/recruit-crm-job-import/README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ By default the script creates jobs and resource bookings via `TC_API`.
1616
Follow the README for Taas API to deploy Taas API locally and then point the script to the local API by running:
1717

1818
``` bash
19+
export RCRM_IMPORT_CONFIG_NAMESAPCE=RCRM_IMPORT_
1920
export RCRM_IMPORT_TAAS_API_URL=http://localhost:3000/api/v5
2021
node scripts/recruit-crm-job-import scripts/recruit-crm-job-import/example_data.csv | tee /tmp/report.txt
2122
```
@@ -27,38 +28,42 @@ DEBUG: processing line #1 - {"directProjectId":"24568","projectId":"(dynamic loa
2728
WARN: #1 - externalId is missing
2829
DEBUG: processed line #1
2930
DEBUG: processing line #2 - {"directProjectId":"24568","projectId":"(dynamic load)","externalId":"0","title":"taas-demo-job5","startDate":"10/26/2020","endDate":"01/29/2021","numPositions":"2","userHandle":"not_found_handle","jobid":"(dynamic load)","customerRate":"20","memberRate":"10","_lnum":2}
30-
ERROR: #2 - handle: not_found_handle user not found
31+
ERROR: #2 - id: 51ce2216-0dee-4dcf-bf7d-79f862e8d63c job created; handle: not_found_handle user not found
3132
DEBUG: processed line #2
3233
DEBUG: processing line #3 - {"directProjectId":"24568","projectId":"(dynamic load)","externalId":"0","title":"taas-demo-job5","startDate":"10/26/2020","endDate":"01/29/2021","numPositions":"2","userHandle":"nkumartest","jobid":"(dynamic load)","customerRate":"20","memberRate":"10","_lnum":3}
3334
DEBUG: userHandle: nkumartest userId: 57646ff9-1cd3-4d3c-88ba-eb09a395366c
34-
DEBUG: resourceBookingId: dc8b23d4-9987-4a7d-a587-2056283223de status: assigned
35-
INFO: #3 - id: 7c8ed989-35bf-4899-9c93-708630a7c63b job already exists; id: dc8b23d4-9987-4a7d-a587-2056283223de resource booking created; id: dc8b23d4-9987-4a7d-a587-2056283223de status: assigned resource booking updated
35+
INFO: #3 - id: 51ce2216-0dee-4dcf-bf7d-79f862e8d63c externalId: 0 job already exists; id: d49d2fbd-ba11-49dc-8eaa-5afafa7e993f resource booking created
3636
DEBUG: processed line #3
3737
DEBUG: processing line #4 - {"directProjectId":"24567","projectId":"(dynamic load)","externalId":"1212","title":"Dummy Description","startDate":"10/20/2020","endDate":"01/29/2021","numPositions":"2","userHandle":"pshah_manager","jobid":"(dynamic load)","customerRate":"150","memberRate":"100","_lnum":4}
3838
DEBUG: userHandle: pshah_manager userId: a55fe1bc-1754-45fa-9adc-cf3d6d7c377a
39-
DEBUG: resourceBookingId: 708469fb-ead0-4fc3-bef7-1ef4dd041428 status: assigned
40-
INFO: #4 - id: f61da880-5295-40c2-b6db-21e6cdef93f9 job created; id: 708469fb-ead0-4fc3-bef7-1ef4dd041428 resource booking created; id: 708469fb-ead0-4fc3-bef7-1ef4dd041428 status: assigned resource booking updated
39+
INFO: #4 - id: e0267551-24fe-48b5-9605-719852901de2 job created; id: f6285f03-056d-446f-a69b-6d275a97d68a resource booking created
4140
DEBUG: processed line #4
4241
DEBUG: processing line #5 - {"directProjectId":"24566","projectId":"(dynamic load)","externalId":"23850272","title":"33fromzaps330","startDate":"02/21/2021","endDate":"03/15/2021","numPositions":"7","userHandle":"nkumar2","jobid":"(dynamic load)","customerRate":"50","memberRate":"30","_lnum":5}
4342
DEBUG: userHandle: nkumar2 userId: 4b00d029-c87b-47b2-bfe2-0ab80d8b5774
44-
DEBUG: resourceBookingId: 7870c30b-e511-48f2-8687-499ab116174f status: assigned
45-
INFO: #5 - id: 72dc0399-5e4b-4783-9a27-ea07a4ce99a7 job created; id: 7870c30b-e511-48f2-8687-499ab116174f resource booking created; id: 7870c30b-e511-48f2-8687-499ab116174f status: assigned resource booking updated
43+
INFO: #5 - id: cd94784c-432d-4c46-b860-04a89e7b1099 job created; id: 98604c13-c6f3-4203-b74f-db376e9f02e4 resource booking created
4644
DEBUG: processed line #5
4745
DEBUG: processing line #6 - {"directProjectId":"24565","projectId":"(dynamic load)","externalId":"23843365","title":"Designer","startDate":"02/24/2021","endDate":"03/30/2021","numPositions":"1","userHandle":"GunaK-TopCoder","jobid":"(dynamic load)","customerRate":"70","memberRate":"70","_lnum":6}
4846
DEBUG: userHandle: GunaK-TopCoder userId: 2bba34d5-20e4-46d6-bfc1-05736b17afbb
49-
DEBUG: resourceBookingId: b2e705d3-6864-4697-96bb-dc2a288755bc status: assigned
50-
INFO: #6 - id: 7ff0737e-958c-494e-8a5a-592ac1c5d4ff job created; id: b2e705d3-6864-4697-96bb-dc2a288755bc resource booking created; id: b2e705d3-6864-4697-96bb-dc2a288755bc status: assigned resource booking updated
47+
INFO: #6 - id: 49883150-59c2-4e5b-b5c3-aaf6d11d0da2 job created; id: 5505b6b5-050c-421c-893f-b862b1a08092 resource booking created
5148
DEBUG: processed line #6
5249
DEBUG: processing line #7 - {"directProjectId":"24564","projectId":"(dynamic load)","externalId":"23836459","title":"demo-dev-19janV4","startDate":"01/20/2021","endDate":"01/30/2021","numPositions":"1","userHandle":"nkumar1","jobid":"(dynamic load)","customerRate":"400","memberRate":"200","_lnum":7}
5350
DEBUG: userHandle: nkumar1 userId: ab19a53b-0607-4a99-8bdd-f3b0cb552293
54-
DEBUG: resourceBookingId: 04299b4c-3f6e-4b3e-ae57-bf8232408cf9 status: assigned
55-
INFO: #7 - id: 73301ade-40ff-4103-bd50-37b8d2a98183 job created; id: 04299b4c-3f6e-4b3e-ae57-bf8232408cf9 resource booking created; id: 04299b4c-3f6e-4b3e-ae57-bf8232408cf9 status: assigned resource booking updated
51+
INFO: #7 - id: b03dc641-d6be-4a15-9c86-ef38f0e20c28 job created; id: 8e332107-453b-4ec5-b934-902c829e73a2 resource booking created
5652
DEBUG: processed line #7
5753
INFO: === summary ===
5854
INFO: total: 7
5955
INFO: success: 5
6056
INFO: failure: 1
6157
INFO: skips: 1
58+
INFO: jobs created: 5
59+
INFO: resource bookings created: 5
60+
INFO: jobs already exist: 1
61+
INFO: resource bookings already exist: 0
62+
INFO: validation errors: 0
63+
INFO: user not found: 1
64+
INFO: external id missing: 1
65+
INFO: request error: 0
66+
INFO: internal error: 0
6267
INFO: === summary ===
6368
INFO: done!
6469
```

scripts/recruit-crm-job-import/helper.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ async function getJobByExternalId (externalId) {
5454
* Update the status of a resource booking.
5555
*
5656
* @param {String} resourceBookingId the resource booking id
57-
* @param {String} status the status for the resource booking
57+
* @param {Object} data the data to update
5858
* @returns {Object} the result
5959
*/
60-
async function updateResourceBookingStatus (resourceBookingId, status) {
60+
async function updateResourceBooking (resourceBookingId, data) {
6161
const token = await getM2MToken()
6262
const { body: resourceBooking } = await request.patch(`${config.TAAS_API_URL}/resourceBookings/${resourceBookingId}`)
6363
.set('Authorization', `Bearer ${token}`)
6464
.set('Content-Type', 'application/json')
65-
.send({ status })
65+
.send(data)
6666
return resourceBooking
6767
}
6868

@@ -139,7 +139,7 @@ module.exports = {
139139
getPathnameFromCommandline: commonHelper.getPathnameFromCommandline,
140140
createJob,
141141
getJobByExternalId,
142-
updateResourceBookingStatus,
142+
updateResourceBooking,
143143
getResourceBookingByJobIdAndUserId,
144144
createResourceBooking,
145145
getUserByHandle,

scripts/recruit-crm-job-import/index.js

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
const Joi = require('joi')
66
.extend(require('@joi/date'))
77
const _ = require('lodash')
8-
const dateFNS = require('date-fns')
8+
const moment = require('moment')
99
const Report = require('./report')
1010
const config = require('./config')
1111
const helper = require('./helper')
@@ -18,12 +18,12 @@ const jobSchema = Joi.object({
1818
title: Joi.string().required(),
1919
startDate: Joi.date().format('MM/DD/YYYY').required(),
2020
endDate: Joi.date().format('MM/DD/YYYY').required(),
21-
numPositions: Joi.number().integer().min(1),
21+
numPositions: Joi.number().integer().min(1).required(),
2222
userHandle: Joi.string(),
2323
customerRate: Joi.number(),
2424
memberRate: Joi.number(),
2525
skills: Joi.array().default([]),
26-
rateType: Joi.string().default('weekly')
26+
rateType: Joi.string().default('weekly').valid('hourly', 'daily', 'weekly', 'monthly', 'annual')
2727
}).unknown(true)
2828

2929
/**
@@ -67,33 +67,51 @@ async function processJob (job, info = []) {
6767
data.jobId = result.id
6868
} catch (err) {
6969
if (!(err.message && err.message.includes('job not found'))) {
70+
err.info = info
7071
throw err
7172
}
72-
const result = await helper.createJob(_.pick(data, ['projectId', 'externalId', 'title', 'numPositions', 'skills']))
73+
const jobData = _.pick(data, ['projectId', 'externalId', 'title', 'numPositions', 'skills'])
74+
if (data.numPositions === 1) {
75+
jobData.status = 'assigned'
76+
}
77+
const result = await helper.createJob(jobData)
7378
info.push({ text: `id: ${result.id} job created`, tag: 'job_created' })
7479
data.jobId = result.id
7580
}
76-
data.userId = (await helper.getUserByHandle(data.userHandle)).id
77-
logger.debug(`userHandle: ${data.userHandle} userId: ${data.userId}`)
81+
try {
82+
data.userId = (await helper.getUserByHandle(data.userHandle)).id
83+
logger.debug(`userHandle: ${data.userHandle} userId: ${data.userId}`)
84+
} catch (err) {
85+
if (!(err.message && err.message.includes('user not found'))) {
86+
err.info = info
87+
throw err
88+
}
89+
info.push({ text: err.message, tag: 'user_not_found' })
90+
return { status: constants.ProcessingStatus.Failed, info }
91+
}
7892
// create a resource booking if it does not already exist
7993
try {
8094
const result = await helper.getResourceBookingByJobIdAndUserId(data.jobId, data.userId)
8195
info.push({ text: `id: ${result.id} resource booking already exists`, tag: 'resource_booking_already_exists' })
8296
return { status: constants.ProcessingStatus.Successful, info }
8397
} catch (err) {
8498
if (!(err.message && err.message.includes('resource booking not found'))) {
99+
err.info = info
100+
throw err
101+
}
102+
try {
103+
const resourceBookingData = _.pick(data, ['projectId', 'jobId', 'userId', 'memberRate', 'customerRate', 'rateType'])
104+
resourceBookingData.startDate = moment(data.startDate).format('YYYY-MM-DD')
105+
resourceBookingData.endDate = moment(data.endDate).format('YYYY-MM-DD')
106+
resourceBookingData.status = moment(data.endDate).isBefore(moment()) ? 'closed' : 'placed'
107+
const result = await helper.createResourceBooking(resourceBookingData)
108+
info.push({ text: `id: ${result.id} resource booking created`, tag: 'resource_booking_created' })
109+
return { status: constants.ProcessingStatus.Successful, info }
110+
} catch (err) {
111+
err.info = info
85112
throw err
86113
}
87-
const result = await helper.createResourceBooking(_.pick(data, ['projectId', 'jobId', 'userId', 'startDate', 'endDate', 'memberRate', 'customerRate', 'rateType']))
88-
info.push({ text: `id: ${result.id} resource booking created`, tag: 'resource_booking_created' })
89-
data.resourceBookingId = result.id
90114
}
91-
// update the resourceBooking based on startDate and endDate
92-
const resourceBookingStatus = dateFNS.isBefore(data.endDate, dateFNS.startOfToday()) ? 'closed' : 'placed'
93-
logger.debug(`resourceBookingId: ${data.resourceBookingId} status: ${resourceBookingStatus}`)
94-
await helper.updateResourceBookingStatus(data.resourceBookingId, resourceBookingStatus)
95-
info.push({ text: `id: ${data.resourceBookingId} status: ${resourceBookingStatus} resource booking updated`, tag: 'resource_booking_status_updated' })
96-
return { status: constants.ProcessingStatus.Successful, info }
97115
}
98116

99117
/**
@@ -111,10 +129,11 @@ async function main () {
111129
const result = await processJob(job)
112130
report.add({ lnum: job._lnum, ...result })
113131
} catch (err) {
132+
const info = err.info || []
114133
if (err.response) {
115-
report.add({ lnum: job._lnum, status: constants.ProcessingStatus.Failed, info: [{ text: err.response.error.toString().split('\n')[0], tag: 'request_error' }] })
134+
report.add({ lnum: job._lnum, status: constants.ProcessingStatus.Failed, info: [{ text: err.response.error.toString().split('\n')[0], tag: 'request_error' }, ...info] })
116135
} else {
117-
report.add({ lnum: job._lnum, status: constants.ProcessingStatus.Failed, info: [{ text: err.message, tag: 'internal_error' }] })
136+
report.add({ lnum: job._lnum, status: constants.ProcessingStatus.Failed, info: [{ text: err.message, tag: 'internal_error' }, ...info] })
118137
}
119138
}
120139
report.print()

scripts/recruit-crm-job-import/report.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ class Report {
4444
const resourceBookingsCreated = groupsByTag.resource_booking_created || []
4545
const jobsAlreadyExist = groupsByTag.job_already_exists || []
4646
const resourceBookingsAlreadyExist = groupsByTag.resource_booking_already_exists || []
47+
const validationErrors = groupsByTag.validation_error || []
48+
const userNotFound = groupsByTag.user_not_found || []
49+
const externalIdMissing = groupsByTag.external_id_missing || []
50+
const requestError = groupsByTag.request_error || []
51+
const internalError = groupsByTag.internal_error || []
4752
logger.info('=== summary ===')
4853
logger.info(`total: ${this.messages.length}`)
4954
logger.info(`success: ${success.length}`)
@@ -53,6 +58,11 @@ class Report {
5358
logger.info(`resource bookings created: ${resourceBookingsCreated.length}`)
5459
logger.info(`jobs already exist: ${jobsAlreadyExist.length}`)
5560
logger.info(`resource bookings already exist: ${resourceBookingsAlreadyExist.length}`)
61+
logger.info(`validation errors: ${validationErrors.length}`)
62+
logger.info(`user not found: ${userNotFound.length}`)
63+
logger.info(`external id missing: ${externalIdMissing.length}`)
64+
logger.info(`request error: ${requestError.length}`)
65+
logger.info(`internal error: ${internalError.length}`)
5666
logger.info('=== summary ===')
5767
}
5868
}

src/eventHandlers/ResourceBookingEventHandler.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,11 @@ async function assignJob (payload) {
102102
return
103103
}
104104
const job = await models.Job.findById(resourceBooking.jobId)
105-
if (job.status === 'placed') {
105+
if (job.status === 'placed' || job.status === 'assigned') {
106106
logger.debug({
107107
component: 'ResourceBookingEventHandler',
108108
context: 'assignJob',
109-
message: `job with projectId ${job.projectId} is already placed`
109+
message: `job with projectId ${job.projectId} is already ${job.status}`
110110
})
111111
return
112112
}

0 commit comments

Comments
 (0)