Skip to content

Commit cf38c92

Browse files
authored
Merge branch 'dev' into feature/api-updates
2 parents 7370849 + 4a24d73 commit cf38c92

17 files changed

+336
-16
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ The following parameters can be set in config files or in env variables:
3838
- `topics.TAAS_INTERVIEW_REQUEST_TOPIC`: the request interview entity Kafka message topic
3939
- `topics.TAAS_INTERVIEW_UPDATE_TOPIC`: the update interview entity Kafka message topic
4040
- `topics.TAAS_INTERVIEW_BULK_UPDATE_TOPIC`: the bulk update interview entity Kafka message topic
41+
- `topics.TAAS_ROLE_CREATE_TOPIC`: the create role entity Kafka message topic
42+
- `topics.TAAS_ROLE_UPDATE_TOPIC`: the update role entity Kafka message topic
43+
- `topics.TAAS_ROLE_DELETE_TOPIC`: the delete role entity Kafka message topic
4144
- `esConfig.HOST`: Elasticsearch host
4245
- `esConfig.AWS_REGION`: The Amazon region to use when using AWS Elasticsearch service
4346
- `esConfig.ELASTICCLOUD.id`: The elastic cloud id, if your elasticsearch instance is hosted on elastic cloud. DO NOT provide a value for ES_HOST if you are using this
@@ -46,6 +49,7 @@ The following parameters can be set in config files or in env variables:
4649
- `esConfig.ES_INDEX_JOB`: the index name for job
4750
- `esConfig.ES_INDEX_JOB_CANDIDATE`: the index name for job candidate
4851
- `esConfig.ES_INDEX_RESOURCE_BOOKING`: the index name for resource booking
52+
- `esConfig.ES_INDEX_ROLE`: the index name for role
4953

5054
- `auth0.AUTH0_URL`: Auth0 URL, used to get TC M2M token
5155
- `auth0.AUTH0_AUDIENCE`: Auth0 audience, used to get TC M2M token

VERIFICATION.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Create documents in ES
44

5-
- Run the following commands to create `Job`, `JobCandidate`, `Interview`, `ResourceBooking`, `WorkPeriod`, `WorkPeriodPayment` documents in ES.
5+
- Run the following commands to create `Job`, `JobCandidate`, `Interview`, `ResourceBooking`, `WorkPeriod`, `WorkPeriodPayment`, `Role` documents in ES.
66

77
``` bash
88
# for Job
@@ -17,12 +17,14 @@
1717
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.workperiod.create < test/messages/taas.workperiod.create.event.json
1818
# for WorkPeriodPayment
1919
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.workperiodpayment.create < test/messages/taas.workperiodpayment.create.event.json
20+
# for Role
21+
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.role.requested < test/messages/taas.role.create.event.json
2022
```
2123

2224
- Run `npm run view-data <model-name-here>` to see if documents were created.
2325

2426
## Update documents in ES
25-
- Run the following commands to update `Job`, `JobCandidate`, `Interview`, `ResourceBooking`, `WorkPeriod`, `WorkPeriodPayment` documents in ES.
27+
- Run the following commands to update `Job`, `JobCandidate`, `Interview`, `ResourceBooking`, `WorkPeriod`, `WorkPeriodPayment`, `Role` documents in ES.
2628

2729
``` bash
2830
# for Job
@@ -37,12 +39,14 @@
3739
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.workperiod.update < test/messages/taas.workperiod.update.event.json
3840
# for WorkPeriodPayment
3941
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.workperiodpayment.update < test/messages/taas.workperiodpayment.update.event.json
42+
# for Role
43+
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.role.update < test/messages/taas.role.update.event.json
4044
```
4145

4246
- Run `npm run view-data <model-name-here>` to see if documents were updated.
4347

4448
## Delete documents in ES
45-
- Run the following commands to delete `Job`, `JobCandidate`, `ResourceBooking`, `WorkPeriod` documents in ES.
49+
- Run the following commands to delete `Job`, `JobCandidate`, `ResourceBooking`, `WorkPeriod`, `Role` documents in ES.
4650

4751
``` bash
4852
# for Job
@@ -53,6 +57,8 @@
5357
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.resourcebooking.delete < test/messages/taas.resourcebooking.delete.event.json
5458
# for WorkPeriod
5559
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.workperiod.delete < test/messages/taas.workperiod.delete.event.json
60+
# for Role
61+
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.role.delete < test/messages/taas.role.delete.event.json
5662
```
5763

5864
- Run `npm run view-data <model-name-here>` to see if documents were deleted.

