Skip to content

Commit 47b825c

Browse files
authored
Merge branch 'dev' into feature/interview-scheduler
2 parents 36fa12d + c76d6a3 commit 47b825c

12 files changed

+174
-7
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ The following parameters can be set in config files or in env variables:
3535
- `topics.TAAS_WORK_PERIOD_DELETE_TOPIC`: the delete work period entity Kafka message topic
3636
- `topics.TAAS_INTERVIEW_REQUEST_TOPIC`: the request interview entity Kafka message topic
3737
- `topics.TAAS_INTERVIEW_UPDATE_TOPIC`: the update interview entity Kafka message topic
38+
- `topics.TAAS_WORK_PERIOD_PAYMENT_CREATE_TOPIC`: the create work period payment entity Kafka message topic
39+
- `topics.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC`: the update work period payment entity Kafka message topic
3840
- `esConfig.HOST`: Elasticsearch host
3941
- `esConfig.AWS_REGION`: The Amazon region to use when using AWS Elasticsearch service
4042
- `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

VERIFICATION.md

Lines changed: 6 additions & 2 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`, `ResourceBooking`, `WorkPeriod` documents in ES.
5+
- Run the following commands to create `Job`, `JobCandidate`, `ResourceBooking`, `WorkPeriod`, `WorkPeriodPayment` documents in ES.
66

77
``` bash
88
# for Job
@@ -13,12 +13,14 @@
1313
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.resourcebooking.create < test/messages/taas.resourcebooking.create.event.json
1414
# for WorkPeriod
1515
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
16+
# for WorkPeriodPayment
17+
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
1618
```
1719

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

2022
## Update documents in ES
21-
- Run the following commands to update `Job`, `JobCandidate`, `ResourceBooking`, `WorkPeriod` documents in ES.
23+
- Run the following commands to update `Job`, `JobCandidate`, `ResourceBooking`, `WorkPeriod`, `WorkPeriodPayment` documents in ES.
2224

2325
``` bash
2426
# for Job
@@ -29,6 +31,8 @@
2931
docker exec -i taas-es-processor_kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic taas.resourcebooking.update < test/messages/taas.resourcebooking.update.event.json
3032
# for WorkPeriod
3133
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
34+
# for WorkPeriodPayment
35+
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
3236
```
3337

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

config/default.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ module.exports = {
3434
TAAS_WORK_PERIOD_DELETE_TOPIC: process.env.TAAS_WORK_PERIOD_DELETE_TOPIC || 'taas.workperiod.delete',
3535
// topics for interview service
3636
TAAS_INTERVIEW_REQUEST_TOPIC: process.env.TAAS_INTERVIEW_REQUEST_TOPIC || 'taas.interview.requested',
37-
TAAS_INTERVIEW_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_UPDATE_TOPIC || 'taas.interview.update'
37+
TAAS_INTERVIEW_UPDATE_TOPIC: process.env.TAAS_INTERVIEW_UPDATE_TOPIC || 'taas.interview.update',
38+
// topics for work period payment service
39+
TAAS_WORK_PERIOD_PAYMENT_CREATE_TOPIC: process.env.TAAS_WORK_PERIOD_PAYMENT_CREATE_TOPIC || 'taas.workperiodpayment.create',
40+
TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC: process.env.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC || 'taas.workperiodpayment.update'
3841
},
3942

