diff --git a/config/default.js b/config/default.js index c7acb93..d0767c1 100644 --- a/config/default.js +++ b/config/default.js @@ -47,5 +47,6 @@ module.exports = { PAYMENT_METHOD_ID: process.env.PAYMENT_METHOD_ID || 1, CHARITY_IND: process.env.CHARITY_IND || 0, - INSTALLMENT_NUMBER: process.env.INSTALLMENT_NUMBER || 1 + INSTALLMENT_NUMBER: process.env.INSTALLMENT_NUMBER || 1, + COPILOT_ROLE_ID: process.env.COPILOT_ROLE_ID || 'cfe12b3f-2a24-4639-9d8b-ec86726f76bd' } diff --git a/src/app.js b/src/app.js index 6af82f4..977a295 100644 --- a/src/app.js +++ b/src/app.js @@ -44,7 +44,7 @@ const dataHandler = (messageSet, topic, partition) => Promise.each(messageSet, a return } - if (_.upperCase(_.get(messageJSON.payload, 'type')) !== 'TASK' || _.upperCase(_.get(messageJSON.payload, 'status')) !== 'COMPLETED') { + if (_.toUpper(_.get(messageJSON.payload, 'type')) !== 'TASK' || _.toUpper(_.get(messageJSON.payload, 'status')) !== 'COMPLETED') { logger.info(`The message type ${_.get(messageJSON.payload, 'type')}, status ${_.get(messageJSON.payload, 'status')} doesn't match {type: 'Task', status: 'Completed'}.`) // commit the message and ignore it diff --git a/src/common/helper.js b/src/common/helper.js index 993b182..953a870 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -130,6 +130,22 @@ async function getUserId (handle) { return res.body.userId } +/** + * Function to get copilot id + * @param {String} challengeId the challengeId + * @returns {String} the userId + */ +async function getCopilotId (challengeId) { + const token = await getM2MToken() + const url = `${config.TC_API}/resources?challengeId=${challengeId}&roleId=${config.COPILOT_ROLE_ID}` + const res = await request + .get(url) + .set('Authorization', `Bearer ${token}`) + .set('Content-Type', 'application/json') + .set('Accept', 'application/json') + return _.get(_.head(res.body), 'memberId') +} + module.exports = { getInformixConnection, getKafkaOptions, @@ -137,5 +153,6 @@ module.exports = { getRequest, putRequest, postRequest, - getUserId + getUserId, + getCopilotId } diff --git a/src/services/paymentService.js b/src/services/paymentService.js index db0b1bd..6b96569 100644 --- a/src/services/paymentService.js +++ b/src/services/paymentService.js @@ -39,6 +39,7 @@ async function createPayment (payment) { const paymentDetailId = await paymentDetailIdGen.getNextId() const paymentId = await paymentIdGen.getNextId() try { + await connection.beginTransactionAsync() const insertDetail = await prepare(connection, INSERT_PAYMENT_DETAIL) await insertDetail.executeAsync([paymentDetailId, payment.amount, payment.amount, payment.statusId, payment.modificationRationaleId, payment.desc, payment.typeId, payment.methodId, payment.projectId, payment.charityInd, payment.amount, payment.installmentNumber, payment.createUser]) const insertPayment = await prepare(connection, INSERT_PAYMENT) @@ -46,6 +47,7 @@ async function createPayment (payment) { const insertDetailXref = await prepare(connection, INSERT_PAYMENT_DETAIL_XREF) await insertDetailXref.executeAsync([paymentId, paymentDetailId]) logger.info(`Payment ${paymentId} with detail ${paymentDetailId} has been inserted`) + await connection.commitTransactionAsync() } catch (e) { logger.error(`Error in 'createPayment' ${e}, rolling back transaction`) await connection.rollbackTransactionAsync() diff --git a/src/services/processorService.js b/src/services/processorService.js index 7ba20e5..366086d 100644 --- a/src/services/processorService.js +++ b/src/services/processorService.js @@ -34,30 +34,47 @@ async function processUpdate (message) { createUser: createUserId } - // the properties of userPayment - try { - const userPayment = _.assign({ - memberId: message.payload.task.memberId, - amount: _.head(_.find(message.payload.prizeSets, ['type', 'placement']).prizes).value, - desc: `Task - ${message.payload.name} - First Place`, - typeId: config.WINNER_PAYMENT_TYPE_ID - }, basePayment) - await paymentService.createPayment(userPayment) - } catch (error) { - logger.error(`For challenge ${challengeId}, user prize info missing: ${error}`) + // add winner payment + const winnerPrizes = _.get(_.find(message.payload.prizeSets, ['type', 'placement']), 'prizes', []) + const winnerMembers = _.sortBy(_.get(message.payload, 'winners', []), ['placement']) + if (_.isEmpty(winnerPrizes)) { + logger.warn(`For challenge ${challengeId}, no winner payment avaiable`) + } else if (winnerPrizes.length !== winnerMembers.length) { + logger.error(`For challenge ${challengeId}, there is ${winnerPrizes.length} user prizes but ${winnerMembers.length} winners`) + } else { + try { + for (let i = 1; i <= winnerPrizes.length; i++) { + await paymentService.createPayment(_.assign({ + memberId: winnerMembers[i - 1].userId, + amount: winnerPrizes[i - 1].value, + desc: `Task - ${message.payload.name} - ${i} Place`, + typeId: config.WINNER_PAYMENT_TYPE_ID + }, basePayment)) + } + } catch (error) { + logger.error(`For challenge ${challengeId}, add winner payments error: ${error}`) + } } - // the properties of copilotPayment - try { - const copilotPayment = _.assign({ - memberId: createUserId, - amount: _.head(_.find(message.payload.prizeSets, ['type', 'copilot']).prizes).value, - desc: `Task - ${message.payload.name} - Copilot`, - typeId: config.COPILOT_PAYMENT_TYPE_ID - }, basePayment) - await paymentService.createPayment(copilotPayment) - } catch (error) { - logger.debug(`For challenge ${challengeId}, no copilot payment avaiable`) + // add copilot payment + const copilotId = await helper.getCopilotId(message.payload.id) + const copilotAmount = _.get(_.head(_.get(_.find(message.payload.prizeSets, ['type', 'copilot']), 'prizes', [])), 'value') + if (!copilotAmount) { + logger.warn(`For challenge ${challengeId}, no copilot payment avaiable`) + } else if (!copilotId) { + logger.warn(`For challenge ${challengeId}, no copilot memberId avaiable`) + } else { + try { + const copilotPayment = _.assign({ + memberId: copilotId, + amount: copilotAmount, + desc: `Task - ${message.payload.name} - Copilot`, + typeId: config.COPILOT_PAYMENT_TYPE_ID + }, basePayment) + await paymentService.createPayment(copilotPayment) + } catch (error) { + logger.error(`For challenge ${challengeId}, add copilot payments error: ${error}`) + } } } @@ -68,18 +85,23 @@ processUpdate.schema = { timestamp: Joi.date().required(), 'mime-type': Joi.string().required(), payload: Joi.object().keys({ - id: Joi.string(), + id: Joi.string().required(), legacyId: Joi.number().integer().positive(), task: Joi.object().keys({ memberId: Joi.string().allow(null) }).unknown(true).required(), - name: Joi.string(), + name: Joi.string().required(), prizeSets: Joi.array().items(Joi.object().keys({ type: Joi.string().valid('copilot', 'placement').required(), prizes: Joi.array().items(Joi.object().keys({ value: Joi.number().positive().required() }).unknown(true)) }).unknown(true)).min(1), + winners: Joi.array().items(Joi.object({ + userId: Joi.string().required(), + handle: Joi.string(), + placement: Joi.number().integer().positive().required() + }).unknown(true)), type: Joi.string().required(), status: Joi.string().required(), createdBy: Joi.string().required()