config/default.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ module.exports = {
3838
// topics for interview service
3939
TAAS_INTERVIEW_REQUEST_TOPIC: process.env.TAAS_INTERVIEW_REQUEST_TOPIC || 'taas.interview.requested',
4040
TAAS_INTERVIEW_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_UPDATE_TOPIC || 'taas.interview.update',
41-
TAAS_INTERVIEW_BULK_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_BULK_UPDATE_TOPIC || 'taas.interview.bulkUpdate'
41+
TAAS_INTERVIEW_BULK_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_BULK_UPDATE_TOPIC || 'taas.interview.bulkUpdate',
42+
// topics for role service
43+
TAAS_ROLE_CREATE_TOPIC: process.env.TAAS_ROLE_CREATE_TOPIC || 'taas.role.requested',
44+
TAAS_ROLE_UPDATE_TOPIC: process.env.TAAS_ROLE_UPDATE_TOPIC || 'taas.role.update',
45+
TAAS_ROLE_DELETE_TOPIC: process.env.TAAS_ROLE_DELETE_TOPIC || 'taas.role.delete'
4246
},
4347

4448
esConfig: {
@@ -54,7 +58,8 @@ module.exports = {
5458

5559
ES_INDEX_JOB: process.env.ES_INDEX_JOB || 'job',
5660
ES_INDEX_JOB_CANDIDATE: process.env.ES_INDEX_JOB_CANDIDATE || 'job_candidate',
57-
ES_INDEX_RESOURCE_BOOKING: process.env.ES_INDEX_RESOURCE_BOOKING || 'resource_booking'
61+
ES_INDEX_RESOURCE_BOOKING: process.env.ES_INDEX_RESOURCE_BOOKING || 'resource_booking',
62+
ES_INDEX_ROLE: process.env.ES_INDEX_ROLE || 'role'
5863
},
5964

6065
auth0: {

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const ResourceBookingProcessorService = require('./services/ResourceBookingProce
1515
const WorkPeriodProcessorService = require('./services/WorkPeriodProcessorService')
1616
const InterviewProcessorService = require('./services/InterviewProcessorService')
1717
const WorkPeriodPaymentProcessorService = require('./services/WorkPeriodPaymentProcessorService')
18+
const RoleProcessorService = require('./services/RoleProcessorService')
1819
const Mutex = require('async-mutex').Mutex
1920
const events = require('events')
2021

@@ -52,7 +53,11 @@ const topicServiceMapping = {
5253
// interview
5354
[config.topics.TAAS_INTERVIEW_REQUEST_TOPIC]: InterviewProcessorService.processRequestInterview,
5455
[config.topics.TAAS_INTERVIEW_UPDATE_TOPIC]: InterviewProcessorService.processUpdateInterview,
55-
[config.topics.TAAS_INTERVIEW_BULK_UPDATE_TOPIC]: InterviewProcessorService.processBulkUpdateInterviews
56+
[config.topics.TAAS_INTERVIEW_BULK_UPDATE_TOPIC]: InterviewProcessorService.processBulkUpdateInterviews,
57+
// role
58+
[config.topics.TAAS_ROLE_CREATE_TOPIC]: RoleProcessorService.processCreate,
59+
[config.topics.TAAS_ROLE_UPDATE_TOPIC]: RoleProcessorService.processUpdate,
60+
[config.topics.TAAS_ROLE_DELETE_TOPIC]: RoleProcessorService.processDelete
5661
}
5762

5863
// Start kafka consumer

src/bootstrap.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Joi.workPeriodPaymentStatus = () => Joi.string().valid('completed', 'cancelled')
2323
// See https://joi.dev/api/?v=17.3.0#string fro details why it's like this.
2424
// In many cases we would like to allow empty string to make it easier to create UI for editing data.
2525
Joi.stringAllowEmpty = () => Joi.string().allow('')
26+
Joi.smallint = () => Joi.number().min(-32768).max(32767)
2627

2728
const zapierSwitch = Joi.string().label('ZAPIER_SWITCH').valid(...Object.values(constants.Zapier.Switch))
2829

src/scripts/createIndex.js

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ async function createIndex () {
2626
rateType: { type: 'keyword' },
2727
workload: { type: 'keyword' },
2828
skills: { type: 'keyword' },
29+
roles: { type: 'keyword' },
2930
status: { type: 'keyword' },
3031
isApplicationPageActive: { type: 'boolean' },
3132
minSalary: { type: 'integer' },
@@ -34,6 +35,7 @@ async function createIndex () {
3435
jobLocation: { type: 'keyword' },
3536
jobTimezone: { type: 'keyword' },
3637
currency: { type: 'keyword' },
38+
roleIds: { type: 'keyword' },
3739
createdAt: { type: 'date' },
3840
createdBy: { type: 'keyword' },
3941
updatedAt: { type: 'date' },
@@ -110,7 +112,8 @@ async function createIndex () {
110112
properties: {
111113
id: { type: 'keyword' },
112114
resourceBookingId: { type: 'keyword' },
113-
userHandle: { type: 'keyword' },
115+
userHandle: { type: 'keyword',
116+
normalizer: 'lowercaseNormalizer' },
114117
projectId: { type: 'integer' },
115118
userId: { type: 'keyword' },
116119
startDate: { type: 'date', format: 'yyyy-MM-dd' },
@@ -147,11 +150,66 @@ async function createIndex () {
147150
}
148151
}
149152
}
153+
},
154+
{ index: config.get('esConfig.ES_INDEX_ROLE'),
155+
body: {
156+
mappings: {
157+
properties: {
158+
name: { type: 'keyword' },
159+
description: { type: 'keyword' },
160+
listOfSkills: { type: 'keyword' },
161+
rates: {
162+
properties: {
163+
global: { type: 'integer' },
164+
inCountry: { type: 'integer' },
165+
offShore: { type: 'integer' },
166+
rate30Global: { type: 'integer' },
167+
rate30InCountry: { type: 'integer' },
168+
rate30OffShore: { type: 'integer' },
169+
rate20Global: { type: 'integer' },
170+
rate20InCountry: { type: 'integer' },
171+
rate20OffShore: { type: 'integer' }
172+
}
173+
},
174+
numberOfMembers: { type: 'integer' },
175+
numberOfMembersAvailable: { type: 'integer' },
176+
imageUrl: { type: 'keyword' },
177+
timeToCandidate: { type: 'integer' },
178+
timeToInterview: { type: 'integer' },
179+
createdAt: { type: 'date' },
180+
createdBy: { type: 'keyword' },
181+
updatedAt: { type: 'date' },
182+
updatedBy: { type: 'keyword' }
183+
}
184+
}
185+
}
150186
}
151187
]
152188

153189
for (const index of indices) {
154-
await esClient.indices.create(index)
190+
await esClient.indices.create({ index: index.index })
191+
await esClient.indices.close({ index: index.index })
192+
await esClient.indices.putSettings({
193+
index: index.index,
194+
body: {
195+
settings: {
196+
analysis: {
197+
normalizer: {
198+
lowercaseNormalizer: {
199+
filter: ['lowercase']
200+
}
201+
}
202+
}
203+
}
204+
}
205+
})
206+
await esClient.indices.open({ index: index.index })
207+
await esClient.indices.putMapping({
208+
index: index.index,
209+
body: {
210+
properties: index.body.mappings.properties
211+
}
212+
})
155213
logger.info({ component: 'createIndex', message: `ES Index ${index.index} creation succeeded!` })
156214
}
157215
process.exit(0)

src/scripts/deleteIndex.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ async function deleteIndex () {
1111
const esClient = helper.getESClient()
1212
const indices = [config.get('esConfig.ES_INDEX_JOB'),
1313
config.get('esConfig.ES_INDEX_JOB_CANDIDATE'),
14-
config.get('esConfig.ES_INDEX_RESOURCE_BOOKING')]
14+
config.get('esConfig.ES_INDEX_RESOURCE_BOOKING'),
15+
config.get('esConfig.ES_INDEX_ROLE')]
1516
for (const index of indices) {
1617
await esClient.indices.delete({
1718
index

src/scripts/view-data.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ const esClient = helper.getESClient()
1111
const modelIndexMapping = {
1212
Job: 'ES_INDEX_JOB',
1313
JobCandidate: 'ES_INDEX_JOB_CANDIDATE',
14-
ResourceBooking: 'ES_INDEX_RESOURCE_BOOKING'
14+
ResourceBooking: 'ES_INDEX_RESOURCE_BOOKING',
15+
Role: 'ES_INDEX_ROLE'
1516
}
1617

1718
async function showESData () {

src/services/JobProcessorService.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ processCreate.schema = {
7878
rateType: Joi.rateType().allow(null),
7979
workload: Joi.workload().allow(null),
8080
skills: Joi.array().items(Joi.string().uuid()).required(),
81+
roles: Joi.array().items(Joi.string().uuid()).allow(null),
8182
createdAt: Joi.date().required(),
8283
createdBy: Joi.string().uuid().required(),
8384
updatedAt: Joi.date().allow(null),
@@ -89,7 +90,8 @@ processCreate.schema = {
8990
hoursPerWeek: Joi.number().integer().required(),
9091
jobLocation: Joi.string().required(),
9192
jobTimezone: Joi.string().required(),
92-
currency: Joi.string().required()
93+
currency: Joi.string().required(),
94+
roleIds: Joi.array().items(Joi.string().uuid().required()).allow(null)
9395
}).required()
9496
}).required(),
9597
transactionId: Joi.string().required()

src/services/RoleProcessorService.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
* Role Processor Service
3+
*/
4+
5+
const Joi = require('@hapi/joi')
6+
const logger = require('../common/logger')
7+
const helper = require('../common/helper')
8+
const constants = require('../common/constants')
9+
const config = require('config')
10+
11+
const esClient = helper.getESClient()
12+
13+
/**
14+
* Process create entity message
15+
* @param {Object} message the kafka message
16+
* @param {String} transactionId
17+
*/
18+
async function processCreate (message, transactionId) {
19+
const role = message.payload
20+
await esClient.createExtra({
21+
index: config.get('esConfig.ES_INDEX_ROLE'),
22+
id: role.id,
23+
transactionId,
24+
body: role,
25+
refresh: constants.esRefreshOption
26+
})
27+
}
28+
29+
processCreate.schema = {
30+
message: Joi.object().keys({
31+
topic: Joi.string().required(),
32+
originator: Joi.string().required(),
33+
timestamp: Joi.date().required(),
34+
'mime-type': Joi.string().required(),
35+
payload: Joi.object().keys({
36+
id: Joi.string().uuid().required(),
37+
name: Joi.string().max(50).required(),
38+
description: Joi.string().max(1000).allow(null),
39+
listOfSkills: Joi.array().items(Joi.string().max(50).required()).allow(null),
40+
rates: Joi.array().items(Joi.object().keys({
41+
global: Joi.smallint().required(),
42+
inCountry: Joi.smallint().required(),
43+
offShore: Joi.smallint().required(),
44+
rate30Global: Joi.smallint().allow(null),
45+
rate30InCountry: Joi.smallint().allow(null),
46+
rate30OffShore: Joi.smallint().allow(null),
47+
rate20Global: Joi.smallint().allow(null),
48+
rate20InCountry: Joi.smallint().allow(null),
49+
rate20OffShore: Joi.smallint().allow(null)
50+
}).required()).required(),
51+
numberOfMembers: Joi.number().allow(null),
52+
numberOfMembersAvailable: Joi.smallint().allow(null),
53+
imageUrl: Joi.string().uri().max(255).allow(null),
54+
timeToCandidate: Joi.smallint().allow(null),
55+
timeToInterview: Joi.smallint().allow(null),
56+
createdAt: Joi.date().required(),
57+
createdBy: Joi.string().uuid().required(),
58+
updatedAt: Joi.date().allow(null),
59+
updatedBy: Joi.string().uuid().allow(null)
60+
}).required()
61+
}).required(),
62+
transactionId: Joi.string().required()
63+
}
64+
65+
/**
66+
* Process update entity message
67+
* @param {Object} message the kafka message
68+
* @param {String} transactionId
69+
*/
70+
async function processUpdate (message, transactionId) {
71+
const data = message.payload
72+
await esClient.updateExtra({
73+
index: config.get('esConfig.ES_INDEX_ROLE'),
74+
id: data.id,
75+
transactionId,
76+
body: {
77+
doc: data
78+
},
79+
refresh: constants.esRefreshOption
80+
})
81+
}
82+
83+
processUpdate.schema = processCreate.schema
84+
85+
/**
86+
* Process delete entity message
87+
* @param {Object} message the kafka message
88+
* @param {String} transactionId
89+
*/
90+
async function processDelete (message, transactionId) {
91+
const id = message.payload.id
92+
await esClient.deleteExtra({
93+
index: config.get('esConfig.ES_INDEX_ROLE'),
94+
id,
95+
transactionId,
96+
refresh: constants.esRefreshOption
97+
})
98+
}
99+
100+
processDelete.schema = {
101+
message: Joi.object().keys({
102+
topic: Joi.string().required(),
103+
originator: Joi.string().required(),
104+
timestamp: Joi.date().required(),
105+
'mime-type': Joi.string().required(),
106+
payload: Joi.object().keys({
107+
id: Joi.string().uuid().required()
108+
}).required()
109+
}).required(),
110+
transactionId: Joi.string().required()
111+
}
112+
113+
module.exports = {
114+
processCreate,
115+
processUpdate,
116+
processDelete
117+
}
118+
119+
logger.buildService(module.exports, 'RoleProcessorService')

test/common/testData.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ const messages = {
2626
create: { topic: 'taas.workperiodpayment.create', message: require('../messages/taas.workperiodpayment.create.event.json') },
2727
update: { topic: 'taas.workperiodpayment.update', message: require('../messages/taas.workperiodpayment.update.event.json') }
2828
},
29+
Role: {
30+
create: { topic: 'taas.role.requested', message: require('../messages/taas.role.create.event.json') },
31+
update: { topic: 'taas.role.update', message: require('../messages/taas.role.update.event.json') },
32+
delete: { topic: 'taas.role.delete', message: require('../messages/taas.role.delete.event .json') }
33+
},
2934
messageInvalid: '{ "topic": "taas.job.create", }'
3035
}
3136

0 commit comments

Comments
 (0)