Skip to content

Commit 8fdd9ef

Browse files
Merge pull request #100 from imcaizheng/job-candidate-add-external-id-and-resume
add externalId and resume fields to the JobCanidate model
2 parents c1225a2 + d3873f8 commit 8fdd9ef

6 files changed

+114
-25
lines changed

docs/Topcoder-bookings-api.postman_collection.json

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"info": {
3-
"_postman_id": "cc3d894d-9cf4-4711-bd64-5515b4cf945c",
3+
"_postman_id": "b1144d77-699c-47be-864e-fbe99e7f5c14",
44
"name": "Topcoder-bookings-api",
55
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
66
},
@@ -1625,7 +1625,7 @@
16251625
],
16261626
"body": {
16271627
"mode": "raw",
1628-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}",
1628+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
16291629
"options": {
16301630
"raw": {
16311631
"language": "json"
@@ -1669,7 +1669,7 @@
16691669
],
16701670
"body": {
16711671
"mode": "raw",
1672-
"raw": "{\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}",
1672+
"raw": "{\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
16731673
"options": {
16741674
"raw": {
16751675
"language": "json"
@@ -1713,7 +1713,7 @@
17131713
],
17141714
"body": {
17151715
"mode": "raw",
1716-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}",
1716+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
17171717
"options": {
17181718
"raw": {
17191719
"language": "json"
@@ -1757,7 +1757,7 @@
17571757
],
17581758
"body": {
17591759
"mode": "raw",
1760-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}",
1760+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
17611761
"options": {
17621762
"raw": {
17631763
"language": "json"
@@ -1801,7 +1801,7 @@
18011801
],
18021802
"body": {
18031803
"mode": "raw",
1804-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}",
1804+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
18051805
"options": {
18061806
"raw": {
18071807
"language": "json"
@@ -1844,7 +1844,7 @@
18441844
],
18451845
"body": {
18461846
"mode": "raw",
1847-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\"\r\n}",
1847+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
18481848
"options": {
18491849
"raw": {
18501850
"language": "json"
@@ -2043,6 +2043,11 @@
20432043
"key": "status",
20442044
"value": "shortlist",
20452045
"disabled": true
2046+
},
2047+
{
2048+
"key": "externalId",
2049+
"value": "300234321",
2050+
"disabled": true
20462051
}
20472052
]
20482053
}
@@ -2103,6 +2108,11 @@
21032108
"key": "status",
21042109
"value": "shortlist",
21052110
"disabled": true
2111+
},
2112+
{
2113+
"key": "externalId",
2114+
"value": "300234321",
2115+
"disabled": true
21062116
}
21072117
]
21082118
}
@@ -2163,6 +2173,11 @@
21632173
"key": "status",
21642174
"value": "shortlist",
21652175
"disabled": true
2176+
},
2177+
{
2178+
"key": "externalId",
2179+
"value": "300234321",
2180+
"disabled": true
21662181
}
21672182
]
21682183
}
@@ -2221,6 +2236,11 @@
22212236
"key": "status",
22222237
"value": "shortlist",
22232238
"disabled": true
2239+
},
2240+
{
2241+
"key": "externalId",
2242+
"value": "300234321",
2243+
"disabled": true
22242244
}
22252245
]
22262246
}
@@ -2279,6 +2299,11 @@
22792299
"key": "status",
22802300
"value": "shortlist",
22812301
"disabled": true
2302+
},
2303+
{
2304+
"key": "externalId",
2305+
"value": "300234321",
2306+
"disabled": true
22822307
}
22832308
]
22842309
}
@@ -2298,7 +2323,7 @@
22982323
],
22992324
"body": {
23002325
"mode": "raw",
2301-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}",
2326+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
23022327
"options": {
23032328
"raw": {
23042329
"language": "json"
@@ -2331,7 +2356,7 @@
23312356
],
23322357
"body": {
23332358
"mode": "raw",
2334-
"raw": "{\r\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}",
2359+
"raw": "{\n \"jobId\": \"{{jobIdCreatedByM2M}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
23352360
"options": {
23362361
"raw": {
23372362
"language": "json"
@@ -2364,7 +2389,7 @@
23642389
],
23652390
"body": {
23662391
"mode": "raw",
2367-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}",
2392+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
23682393
"options": {
23692394
"raw": {
23702395
"language": "json"
@@ -2397,7 +2422,7 @@
23972422
],
23982423
"body": {
23992424
"mode": "raw",
2400-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}",
2425+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
24012426
"options": {
24022427
"raw": {
24032428
"language": "json"
@@ -2430,7 +2455,7 @@
24302455
],
24312456
"body": {
24322457
"mode": "raw",
2433-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}",
2458+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
24342459
"options": {
24352460
"raw": {
24362461
"language": "json"
@@ -2463,7 +2488,7 @@
24632488
],
24642489
"body": {
24652490
"mode": "raw",
2466-
"raw": "{\r\n \"jobId\": \"{{jobId}}\",\r\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\r\n \"status\": \"selected\"\r\n}",
2491+
"raw": "{\n \"jobId\": \"{{jobId}}\",\n \"userId\": \"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a\",\n \"status\": \"selected\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
24672492
"options": {
24682493
"raw": {
24692494
"language": "json"
@@ -2496,7 +2521,7 @@
24962521
],
24972522
"body": {
24982523
"mode": "raw",
2499-
"raw": "{\r\n \"status\": \"shortlist\"\r\n}",
2524+
"raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
25002525
"options": {
25012526
"raw": {
25022527
"language": "json"
@@ -2529,7 +2554,7 @@
25292554
],
25302555
"body": {
25312556
"mode": "raw",
2532-
"raw": "{\r\n \"status\": \"shortlist\"\r\n}",
2557+
"raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
25332558
"options": {
25342559
"raw": {
25352560
"language": "json"
@@ -2562,7 +2587,7 @@
25622587
],
25632588
"body": {
25642589
"mode": "raw",
2565-
"raw": "{\r\n \"status\": \"shortlist\"\r\n}",
2590+
"raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
25662591
"options": {
25672592
"raw": {
25682593
"language": "json"
@@ -2595,7 +2620,7 @@
25952620
],
25962621
"body": {
25972622
"mode": "raw",
2598-
"raw": "{\r\n \"status\": \"shortlist\"\r\n}",
2623+
"raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
25992624
"options": {
26002625
"raw": {
26012626
"language": "json"
@@ -2628,7 +2653,7 @@
26282653
],
26292654
"body": {
26302655
"mode": "raw",
2631-
"raw": "{\r\n \"status\": \"shortlist\"\r\n}",
2656+
"raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
26322657
"options": {
26332658
"raw": {
26342659
"language": "json"
@@ -2661,7 +2686,7 @@
26612686
],
26622687
"body": {
26632688
"mode": "raw",
2664-
"raw": "{\r\n \"status\": \"shortlist\"\r\n}",
2689+
"raw": "{\n \"status\": \"shortlist\",\n \"externalId\": \"300234321\",\n \"resume\": \"http://example.com\"\n}",
26652690
"options": {
26662691
"raw": {
26672692
"language": "json"

docs/swagger.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,12 @@ paths:
584584
type: string
585585
enum: ['open', 'selected', 'shortlist', 'rejected', 'cancelled']
586586
description: The job candidate status.
587+
- in: query
588+
name: externalId
589+
required: false
590+
schema:
591+
type: string
592+
description: The external id.
587593
responses:
588594
'200':
589595
description: OK
@@ -1797,6 +1803,14 @@ components:
17971803
type: string
17981804
enum: ['open', 'selected', 'shortlist', 'rejected', 'cancelled']
17991805
description: "The job candidate status."
1806+
externalId:
1807+
type: string
1808+
example: "1212"
1809+
description: "The external id."
1810+
resume:
1811+
type: string
1812+
example: "http://example.com"
1813+
description: "The resume link"
18001814
createdAt:
18011815
type: string
18021816
format: date-time
@@ -1827,11 +1841,27 @@ components:
18271841
format: uuid
18281842
example: "a55fe1bc-1754-45fa-9adc-cf3d6d7c377a"
18291843
description: "The user id."
1844+
externalId:
1845+
type: string
1846+
example: "1212"
1847+
description: "The external id."
1848+
resume:
1849+
type: string
1850+
example: "http://example.com"
1851+
description: "The resume link"
18301852
JobCandidatePatchRequestBody:
18311853
properties:
18321854
status:
18331855
type: string
18341856
enum: ['open', 'selected', 'shortlist', 'rejected', 'cancelled']
1857+
externalId:
1858+
type: string
1859+
example: "1212"
1860+
description: "The external id."
1861+
resume:
1862+
type: string
1863+
example: "http://example.com"
1864+
description: "The resume link"
18351865
JobPatchRequestBody:
18361866
properties:
18371867
status:
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Add externalId and resume fields to the JobCandidate model.
3+
*/
4+
5+
module.exports = {
6+
up: queryInterface => {
7+
return Promise.all([
8+
queryInterface.sequelize.query('ALTER TABLE bookings.job_candidates ADD external_id VARCHAR(255)'),
9+
queryInterface.sequelize.query('ALTER TABLE bookings.job_candidates ADD resume VARCHAR(2048)')
10+
])
11+
},
12+
down: queryInterface => {
13+
return Promise.all([
14+
queryInterface.sequelize.query('ALTER TABLE bookings.job_candidates DROP external_id'),
15+
queryInterface.sequelize.query('ALTER TABLE bookings.job_candidates DROP resume')
16+
])
17+
}
18+
}

scripts/createIndex.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ async function createIndex () {
4343
jobId: { type: 'keyword' },
4444
userId: { type: 'keyword' },
4545
status: { type: 'keyword' },
46+
externalId: { type: 'keyword' },
47+
resume: { type: 'text' },
4648
createdAt: { type: 'date' },
4749
createdBy: { type: 'keyword' },
4850
updatedAt: { type: 'date' },

src/models/JobCandidate.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ module.exports = (sequelize) => {
5656
type: Sequelize.STRING,
5757
allowNull: false
5858
},
59+
externalId: {
60+
field: 'external_id',
61+
type: Sequelize.STRING
62+
},
63+
resume: {
64+
type: Sequelize.STRING
65+
},
5966
createdAt: {
6067
field: 'created_at',
6168
type: Sequelize.DATE,

src/services/JobCandidateService.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ createJobCandidate.schema = Joi.object().keys({
103103
currentUser: Joi.object().required(),
104104
jobCandidate: Joi.object().keys({
105105
jobId: Joi.string().uuid().required(),
106-
userId: Joi.string().uuid().required()
106+
userId: Joi.string().uuid().required(),
107+
externalId: Joi.string(),
108+
resume: Joi.string().uri()
107109
}).required()
108110
}).required()
109111

@@ -148,7 +150,9 @@ partiallyUpdateJobCandidate.schema = Joi.object().keys({
148150
currentUser: Joi.object().required(),
149151
id: Joi.string().uuid().required(),
150152
data: Joi.object().keys({
151-
status: Joi.jobCandidateStatus()
153+
status: Joi.jobCandidateStatus(),
154+
externalId: Joi.string(),
155+
resume: Joi.string().uri()
152156
}).required()
153157
}).required()
154158

@@ -171,7 +175,9 @@ fullyUpdateJobCandidate.schema = Joi.object().keys({
171175
data: Joi.object().keys({
172176
jobId: Joi.string().uuid().required(),
173177
userId: Joi.string().uuid().required(),
174-
status: Joi.jobCandidateStatus()
178+
status: Joi.jobCandidateStatus(),
179+
externalId: Joi.string(),
180+
resume: Joi.string().uri()
175181
}).required()
176182
}).required()
177183

@@ -236,7 +242,7 @@ async function searchJobCandidates (currentUser, criteria) {
236242
}
237243
}
238244

239-
_.each(_.pick(criteria, ['jobId', 'userId', 'status']), (value, key) => {
245+
_.each(_.pick(criteria, ['jobId', 'userId', 'status', 'externalId']), (value, key) => {
240246
esQuery.body.query.bool.must.push({
241247
term: {
242248
[key]: {
@@ -266,7 +272,7 @@ async function searchJobCandidates (currentUser, criteria) {
266272
const filter = {
267273
[Op.and]: [{ deletedAt: null }]
268274
}
269-
_.each(_.pick(criteria, ['jobId', 'userId', 'status']), (value, key) => {
275+
_.each(_.pick(criteria, ['jobId', 'userId', 'status', 'externalId']), (value, key) => {
270276
filter[Op.and].push({ [key]: value })
271277
})
272278
const jobCandidates = await JobCandidate.findAll({
@@ -296,7 +302,8 @@ searchJobCandidates.schema = Joi.object().keys({
296302
sortOrder: Joi.string().valid('desc', 'asc'),
297303
jobId: Joi.string().uuid(),
298304
userId: Joi.string().uuid(),
299-
status: Joi.jobCandidateStatus()
305+
status: Joi.jobCandidateStatus(),
306+
externalId: Joi.string()
300307
}).required()
301308
}).required()
302309

0 commit comments

Comments
 (0)