diff --git a/README.md b/README.md index b529c166..15df917c 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ The following parameters can be set in config files or in env variables: - ES.ES_REFRESH: Elasticsearch refresh method. Default to string `true`(i.e. refresh immediately) - FILE_UPLOAD_SIZE_LIMIT: the file upload size limit in bytes - RESOURCES_API_URL: TC resources API base URL +- V3_PROJECTS_API_URL: TC direct projects API base URL - GROUPS_API_URL: TC groups API base URL - PROJECTS_API_URL: TC projects API base URL - TERMS_API_URL: TC Terms API Base URL diff --git a/config/default.js b/config/default.js index 58ea49b6..e7d1cf02 100644 --- a/config/default.js +++ b/config/default.js @@ -50,6 +50,7 @@ module.exports = { GROUPS_API_URL: process.env.GROUPS_API_URL || 'http://localhost:4000/v5/groups', PROJECTS_API_URL: process.env.PROJECTS_API_URL || 'http://localhost:4000/v5/projects', TERMS_API_URL: process.env.TERMS_API_URL || 'http://localhost:4000/v5/terms', + V3_PROJECTS_API_URL: process.env.V3_PROJECTS_API_URL || 'http://localhost:4000/v3/direct/projects', // copilot resource role ids allowed to upload attachment COPILOT_RESOURCE_ROLE_IDS: process.env.COPILOT_RESOURCE_ROLE_IDS ? process.env.COPILOT_RESOURCE_ROLE_IDS.split(',') : ['10ba038e-48da-487b-96e8-8d3b99b6d18b'], diff --git a/src/common/helper.js b/src/common/helper.js index ffb9f3cd..1ce3c49f 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -587,6 +587,19 @@ async function getProjectDefaultTerms (projectId) { return res.data.terms || [] } +/** + * This functions gets the default billing account for a given project id + * + * @param {Number} projectId The id of the project for which to get the default terms of use + * @returns {Promise} The billing account ID + */ +async function getProjectBillingAccount (projectId) { + const token = await getM2MToken() + const projectUrl = `${config.V3_PROJECTS_API_URL}/${projectId}` + const res = await axios.get(projectUrl, { headers: { Authorization: `Bearer ${token}` } }) + return _.get(res, 'data.result.content.billingAccountIds[0]', null) +} + /** * This function gets the challenge terms array with the terms data * The terms data is retrieved from the terms API using the specified terms ids @@ -642,5 +655,6 @@ module.exports = { listChallengesByMember, validateESRefreshMethod, getProjectDefaultTerms, - validateChallengeTerms + validateChallengeTerms, + getProjectBillingAccount } diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index c06ce228..02f7e107 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -443,6 +443,9 @@ async function populatePhases (phases, startDate, timelineTemplateId) { * @returns {Object} the created challenge */ async function createChallenge (currentUser, challenge, userToken) { + if (challenge.status === constants.challengeStatuses.Active) { + throw new errors.BadRequestError('You cannot create an Active challenge. Please create a Draft challenge and then change the status to Active.') + } await helper.ensureProjectExist(challenge.projectId, userToken) await validateChallengeData(challenge) if (challenge.phases && challenge.phases.length > 0) { @@ -755,6 +758,18 @@ async function update (currentUser, challengeId, data, userToken, isFull) { // helper.ensureNoDuplicateOrNullElements(data.gitRepoURLs, 'gitRepoURLs') const challenge = await helper.getById('Challenge', challengeId) + let billingAccountId + if (data.status) { + if (data.status === constants.challengeStatuses.Active && _.isUndefined(challenge.legacy.directProjectId)) { + throw new errors.BadRequestError('You cannot activate the challenge as it has not been created on legacy yet. Please try again later or contact support.') + } + if (data.status === constants.challengeStatuses.Completed) { + if (challenge.status !== constants.challengeStatuses.Active) { + throw new errors.BadRequestError('You cannot mark a Draft challenge as Completed') + } + billingAccountId = helper.getProjectBillingAccount(challenge.legacy.directProjectId) + } + } // FIXME: Tech Debt if (_.get(challenge, 'legacy.track') && _.get(data, 'legacy.track') && _.get(challenge, 'legacy.track') !== _.get(data, 'legacy.track')) { @@ -1091,7 +1106,11 @@ async function update (currentUser, challengeId, data, userToken, isFull) { // post bus event logger.debug(`Post Bus Event: ${constants.Topics.ChallengeUpdated} ${JSON.stringify(challenge)}`) - await helper.postBusEvent(constants.Topics.ChallengeUpdated, challenge) + const busEventPayload = { ...challenge } + if (billingAccountId) { + busEventPayload.billingAccountId = billingAccountId + } + await helper.postBusEvent(constants.Topics.ChallengeUpdated, busEventPayload) if (challenge.phases && challenge.phases.length > 0) { challenge.currentPhase = challenge.phases.slice().reverse().find(phase => phase.isOpen)