4043
esConfig: {

local/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ services:
1212
- "9092:9092"
1313
environment:
1414
KAFKA_ADVERTISED_HOST_NAME: localhost
15-
KAFKA_CREATE_TOPICS: "taas.job.create:1:1,taas.jobcandidate.create:1:1,taas.resourcebooking.create:1:1,taas.interview.requested:1:1,taas.interview.update:1:1,taas.job.update:1:1,taas.jobcandidate.update:1:1,taas.resourcebooking.update:1:1,taas.job.delete:1:1,taas.jobcandidate.delete:1:1,taas.resourcebooking.delete:1:1"
15+
KAFKA_CREATE_TOPICS: "taas.job.create:1:1,taas.jobcandidate.create:1:1,taas.resourcebooking.create:1:1,taas.interview.requested:1:1,taas.interview.update:1:1,taas.workperiod.create:1:1,taas.workperiodpayment.create:1:1,taas.job.update:1:1,taas.jobcandidate.update:1:1,taas.resourcebooking.update:1:1,taas.workperiod.update:1:1,taas.workperiodpayment.update:1:1,taas.job.delete:1:1,taas.jobcandidate.delete:1:1,taas.resourcebooking.delete:1:1,taas.workperiod.delete:1:1"
1616
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
1717
esearch:
1818
image: elasticsearch:7.7.1

src/app.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const JobCandidateProcessorService = require('./services/JobCandidateProcessorSe
1414
const ResourceBookingProcessorService = require('./services/ResourceBookingProcessorService')
1515
const WorkPeriodProcessorService = require('./services/WorkPeriodProcessorService')
1616
const InterviewProcessorService = require('./services/InterviewProcessorService')
17+
const WorkPeriodPaymentProcessorService = require('./services/WorkPeriodPaymentProcessorService')
1718
const Mutex = require('async-mutex').Mutex
1819
const events = require('events')
1920

@@ -47,7 +48,10 @@ const topicServiceMapping = {
4748
[config.topics.TAAS_WORK_PERIOD_DELETE_TOPIC]: WorkPeriodProcessorService.processDelete,
4849
// interview
4950
[config.topics.TAAS_INTERVIEW_REQUEST_TOPIC]: InterviewProcessorService.processRequestInterview,
50-
[config.topics.TAAS_INTERVIEW_UPDATE_TOPIC]: InterviewProcessorService.processUpdateInterview
51+
[config.topics.TAAS_INTERVIEW_UPDATE_TOPIC]: InterviewProcessorService.processUpdateInterview,
52+
// work period payment
53+
[config.topics.TAAS_WORK_PERIOD_PAYMENT_CREATE_TOPIC]: WorkPeriodPaymentProcessorService.processCreate,
54+
[config.topics.TAAS_WORK_PERIOD_PAYMENT_UPDATE_TOPIC]: WorkPeriodPaymentProcessorService.processUpdate
5155
}
5256

5357
// Start kafka consumer

src/bootstrap.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ global.Promise = require('bluebird')
1010

1111
Joi.rateType = () => Joi.string().valid('hourly', 'daily', 'weekly', 'monthly')
1212
Joi.jobStatus = () => Joi.string().valid('sourcing', 'in-review', 'assigned', 'closed', 'cancelled')
13+
Joi.resourceBookingStatus = () => Joi.string().valid('assigned', 'closed', 'cancelled')
1314
Joi.jobCandidateStatus = () => Joi.string().valid('open', 'selected', 'shortlist', 'rejected', 'cancelled', 'interview', 'topcoder-rejected')
1415
Joi.workload = () => Joi.string().valid('full-time', 'fractional')
1516
Joi.title = () => Joi.string().max(128)
1617
Joi.paymentStatus = () => Joi.string().valid('pending', 'partially-completed', 'completed', 'cancelled')
1718
Joi.interviewStatus = () => Joi.string().valid(...allowedInterviewStatuses)
19+
Joi.workPeriodPaymentStatus = () => Joi.string().valid('completed', 'cancelled')
1820
// Empty string is not allowed by Joi by default and must be enabled with allow('').
1921
// See https://joi.dev/api/?v=17.3.0#string fro details why it's like this.
2022
// In many cases we would like to allow empty string to make it easier to create UI for editing data.

src/scripts/createIndex.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@ async function createIndex () {
109109
memberRate: { type: 'float' },
110110
customerRate: { type: 'float' },
111111
paymentStatus: { type: 'keyword' },
112+
payments: {
113+
type: 'nested',
114+
properties: {
115+
workPeriodId: { type: 'keyword' },
116+
challengeId: { type: 'keyword' },
117+
amount: { type: 'float' },
118+
status: { type: 'keyword' },
119+
createdAt: { type: 'date' },
120+
createdBy: { type: 'keyword' },
121+
updatedAt: { type: 'date' },
122+
updatedBy: { type: 'keyword' }
123+
}
124+
},
112125
createdAt: { type: 'date' },
113126
createdBy: { type: 'keyword' },
114127
updatedAt: { type: 'date' },

src/services/ResourceBookingProcessorService.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ processCreate.schema = {
4646
createdBy: Joi.string().uuid().required(),
4747
updatedAt: Joi.date().allow(null),
4848
updatedBy: Joi.string().uuid().allow(null),
49-
status: Joi.jobStatus().required()
49+
status: Joi.resourceBookingStatus().required()
5050
}).required()
5151
}).required(),
5252
transactionId: Joi.string().required()
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/**
2+
* WorkPeriodPayment Processor Service
3+
*/
4+
5+
const Joi = require('@hapi/joi')
6+
const config = require('config')
7+
const _ = require('lodash')
8+
const logger = require('../common/logger')
9+
const helper = require('../common/helper')
10+
const constants = require('../common/constants')
11+
12+
const esClient = helper.getESClient()
13+
14+
/**
15+
* Process create entity message
16+
* @param {Object} message the kafka message
17+
* @param {String} transactionId
18+
*/
19+
async function processCreate (message, transactionId) {
20+
const data = message.payload
21+
const workPeriod = await esClient.getExtra({
22+
index: config.get('esConfig.ES_INDEX_WORK_PERIOD'),
23+
id: data.workPeriodId
24+
})
25+
const payments = _.isArray(workPeriod.body.payments) ? workPeriod.body.payments : []
26+
payments.push(data)
27+
28+
return esClient.updateExtra({
29+
index: config.get('esConfig.ES_INDEX_WORK_PERIOD'),
30+
id: data.workPeriodId,
31+
transactionId,
32+
body: {
33+
doc: _.assign(workPeriod.body, { payments })
34+
},
35+
refresh: constants.esRefreshOption
36+
})
37+
}
38+
39+
processCreate.schema = {
40+
message: Joi.object().keys({
41+
topic: Joi.string().required(),
42+
originator: Joi.string().required(),
43+
timestamp: Joi.date().required(),
44+
'mime-type': Joi.string().required(),
45+
payload: Joi.object().keys({
46+
id: Joi.string().uuid().required(),
47+
workPeriodId: Joi.string().uuid().required(),
48+
challengeId: Joi.string().uuid().required(),
49+
amount: Joi.number().greater(0).allow(null),
50+
status: Joi.workPeriodPaymentStatus().required(),
51+
createdAt: Joi.date().required(),
52+
createdBy: Joi.string().uuid().required(),
53+
updatedAt: Joi.date().allow(null),
54+
updatedBy: Joi.string().uuid().allow(null)
55+
}).required()
56+
}).required(),
57+
transactionId: Joi.string().required()
58+
}
59+
60+
/**
61+
* Process update entity message
62+
* @param {Object} message the kafka message
63+
* @param {String} transactionId
64+
*/
65+
async function processUpdate (message, transactionId) {
66+
const data = message.payload
67+
let workPeriod = await esClient.search({
68+
index: config.get('esConfig.ES_INDEX_WORK_PERIOD'),
69+
body: {
70+
query: {
71+
nested: {
72+
path: 'payments',
73+
query: {
74+
match: { 'payments.id': data.id }
75+
}
76+
}
77+
}
78+
}
79+
})
80+
if (!workPeriod.body.hits.total.value) {
81+
throw new Error(`id: ${data.id} "WorkPeriodPayments" not found`)
82+
}
83+
let payments
84+
// if WorkPeriodPayment's workPeriodId changed then it must be deleted from the old WorkPeriod
85+
// and added to the new WorkPeriod
86+
if (workPeriod.body.hits.hits[0]._source.id !== data.workPeriodId) {
87+
payments = _.filter(workPeriod.body.hits.hits[0]._source.payments, (payment) => payment.id !== data.id)
88+
await esClient.updateExtra({
89+
index: config.get('esConfig.ES_INDEX_WORK_PERIOD'),
90+
id: workPeriod.body.hits.hits[0]._source.id,
91+
transactionId,
92+
body: {
93+
doc: _.assign(workPeriod.body.hits.hits[0]._source, { payments })
94+
}
95+
})
96+
workPeriod = await esClient.getExtra({
97+
index: config.get('esConfig.ES_INDEX_WORK_PERIOD'),
98+
id: data.workPeriodId
99+
})
100+
payments = _.isArray(workPeriod.body.payments) ? workPeriod.body.payments : []
101+
payments.push(data)
102+
return esClient.updateExtra({
103+
index: config.get('esConfig.ES_INDEX_WORK_PERIOD'),
104+
id: data.workPeriodId,
105+
transactionId,
106+
body: {
107+
doc: _.assign(workPeriod.body, { payments })
108+
}
109+
})
110+
}
111+
112+
payments = _.map(workPeriod.body.hits.hits[0]._source.payments, (payment) => {
113+
if (payment.id === data.id) {
114+
return _.assign(payment, data)
115+
}
116+
return payment
117+
})
118+
119+
return esClient.updateExtra({
120+
index: config.get('esConfig.ES_INDEX_WORK_PERIOD'),
121+
id: data.workPeriodId,
122+
transactionId,
123+
body: {
124+
doc: _.assign(workPeriod.body.hits.hits[0]._source, { payments })
125+
},
126+
refresh: constants.esRefreshOption
127+
})
128+
}
129+
130+
processUpdate.schema = processCreate.schema
131+
132+
module.exports = {
133+
processCreate,
134+
processUpdate
135+
}
136+
137+
logger.buildService(module.exports, 'WorkPeriodPaymentProcessorService')
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"topic":"taas.resourcebooking.create","originator":"taas-api","timestamp":"2020-11-05T19:00:25.038Z","mime-type":"application/json","payload":{"projectId":21,"userId":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","jobId":"ffbc24f7-301e-48d3-bf01-c056916056a2","startDate":"2020-09-27T04:17:23.131Z","endDate":"2020-09-27T04:17:23.131Z","memberRate":13.23,"customerRate":13,"rateType":"hourly","id":"60d97713-8621-476e-b006-7cb9589c7777","createdAt":"2020-11-05T19:00:23.036Z","createdBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","status":"sourcing"}}
1+
{"topic":"taas.resourcebooking.create","originator":"taas-api","timestamp":"2020-11-05T19:00:25.038Z","mime-type":"application/json","payload":{"projectId":21,"userId":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","jobId":"ffbc24f7-301e-48d3-bf01-c056916056a2","startDate":"2020-09-27T04:17:23.131Z","endDate":"2020-09-27T04:17:23.131Z","memberRate":13.23,"customerRate":13,"rateType":"hourly","id":"60d97713-8621-476e-b006-7cb9589c7777","createdAt":"2020-11-05T19:00:23.036Z","createdBy":"a55fe1bc-1754-45fa-9adc-cf3d6d7c377a","status":"assigned"}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"topic":"taas.workperiodpayment.create","originator":"taas-api","timestamp":"2021-04-09T20:10:33.770Z","mime-type":"application/json","payload":{"challengeId":"00000000-0000-0000-0000-000000000000","workPeriodId":"140b7407-540d-40c3-ad23-905d932aa9c8","amount":600,"status":"completed","id":"09c80ee6-21be-45a4-9c3c-7ec4c75ece79","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedAt":"2021-04-09T20:10:33.755Z","createdAt":"2021-04-09T20:10:33.755Z","updatedBy":null}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"topic":"taas.workperiodpayment.update","originator":"taas-api","timestamp":"2021-04-09T20:12:26.994Z","mime-type":"application/json","payload":{"id":"09c80ee6-21be-45a4-9c3c-7ec4c75ece79","workPeriodId":"140b7407-540d-40c3-ad23-905d932aa9c8","challengeId":"00000000-0000-0000-0000-000000000000","amount":1600,"status":"completed","createdBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","updatedBy":"57646ff9-1cd3-4d3c-88ba-eb09a395366c","createdAt":"2021-04-09T20:10:33.755Z","updatedAt":"2021-04-09T20:12:26.966Z"}}

0 commit comments

Comments
 (0)