Skip to content

Commit eb4afdb

Browse files
committed
Add skillsMatch to sendRoleSearchRequest response.
Change 'Niche' role to 'Custom' role. Fix getRoleBySkills to match lower-case skills in list. Allow anonymous user to get taas-roles/ and post sendRoleSearchRequest.
1 parent e66100c commit eb4afdb

8 files changed

+51
-29
lines changed

data/demo-data.json

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7258,10 +7258,30 @@
72587258
}
72597259
],
72607260
"Role": [
7261+
{
7262+
"id": "f5e01b7c-466f-45c8-989c-16ff831d7e59",
7263+
"name": "Custom",
7264+
"description": null,
7265+
"listOfSkills": null,
7266+
"rates": [{
7267+
"global": 1200,
7268+
"offShore": 1200,
7269+
"inCountry": 1200
7270+
}],
7271+
"numberOfMembers": null,
7272+
"numberOfMembersAvailable": null,
7273+
"imageUrl": null,
7274+
"timeToCandidate": null,
7275+
"timeToInterview": null,
7276+
"createdBy": "57646ff9-1cd3-4d3c-88ba-eb09a395366c",
7277+
"updatedBy": null,
7278+
"createdAt": "2021-05-27T21:43:08.201Z",
7279+
"updatedAt": "2021-05-27T21:43:08.201Z"
7280+
},
72617281
{
72627282
"id": "c145247d-5757-463d-9317-ff9e7026d403",
72637283
"name": "Angular Developer",
7264-
"description": "Angular is an open-source, client-side framework based on TypeScript and designed for building web applications.",
7284+
"description": "* Writes tested and documented JavaScript, HTML and CSS\n* Makes design and technical decisions for AngularJS projects\n* Develops application code and unit test in the AngularJS, Rest Web Services and Java technologies",
72657285
"listOfSkills": [
72667286
"database",
72677287
"winforms",
@@ -7293,7 +7313,7 @@
72937313
{
72947314
"id": "d7ff0289-d3ea-44d8-b39a-53bba5b5b309",
72957315
"name": "Dev Ops Engineer",
7296-
"description": "A DevOps engineer introduces processes, tools, and methodologies to balance needs throughout the software development life cycle, from coding and deployment, to maintenance and updates.",
7316+
"description": "* Introduces processes, tools, and methodologies\n* Balances needs throughout the software development life cycle\n* Configures server images, optimizes task performance in correspondence with engineers",
72977317
"listOfSkills": [
72987318
"dropwizard",
72997319
"nginx",
@@ -7337,7 +7357,7 @@
73377357
{
73387358
"id": "e7b7e818-40d4-4102-b486-09bdd21400b8",
73397359
"name": "Salesforce Developer",
7340-
"description": "A Salesforce developer is a programmer who builds Salesforce applications across various PaaS (Platform as a Service) platforms.",
7360+
"description": "* Meets with project managers to determine CRM needs\n* Develops customized solutions within the Salesforce platform\n* Designs, codes, and implements Salesforce applications\n* Creates timelines and development goals\n* Tests the stability and functionality of the application\n* Troubleshoots and fixes bugs\n* Writes documents and provides technical training for Salesforce Staff\n* Maintains the security and integrity of the application software",
73417361
"listOfSkills": [
73427362
"docker",
73437363
".net",

docs/Topcoder-bookings-api.postman_collection.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19627,7 +19627,7 @@
1962719627
"response": []
1962819628
},
1962919629
{
19630-
"name": "create role Niche",
19630+
"name": "create role Custom",
1963119631
"event": [
1963219632
{
1963319633
"listen": "test",
@@ -19652,7 +19652,7 @@
1965219652
],
1965319653
"body": {
1965419654
"mode": "raw",
19655-
"raw": "{\n \"name\": \"Niche\",\n \"rates\": [\n {\n \"global\": 10,\n \"inCountry\": 10,\n \"offShore\": 10\n }\n ]\n}",
19655+
"raw": "{\n \"name\": \"Custom\",\n \"rates\": [\n {\n \"global\": 1200,\n \"inCountry\": 1200,\n \"offShore\": 1200\n }\n ]\n}",
1965619656
"options": {
1965719657
"raw": {
1965819658
"language": "json"
@@ -20424,7 +20424,7 @@
2042420424
"pm.test('Status code is 200', function () {\r",
2042520425
" pm.response.to.have.status(200);\r",
2042620426
" const response = pm.response.json()\r",
20427-
" pm.expect(response.name).to.eq(\"Niche\")\r",
20427+
" pm.expect(response.name).to.eq(\"Custom\")\r",
2042820428
"});"
2042920429
],
2043020430
"type": "text/javascript"

docs/swagger.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5505,6 +5505,11 @@ components:
55055505
isExternalMember:
55065506
type: boolean
55075507
description: "Is the user external member"
5508+
skillsMatch:
5509+
type: number
5510+
format: float
5511+
description: "Rate at which searched skills match the given role"
5512+
example: 0.75
55085513
SubmitTeamRequestBody:
55095514
properties:
55105515
teamName:

src/controllers/RoleController.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const service = require('../services/RoleService')
1010
* @param res the response
1111
*/
1212
async function getRole (req, res) {
13-
res.send(await service.getRole(req.authUser, req.params.id, req.query.fromDb))
13+
res.send(await service.getRole(req.params.id, req.query.fromDb))
1414
}
1515

1616
/**
@@ -47,7 +47,7 @@ async function deleteRole (req, res) {
4747
* @param res the response
4848
*/
4949
async function searchRoles (req, res) {
50-
res.send(await service.searchRoles(req.authUser, req.query))
50+
res.send(await service.searchRoles(req.query))
5151
}
5252

5353
module.exports = {

src/routes/RoleRoutes.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,12 @@ module.exports = {
1414
get: {
1515
controller: 'RoleController',
1616
method: 'searchRoles',
17-
auth: 'jwt',
18-
scopes: [constants.Scopes.READ_ROLE, constants.Scopes.ALL_ROLE]
1917
}
2018
},
2119
'/taas-roles/:id': {
2220
get: {
2321
controller: 'RoleController',
2422
method: 'getRole',
25-
auth: 'jwt',
26-
scopes: [constants.Scopes.READ_ROLE, constants.Scopes.ALL_ROLE]
2723
},
2824
patch: {
2925
controller: 'RoleController',

src/routes/TeamRoutes.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ module.exports = {
2424
get: {
2525
controller: 'TeamController',
2626
method: 'searchSkills',
27-
auth: 'jwt',
28-
scopes: [constants.Scopes.READ_TAAS_TEAM]
2927
}
3028
},
3129
'/taas-teams/me': {
@@ -94,8 +92,6 @@ module.exports = {
9492
post: {
9593
controller: 'TeamController',
9694
method: 'roleSearchRequest',
97-
auth: 'jwt',
98-
scopes: [constants.Scopes.CREATE_ROLE_SEARCH_REQUEST]
9995
}
10096
},
10197
'/taas-teams/submitTeamRequest': {

src/services/RoleService.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ async function _checkIfSameNamedRoleExists (roleName) {
7474
* @param {Boolean} fromDb flag if query db for data or not
7575
* @returns {Object} the role
7676
*/
77-
async function getRole (currentUser, id, fromDb = false) {
77+
async function getRole (id, fromDb = false) {
7878
if (!fromDb) {
7979
try {
8080
const role = await esClient.get({
@@ -95,7 +95,6 @@ async function getRole (currentUser, id, fromDb = false) {
9595
}
9696

9797
getRole.schema = Joi.object().keys({
98-
currentUser: Joi.object().required(),
9998
id: Joi.string().uuid().required(),
10099
fromDb: Joi.boolean()
101100
}).required()
@@ -230,7 +229,7 @@ deleteRole.schema = Joi.object().keys({
230229
* @param {Object} criteria the search criteria
231230
* @returns {Object} the search result
232231
*/
233-
async function searchRoles (currentUser, criteria) {
232+
async function searchRoles (criteria) {
234233
// clean skill names and convert into an array
235234
criteria.skillsList = _.filter(_.map(_.split(criteria.skillsList, ','), skill => _.trim(skill)), skill => !_.isEmpty(skill))
236235
try {
@@ -291,7 +290,6 @@ async function searchRoles (currentUser, criteria) {
291290
}
292291

293292
searchRoles.schema = Joi.object().keys({
294-
currentUser: Joi.object().required(),
295293
criteria: Joi.object().keys({
296294
skillsList: Joi.string(),
297295
keyword: Joi.string()

src/services/TeamService.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const HttpStatus = require('http-status-codes')
1616
const { Op } = require('sequelize')
1717
const models = require('../models')
1818
const stopWords = require('../../data/stopWords.json')
19+
const { getAuditM2Muser } = require('../common/helper')
1920
const Role = models.Role
2021
const RoleSearchRequest = models.RoleSearchRequest
2122
const topcoderSkills = {}
@@ -750,11 +751,16 @@ getMe.schema = Joi.object()
750751
* @returns {Object} the created project
751752
*/
752753
async function roleSearchRequest (currentUser, data) {
754+
// if currentUser is undefined then set to machine
755+
if (_.isUndefined(currentUser)) {
756+
currentUser = getAuditM2Muser()
757+
}
753758
let role
754759
// if roleId is provided then find role with given id.
755760
if (!_.isUndefined(data.roleId)) {
756761
role = await Role.findById(data.roleId)
757762
role = role.toJSON()
763+
role.skillsMatch = 1;
758764
// if skills is provided then use skills to find role
759765
} else if (!_.isUndefined(data.skills)) {
760766
// validate given skillIds and convert them into skill names
@@ -779,7 +785,7 @@ async function roleSearchRequest (currentUser, data) {
779785

780786
roleSearchRequest.schema = Joi.object()
781787
.keys({
782-
currentUser: Joi.object().required(),
788+
currentUser: Joi.object(),
783789
data: Joi.object().keys({
784790
roleId: Joi.string().uuid(),
785791
jobDescription: Joi.string().max(255),
@@ -793,28 +799,29 @@ roleSearchRequest.schema = Joi.object()
793799
* @returns {Role} the best matching Role
794800
*/
795801
async function getRoleBySkills (skills) {
802+
const lowerCaseSkills = skills.map(skill => skill.toLowerCase())
796803
// find all roles which includes any of the given skills
797804
const queryCriteria = {
798-
where: { listOfSkills: { [Op.overlap]: skills } },
805+
where: { listOfSkills: { [Op.overlap]: lowerCaseSkills } },
799806
raw: true
800807
}
801808
const roles = await Role.findAll(queryCriteria)
802809
if (roles.length > 0) {
803810
let result = _.each(roles, role => {
804811
// calculate each found roles matching rate
805-
role.matchingRate = _.intersection(role.listOfSkills, skills).length / skills.length
812+
role.skillsMatch = _.intersection(role.listOfSkills, lowerCaseSkills).length / skills.length
806813
// each role can have multiple rates, get the maximum of global rates
807814
role.maxGlobal = _.maxBy(role.rates, 'global').global
808815
})
809-
// sort roles by matchingRate, global rate and name
810-
result = _.orderBy(result, ['matchingRate', 'maxGlobal', 'name'], ['desc', 'desc', 'asc'])
811-
if (result[0].matchingRate >= config.ROLE_MATCHING_RATE) {
816+
// sort roles by skillsMatch, global rate and name
817+
result = _.orderBy(result, ['skillsMatch', 'maxGlobal', 'name'], ['desc', 'desc', 'asc'])
818+
if (result[0].skillsMatch >= config.ROLE_MATCHING_RATE) {
812819
// return the 1st role
813-
return _.omit(result[0], ['matchingRate', 'maxGlobal'])
820+
return _.omit(result[0], ['maxGlobal'])
814821
}
815822
}
816-
// if no matching role found then return Niche role or empty object
817-
return await Role.findOne({ where: { name: { [Op.iLike]: 'Niche' } } }) || {}
823+
// if no matching role found then return Custom role or empty object
824+
return await Role.findOne({ where: { name: { [Op.iLike]: 'Custom' } } }) || {}
818825
}
819826

820827
getRoleBySkills.schema = Joi.object()

0 commit comments

Comments
 (0)