Skip to content

Commit 627118d

Browse files
committed
Merge dev into feature/role-jd-parser2 - resolve conflict
2 parents 216c256 + 6ba5f16 commit 627118d

27 files changed

+1107
-83
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ workflows:
6868
branches:
6969
only:
7070
- dev
71+
- change-validatations-in-job-jc
7172

7273
# Production builds are exectuted only on tagged commits to the
7374
# master branch.

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@
103103
tc-taas-es-processor | 2021-04-09T21:20:21.469Z DEBUG no-kafka-client Subscribed to taas.workperiodpayment.update:0 offset 0 leader kafka:9093
104104
tc-taas-es-processor | 2021-04-09T21:20:21.470Z DEBUG no-kafka-client Subscribed to taas.workperiodpayment.delete:0 offset 0 leader kafka:9093
105105
tc-taas-es-processor | 2021-04-09T21:20:21.471Z DEBUG no-kafka-client Subscribed to taas.workperiodpayment.create:0 offset 0 leader kafka:9093
106+
tc-taas-es-processor | 2021-04-09T21:20:21.472Z DEBUG no-kafka-client Subscribed to taas.action.retry:0 offset 0 leader kafka:9093
106107
tc-taas-es-processor | 2021-04-09T21:20:21.473Z DEBUG no-kafka-client Subscribed to taas.job.update:0 offset 0 leader kafka:9093
107108
tc-taas-es-processor | 2021-04-09T21:20:21.474Z DEBUG no-kafka-client Subscribed to taas.resourcebooking.update:0 offset 0 leader kafka:9093
108109
tc-taas-es-processor | [2021-04-09T21:20:21.475Z] app INFO : Initialized.......
109-
tc-taas-es-processor | [2021-04-09T21:20:21.479Z] app INFO : taas.job.create,taas.job.update,taas.job.delete,taas.jobcandidate.create,taas.jobcandidate.update,taas.jobcandidate.delete,taas.resourcebooking.create,taas.resourcebooking.update,taas.resourcebooking.delete,taas.workperiod.create,taas.workperiod.update,taas.workperiod.delete,taas.workperiodpayment.create,taas.workperiodpayment.update,taas.interview.requested,taas.interview.update,taas.interview.bulkUpdate,taas.role.requested,taas.role.update,taas.role.delete
110+
tc-taas-es-processor | [2021-04-09T21:20:21.479Z] app INFO : common.error.reporting,taas.job.create,taas.job.update,taas.job.delete,taas.jobcandidate.create,taas.jobcandidate.update,taas.jobcandidate.delete,taas.resourcebooking.create,taas.resourcebooking.update,taas.resourcebooking.delete,taas.workperiod.create,taas.workperiod.update,taas.workperiod.delete,taas.workperiodpayment.create,taas.workperiodpayment.update,taas.interview.requested,taas.interview.update,taas.interview.bulkUpdate,taas.role.requested,taas.role.update,taas.role.delete,taas.action.retry
110111
tc-taas-es-processor | [2021-04-09T21:20:21.480Z] app INFO : Kick Start.......
111112
tc-taas-es-processor | ********** Topcoder Health Check DropIn listening on port 3001
112113
tc-taas-es-processor | Topcoder Health Check DropIn started and ready to roll
@@ -176,6 +177,19 @@ To be able to change and test `taas-es-processor` locally you can follow the nex
176177
2. Run `taas-es-processor` separately from the source code. As `npm run services:up` already run all the dependencies for both `taas-apis` and for `taas-es-processor`. The only thing you need to do for running `taas-es-processor` locally is clone the [taas-es-processor](https://github.com/topcoder-platform/taas-es-processor) repository and inside `taas-es-processor` folder run:
177178
- `nvm use` - to use correct Node version
178179
- `npm run install`
180+
- Create `.env` file with the next environment variables. Values for **Auth0 config** should be shared with you on the forum.<br>
181+
182+
```bash
183+
# Auth0 config
184+
AUTH0_URL=
185+
AUTH0_AUDIENCE=
186+
AUTH0_CLIENT_ID=
187+
AUTH0_CLIENT_SECRET=
188+
```
189+
190+
- Values from this file would be automatically used by many `npm` commands.
191+
- ⚠️ Never commit this file or its copy to the repository!
192+
179193
- `npm run start`
180194

181195
## NPM Commands
@@ -206,6 +220,7 @@ To be able to change and test `taas-es-processor` locally you can follow the nex
206220
| `npm run cov` | Code Coverage Report. |
207221
| `npm run migrate` | Run any migration files which haven't run yet. |
208222
| `npm run migrate:undo` | Revert most recent migration. |
223+
| `npm run demo-payment-scheduler` | Create 1000 Work Periods Payment records in with status "scheduled" and various "amount" |
209224
210225
## Import and Export data
211226

app-constants.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,24 @@ const ChallengeStatus = {
8686

8787
const WorkPeriodPaymentStatus = {
8888
COMPLETED: 'completed',
89-
CANCELLED: 'cancelled',
90-
SCHEDULED: 'scheduled'
89+
SCHEDULED: 'scheduled',
90+
IN_PROGRESS: 'in-progress',
91+
FAILED: 'failed',
92+
CANCELLED: 'cancelled'
93+
}
94+
95+
const PaymentProcessingSwitch = {
96+
ON: 'ON',
97+
OFF: 'OFF'
98+
}
99+
100+
const PaymentSchedulerStatus = {
101+
START_PROCESS: 'start-process',
102+
CREATE_CHALLENGE: 'create-challenge',
103+
ASSIGN_MEMBER: 'assign-member',
104+
ACTIVATE_CHALLENGE: 'activate-challenge',
105+
GET_USER_ID: 'get-userId',
106+
CLOSE_CHALLENGE: 'close-challenge'
91107
}
92108

93109
module.exports = {
@@ -96,5 +112,7 @@ module.exports = {
96112
Scopes,
97113
Interviews,
98114
ChallengeStatus,
99-
WorkPeriodPaymentStatus
115+
WorkPeriodPaymentStatus,
116+
PaymentSchedulerStatus,
117+
PaymentProcessingSwitch
100118
}

app.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const schedule = require('node-schedule')
1313
const logger = require('./src/common/logger')
1414
const eventHandlers = require('./src/eventHandlers')
1515
const interviewService = require('./src/services/InterviewService')
16+
const { processScheduler } = require('./src/services/PaymentSchedulerService')
1617

1718
// setup express app
1819
const app = express()
@@ -97,6 +98,9 @@ const server = app.listen(app.get('port'), () => {
9798
eventHandlers.init()
9899
// schedule updateCompletedInterviews to run every hour
99100
schedule.scheduleJob('0 0 * * * *', interviewService.updateCompletedInterviews)
101+
102+
// schedule payment processing
103+
schedule.scheduleJob(config.PAYMENT_PROCESSING.CRON, processScheduler)
100104
})
101105

102106
if (process.env.NODE_ENV === 'test') {

config/default.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ module.exports = {
140140
TAAS_ROLE_UPDATE_TOPIC: process.env.TAAS_ROLE_UPDATE_TOPIC || 'taas.role.update',
141141
// the delete role entity Kafka message topic
142142
TAAS_ROLE_DELETE_TOPIC: process.env.TAAS_ROLE_DELETE_TOPIC || 'taas.role.delete',
143+
// special kafka topics
144+
TAAS_ACTION_RETRY_TOPIC: process.env.TAAS_ACTION_RETRY_TOPIC || 'taas.action.retry',
143145

144146
// the Kafka message topic for sending email
145147
EMAIL_TOPIC: process.env.EMAIL_TOPIC || 'external.action.email',
@@ -175,5 +177,40 @@ module.exports = {
175177
// member groups representing Wipro or TopCoder employee
176178
INTERNAL_MEMBER_GROUPS: process.env.INTERNAL_MEMBER_GROUPS || ['20000000', '20000001', '20000003', '20000010', '20000015'],
177179
// Topcoder skills cache time in minutes
178-
TOPCODER_SKILLS_CACHE_TIME: process.env.TOPCODER_SKILLS_CACHE_TIME || 60
180+
TOPCODER_SKILLS_CACHE_TIME: process.env.TOPCODER_SKILLS_CACHE_TIME || 60,
181+
// payment scheduler config
182+
PAYMENT_PROCESSING: {
183+
// switch off actual API calls in Payment Scheduler
184+
SWITCH: process.env.PAYMENT_PROCESSING_SWITCH || 'OFF',
185+
// the payment scheduler cron config
186+
CRON: process.env.PAYMENT_PROCESSING_CRON || '0 */5 * * * *',
187+
// the number of records processed by one time
188+
BATCH_SIZE: parseInt(process.env.PAYMENT_PROCESSING_BATCH_SIZE || 50),
189+
// in-progress expired to determine whether a record has been processed abnormally, moment duration format
190+
IN_PROGRESS_EXPIRED: process.env.IN_PROGRESS_EXPIRED || 'PT1H',
191+
// the number of max retry config
192+
MAX_RETRY_COUNT: parseInt(process.env.PAYMENT_PROCESSING_MAX_RETRY_COUNT || 10),
193+
// the time of retry base delay, unit: ms
194+
RETRY_BASE_DELAY: parseInt(process.env.PAYMENT_PROCESSING_RETRY_BASE_DELAY || 100),
195+
// the time of retry max delay, unit: ms
196+
RETRY_MAX_DELAY: parseInt(process.env.PAYMENT_PROCESSING_RETRY_MAX_DELAY || 10000),
197+
// the max time of one request, unit: ms
198+
PER_REQUEST_MAX_TIME: parseInt(process.env.PAYMENT_PROCESSING_PER_REQUEST_MAX_TIME || 30000),
199+
// the max time of one payment record, unit: ms
200+
PER_PAYMENT_MAX_TIME: parseInt(process.env.PAYMENT_PROCESSING_PER_PAYMENT_MAX_TIME || 60000),
201+
// the max records of payment of a minute
202+
PER_MINUTE_PAYMENT_MAX_COUNT: parseInt(process.env.PAYMENT_PROCESSING_PER_MINUTE_PAYMENT_MAX_COUNT || 12),
203+
// the max requests of challenge of a minute
204+
PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT: parseInt(process.env.PAYMENT_PROCESSING_PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT || 60),
205+
// the max requests of resource of a minute
206+
PER_MINUTE_RESOURCE_REQUEST_MAX_COUNT: parseInt(process.env.PAYMENT_PROCESSING_PER_MINUTE_CHALLENGE_REQUEST_MAX_COUNT || 20),
207+
// the default step fix delay, unit: ms
208+
FIX_DELAY_STEP: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500),
209+
// the fix delay after step of create challenge, unit: ms
210+
FIX_DELAY_STEP_CREATE_CHALLENGE: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_CREATE_CHALLENGE || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500),
211+
// the fix delay after step of assign member, unit: ms
212+
FIX_DELAY_STEP_ASSIGN_MEMBER: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_ASSIGN_MEMBER || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500),
213+
// the fix delay after step of activate challenge, unit: ms
214+
FIX_DELAY_STEP_ACTIVATE_CHALLENGE: parseInt(process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP_ACTIVATE_CHALLENGE || process.env.PAYMENT_PROCESSING_FIX_DELAY_STEP || 500)
215+
}
179216
}

docs/swagger.yaml

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ paths:
174174
required: false
175175
schema:
176176
type: string
177-
enum: ["hourly", "daily", "weekly", "monthly"]
177+
enum: ["hourly", "daily", "weekly", "monthly","annual"]
178178
description: The rate type.
179179
- in: query
180180
name: status
@@ -1505,9 +1505,14 @@ paths:
15051505
name: workPeriods.paymentStatus
15061506
required: false
15071507
schema:
1508-
type: string
1509-
enum: ["pending", "partially-completed", "completed", "cancelled"]
1510-
description: The payment status.
1508+
oneOf:
1509+
- type: array
1510+
items:
1511+
type: string
1512+
enum: ["pending", "partially-completed", "completed", "cancelled"]
1513+
- type: string
1514+
enum: ["pending", "partially-completed", "completed", "cancelled"]
1515+
description: comma separated payment status.
15111516
- in: query
15121517
name: workPeriods.startDate
15131518
required: false
@@ -1956,9 +1961,14 @@ paths:
19561961
name: paymentStatus
19571962
required: false
19581963
schema:
1959-
type: string
1960-
enum: ["pending", "partially-completed", "completed", "cancelled"]
1961-
description: The payment status.
1964+
oneOf:
1965+
- type: array
1966+
items:
1967+
type: string
1968+
enum: ["pending", "partially-completed", "completed", "cancelled"]
1969+
- type: string
1970+
enum: ["pending", "partially-completed", "completed", "cancelled"]
1971+
description: comma separated payment status.
19621972
- in: query
19631973
name: startDate
19641974
required: false
@@ -2403,7 +2413,7 @@ paths:
24032413
required: false
24042414
schema:
24052415
type: string
2406-
enum: ["completed", "scheduled", "cancelled"]
2416+
enum: ["completed", "scheduled", "in-progress", "failed", "cancelled"]
24072417
description: The payment status.
24082418
responses:
24092419
"200":
@@ -4827,8 +4837,22 @@ components:
48274837
description: "The amount to be paid."
48284838
status:
48294839
type: string
4830-
enum: ["completed", "scheduled", "cancelled"]
4840+
enum: ["completed", "scheduled", "in-progress", "failed", "cancelled"]
48314841
description: "The payment status."
4842+
statusDetails:
4843+
type: object
4844+
properties:
4845+
errorMessage:
4846+
type: string
4847+
errorCode:
4848+
type: integer
4849+
retry:
4850+
type: integer
4851+
step:
4852+
type: string
4853+
challengeId:
4854+
type: string
4855+
format: uuid
48324856
billingAccountId:
48334857
type: integer
48344858
example: 80000071
@@ -4885,7 +4909,7 @@ components:
48854909
description: "The amount to be paid."
48864910
status:
48874911
type: string
4888-
enum: ["completed", "scheduled", "cancelled"]
4912+
enum: ["completed", "scheduled", "in-progress", "failed", "cancelled"]
48894913
description: "The payment status."
48904914
WorkPeriodPaymentCreateRequestBody:
48914915
required:
@@ -4976,7 +5000,7 @@ components:
49765000
description: "The amount to be paid."
49775001
status:
49785002
type: string
4979-
enum: ["completed", "scheduled", "cancelled"]
5003+
enum: ["completed", "scheduled", "in-progress", "failed", "cancelled"]
49805004
description: "The payment status."
49815005
CheckRun:
49825006
type: object

local/kafka-client/topics.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ taas.interview.requested
2020
taas.interview.update
2121
taas.interview.bulkUpdate
2222
external.action.email
23+
taas.action.retry
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
'use strict';
2+
3+
const config = require('config')
4+
const _ = require('lodash')
5+
const { PaymentSchedulerStatus } = require('../app-constants')
6+
7+
/**
8+
* Create `payment_schedulers` table & relations.
9+
*/
10+
module.exports = {
11+
up: async (queryInterface, Sequelize) => {
12+
const transaction = await queryInterface.sequelize.transaction()
13+
try {
14+
await queryInterface.createTable('payment_schedulers', {
15+
id: {
16+
type: Sequelize.UUID,
17+
primaryKey: true,
18+
allowNull: false,
19+
defaultValue: Sequelize.UUIDV4
20+
},
21+
challengeId: {
22+
field: 'challenge_id',
23+
type: Sequelize.UUID,
24+
allowNull: false
25+
},
26+
workPeriodPaymentId: {
27+
field: 'work_period_payment_id',
28+
type: Sequelize.UUID,
29+
allowNull: false,
30+
references: {
31+
model: {
32+
tableName: 'work_period_payments',
33+
schema: config.DB_SCHEMA_NAME
34+
},
35+
key: 'id'
36+
}
37+
},
38+
step: {
39+
type: Sequelize.ENUM(_.values(PaymentSchedulerStatus)),
40+
allowNull: false
41+
},
42+
status: {
43+
type: Sequelize.ENUM(
44+
'in-progress',
45+
'completed',
46+
'failed'
47+
),
48+
allowNull: false
49+
},
50+
userId: {
51+
field: 'user_id',
52+
type: Sequelize.BIGINT
53+
},
54+
userHandle: {
55+
field: 'user_handle',
56+
type: Sequelize.STRING,
57+
allowNull: false
58+
},
59+
createdAt: {
60+
field: 'created_at',
61+
type: Sequelize.DATE
62+
},
63+
updatedAt: {
64+
field: 'updated_at',
65+
type: Sequelize.DATE
66+
},
67+
deletedAt: {
68+
field: 'deleted_at',
69+
type: Sequelize.DATE
70+
}
71+
}, { schema: config.DB_SCHEMA_NAME, transaction })
72+
await queryInterface.addColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'status_details',
73+
{ type: Sequelize.JSONB },
74+
{ transaction })
75+
await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'challenge_id',
76+
{ type: Sequelize.UUID },
77+
{ transaction })
78+
await queryInterface.sequelize.query(`ALTER TYPE ${config.DB_SCHEMA_NAME}.enum_work_period_payments_status ADD VALUE 'in-progress'`)
79+
await queryInterface.sequelize.query(`ALTER TYPE ${config.DB_SCHEMA_NAME}.enum_work_period_payments_status ADD VALUE 'failed'`)
80+
await transaction.commit()
81+
} catch (err) {
82+
await transaction.rollback()
83+
throw err
84+
}
85+
},
86+
87+
down: async (queryInterface, Sequelize) => {
88+
const table = { schema: config.DB_SCHEMA_NAME, tableName: 'payment_schedulers' }
89+
const statusTypeName = `${table.schema}.enum_${table.tableName}_status`
90+
const stepTypeName = `${table.schema}.enum_${table.tableName}_step`
91+
const transaction = await queryInterface.sequelize.transaction()
92+
try {
93+
await queryInterface.dropTable(table, { transaction })
94+
// drop enum type for status and step column
95+
await queryInterface.sequelize.query(`DROP TYPE ${statusTypeName}`, { transaction })
96+
await queryInterface.sequelize.query(`DROP TYPE ${stepTypeName}`, { transaction })
97+
98+
await queryInterface.changeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'challenge_id',
99+
{ type: Sequelize.UUID, allowNull: false },
100+
{ transaction })
101+
await queryInterface.removeColumn({ tableName: 'work_period_payments', schema: config.DB_SCHEMA_NAME }, 'status_details',
102+
{ transaction })
103+
await queryInterface.sequelize.query(`DELETE FROM pg_enum WHERE enumlabel in ('in-progress', 'failed') AND enumtypid = (SELECT oid FROM pg_type WHERE typname = 'enum_work_period_payments_status')`,
104+
{ transaction })
105+
await transaction.commit()
106+
} catch (err) {
107+
await transaction.rollback()
108+
throw err
109+
}
110+
}
111+
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"local:init": "npm run local:reset && npm run data:import -- --force",
2828
"local:reset": "npm run delete-index -- --force || true && npm run create-index -- --force && npm run init-db force",
2929
"cov": "nyc --reporter=html --reporter=text npm run test",
30+
"demo-payment-scheduler": "node scripts/demo-payment-scheduler/index.js && npm run index:all -- --force",
3031
"demo-payment": "node scripts/demo-payment"
3132
},
3233
"keywords": [],

0 commit comments

Comments
 (0)