Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit dbf1374

Browse files
Merge pull request #93 from topcoder-platform/feature/topgear-reviews
support review feedback
2 parents f8d8a45 + e0ff01f commit dbf1374

File tree

3 files changed

+162
-1
lines changed

3 files changed

+162
-1
lines changed

src/constants.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,23 @@ const challengeStatuses = {
4848
CancelledPaymentFailed: 'Cancelled - Payment Failed'
4949
}
5050

51+
const scorecardQuestionMapping = {
52+
30002212: [
53+
{
54+
questionId: 30007531,
55+
description: 'Does the submission sufficiently satisfy the requirements as described in the provided specification?'
56+
},
57+
{
58+
questionId: 30007533,
59+
description: 'How would you rate the work ethic of this submitter?'
60+
},
61+
{
62+
questionId: 30007532,
63+
description: 'How would you rate the quality of this submitters work?'
64+
}
65+
]
66+
}
67+
5168
const PhaseStatusTypes = {
5269
Scheduled: 1,
5370
Open: 2,
@@ -150,5 +167,6 @@ module.exports = {
150167
challengeStatuses,
151168
PhaseStatusTypes,
152169
prizeTypesIds,
153-
supportedMetadata
170+
supportedMetadata,
171+
scorecardQuestionMapping
154172
}

src/services/ProcessorService.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const paymentService = require('./paymentService')
1919
const { createOrSetNumberOfReviewers } = require('./selfServiceReviewerService')
2020
const { disableTimelineNotifications } = require('./selfServiceNotificationService')
2121
const legacyChallengeService = require('./legacyChallengeService')
22+
const legacyChallengeReviewService = require('./legacyChallengeReviewService')
2223

2324
/**
2425
* Drop and recreate phases in ifx
@@ -713,6 +714,24 @@ async function processMessage (message) {
713714
needSyncV4ES = true
714715
}
715716
if (message.payload.status === constants.challengeStatuses.Completed && challenge.currentStatus !== constants.challengeStatuses.Completed) {
717+
// Try to read reviews and insert them into informix DB
718+
if (message.payload.metadata && message.payload.legacy.reviewScorecardId) {
719+
let orReviewFeedback = _.find(message.payload.metadata, meta => meta.name === 'or_review_feedback')
720+
let orReviewScore = _.find(message.payload.metadata, meta => meta.name === 'or_review_score')
721+
if (!_.isUndefined(orReviewFeedback) && !_.isUndefined(orReviewScore)) {
722+
orReviewFeedback = JSON.parse(orReviewFeedback)
723+
const reviewResponses = []
724+
_.each(orReviewFeedback, (value, key) => {
725+
const questionId = _.get(_.find(constants.scorecardQuestionMapping[message.payload.legacy.reviewScorecardId], item => _.toString(item.questionId) === _.toString(key) || _.toLower(item.description) === _.toLower(key)), 'questionId')
726+
reviewResponses.push({
727+
questionId,
728+
answer: value
729+
})
730+
})
731+
orReviewScore = _.toNumber(orReviewFeedback)
732+
await legacyChallengeReviewService.insertReview(legacyId, message.payload.legacy.reviewScorecardId, orReviewScore, reviewResponses, createdByUserId)
733+
}
734+
}
716735
if (message.payload.task.isTask) {
717736
logger.info('Challenge is a TASK')
718737
if (!message.payload.winners || message.payload.winners.length === 0) {
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* Legacy Challenge Service
3+
* Interacts with InformixDB
4+
* Note: this is built to work for topgear challenges and iterative review phases
5+
*/
6+
const _ = require('lodash')
7+
const logger = require('../common/logger')
8+
const util = require('util')
9+
const helper = require('../common/helper')
10+
const IDGenerator = require('../common/idGenerator')
11+
const reviewIdGen = new IDGenerator('review_id_seq')
12+
const reviewItemIdGen = new IDGenerator('review_item_id_seq')
13+
14+
const ITERATIVE_REVIEWER_RESOURCE_ROLE_ID = 21
15+
const QUERY_GET_ITERATIVE_REVIEW_RESOURCE_FOR_CHALLENGE = `SELECT limit 1 resource_id as resourceid FROM resource WHERE project_id = %d AND resource_role_id = ${ITERATIVE_REVIEWER_RESOURCE_ROLE_ID}`
16+
17+
const QUERY_CREATE_REVIEW = 'INSERT INTO review (review_id, resource_id, submission_id, project_phase_id, scorecard_id, committed, score, initial_score, create_user, create_date, modify_user, modify_date) values (?,?,?,?,?,?,?,?,?,CURRENT,?,CURRENT)'
18+
19+
const QUERY_CREATE_REVIEW_ITEM = 'INSERT INTO review_item (review_item_id, review_id, scorecard_question_id, upload_id, answer, sort, create_user, create_date, modify_user, modify_date) values (?,?,?,?,?,?,?,CURRENT,?,CURRENT)'
20+
21+
const QUERY_GET_SUBMISSION = 'SELECT FIRST 1 * FROM submission s INNER JOIN upload u on s.upload_id = u.upload_id WHERE u.project_id = %d AND upload_status_id = 1 AND submission_status_id = 1 ORDER BY u.CREATE_DATE ASC'
22+
23+
const QUERY_GET_PROJECT_PHASE = 'select pc.parameter scorecard_id, pp.project_phase_id project_phase_id from project_phase pp inner join phase_criteria pc on pc.project_phase_id = pp.project_phase_id where pp.project_id = %d and pp.phase_type_id = 18 and phase_criteria_type_id = 1'
24+
25+
/**
26+
* Prepare Informix statement
27+
* @param {Object} connection the Informix connection
28+
* @param {String} sql the sql
29+
* @return {Object} Informix statement
30+
*/
31+
async function prepare (connection, sql) {
32+
// logger.debug(`Preparing SQL ${sql}`)
33+
const stmt = await connection.prepareAsync(sql)
34+
return Promise.promisifyAll(stmt)
35+
}
36+
37+
/**
38+
* Insert review in IFX
39+
* @param {Number} challengeLegacyId the legacy challenge ID
40+
* @param {Number} createdBy the scorecard ID
41+
* @param {Number} score the review score
42+
* @param {Array} responses the review responses
43+
* @param {Number} createdBy the creator user ID
44+
*/
45+
async function insertReview (challengeLegacyId, scorecardId, score, responses, createdBy) {
46+
const connection = await helper.getInformixConnection()
47+
let result = null
48+
let reviewId
49+
try {
50+
const resourceId = await getIterativeReviewerResourceId(connection, challengeLegacyId)
51+
if (!resourceId) throw new Error('Cannot find Iterative Reviewer')
52+
const submissionId = await getSubmissionId(connection, challengeLegacyId)
53+
if (!submissionId) throw new Error('Cannot find Submission')
54+
const projectPhaseId = await getProjectPhaseId(connection, challengeLegacyId)
55+
if (!projectPhaseId) throw new Error('Cannot find Project Phase Id')
56+
reviewId = await reviewIdGen.getNextId()
57+
await connection.beginTransactionAsync()
58+
const query = await prepare(connection, QUERY_CREATE_REVIEW)
59+
result = await query.executeAsync([reviewId, resourceId, submissionId, projectPhaseId, scorecardId, 1, score, score, createdBy, createdBy])
60+
for (let i = 0; i < responses.length; i += 1) {
61+
await insertReviewItem(connection, reviewId, responses[i], i, createdBy)
62+
}
63+
await connection.commitTransactionAsync()
64+
} catch (e) {
65+
logger.error(`Error in 'insertReview' ${e}, rolling back transaction`)
66+
await connection.rollbackTransactionAsync()
67+
throw e
68+
} finally {
69+
logger.info(`Review ${challengeLegacyId} has been created`)
70+
await connection.closeAsync()
71+
}
72+
return result
73+
}
74+
75+
/**
76+
* Insert review item in IFX
77+
* @param {Object} connection
78+
* @param {Number} reviewId the review ID
79+
* @param {Object} response the response
80+
* @param {Number} sort the sort
81+
* @param {Number} createdBy the creator user ID
82+
*/
83+
async function insertReviewItem (connection, reviewId, response, sort, createdBy) {
84+
let result = null
85+
const reviewItemId = await reviewItemIdGen.getNextId()
86+
await connection.beginTransactionAsync()
87+
const query = await prepare(connection, QUERY_CREATE_REVIEW_ITEM)
88+
result = await query.executeAsync([reviewItemId, reviewId, response.questionId, null, response.answer, sort, createdBy, createdBy])
89+
return result
90+
}
91+
92+
/**
93+
* Gets the iterative reviewer resource id
94+
* @param {Object} connection
95+
* @param {Number} challengeLegacyId
96+
*/
97+
async function getIterativeReviewerResourceId (connection, challengeLegacyId) {
98+
const result = await connection.queryAsync(util.format(QUERY_GET_ITERATIVE_REVIEW_RESOURCE_FOR_CHALLENGE, challengeLegacyId))
99+
return _.get(result, '[0].resourceid', null)
100+
}
101+
102+
/**
103+
* Gets the submission id
104+
* @param {Object} connection
105+
* @param {Number} challengeLegacyId
106+
*/
107+
async function getSubmissionId (connection, challengeLegacyId) {
108+
const result = await connection.queryAsync(util.format(QUERY_GET_SUBMISSION, challengeLegacyId))
109+
return _.get(result, '[0].submission_id', null)
110+
}
111+
112+
/**
113+
* Gets the submission id
114+
* @param {Object} connection
115+
* @param {Number} challengeLegacyId
116+
*/
117+
async function getProjectPhaseId (connection, challengeLegacyId) {
118+
const result = await connection.queryAsync(util.format(QUERY_GET_PROJECT_PHASE, challengeLegacyId))
119+
return _.get(result, '[0].project_phase_id', null)
120+
}
121+
122+
module.exports = {
123+
insertReview
124+
}

0 commit comments

Comments
 (0)