diff --git a/src/constants.js b/src/constants.js index 12696193..91e539f1 100644 --- a/src/constants.js +++ b/src/constants.js @@ -71,6 +71,12 @@ export const BUS_API_EVENT = { PROJECT_CANCELED: 'notifications.connect.project.canceled', PROJECT_ACTIVE: 'notifications.connect.project.active', + PROJECT_PHASE_TRANSITION_ACTIVE: 'notifications.connect.project.phase.transition.active', + PROJECT_PHASE_TRANSITION_COMPLETED: 'notifications.connect.project.phase.transition.completed', + PROJECT_PHASE_UPDATE_PAYMENT: 'notifications.connect.project.phase.update.payment', + PROJECT_PHASE_UPDATE_PROGRESS: 'notifications.connect.project.phase.update.progress', + PROJECT_PHASE_UPDATE_SCOPE: 'notifications.connect.project.phase.update.scope', + MEMBER_JOINED: 'notifications.connect.project.member.joined', MEMBER_LEFT: 'notifications.connect.project.member.left', MEMBER_REMOVED: 'notifications.connect.project.member.removed', @@ -81,12 +87,15 @@ export const BUS_API_EVENT = { PROJECT_LINK_CREATED: 'notifications.connect.project.linkCreated', PROJECT_FILE_UPLOADED: 'notifications.connect.project.fileUploaded', PROJECT_SPECIFICATION_MODIFIED: 'notifications.connect.project.specificationModified', + PROJECT_PROGRESS_MODIFIED: 'notifications.connect.project.progressModified', // When phase is added/updated/deleted from the project, // When product is added/deleted from a phase // When product is updated on any field other than specification PROJECT_PLAN_MODIFIED: 'notifications.connect.project.planModified', + PROJECT_PLAN_READY: 'notifications.connect.project.planReady', + // When specification of a product is modified PROJECT_PRODUCT_SPECIFICATION_MODIFIED: 'notifications.connect.project.productSpecificationModified', }; diff --git a/src/events/busApi.js b/src/events/busApi.js index 9608de1c..73cbc729 100644 --- a/src/events/busApi.js +++ b/src/events/busApi.js @@ -1,6 +1,6 @@ import _ from 'lodash'; import config from 'config'; -import { EVENT, BUS_API_EVENT, PROJECT_STATUS, PROJECT_MEMBER_ROLE } from '../constants'; +import { EVENT, BUS_API_EVENT, PROJECT_STATUS, PROJECT_PHASE_STATUS, PROJECT_MEMBER_ROLE } from '../constants'; import { createEvent } from '../services/busApi'; import models from '../models'; @@ -207,6 +207,34 @@ module.exports = (app, logger) => { }).catch(err => null); // eslint-disable-line no-unused-vars }); + /** + * If the project is in draft status and the phase is in reviewed status, and it's the + * only phase in the project with that status, then send the plan ready event. + * + * @param req the req + * @param project the project + * @param phase the phase that was created/updated + * @returns {Promise} + */ + async function sendPlanReadyEventIfNeeded(req, project, phase) { + if (project.status === PROJECT_STATUS.DRAFT && + phase.status === PROJECT_PHASE_STATUS.REVIEWED) { + await models.ProjectPhase.count({ + where: { projectId: project.id, status: PROJECT_PHASE_STATUS.REVIEWED }, + }).then(((count) => { + // only send the plan ready event when this is the only reviewed phase in the project + if (count !== 1) { return; } + createEvent(BUS_API_EVENT.PROJECT_PLAN_READY, { + projectId: project.id, + phaseId: phase.id, + projectName: project.name, + userId: req.authUser.userId, + initiatorUserId: req.authUser.userId, + }, logger); + })); + } + } + /** * PROJECT_PHASE_ADDED */ @@ -226,6 +254,8 @@ module.exports = (app, logger) => { userId: req.authUser.userId, initiatorUserId: req.authUser.userId, }, logger); + + return sendPlanReadyEventIfNeeded(req, project, created); }).catch(err => null); // eslint-disable-line no-unused-vars }); @@ -258,6 +288,7 @@ module.exports = (app, logger) => { logger.debug('receive PROJECT_PHASE_UPDATED event'); const projectId = _.parseInt(req.params.projectId); + const phaseId = _.parseInt(req.params.phaseId); models.Project.findOne({ where: { id: projectId }, @@ -270,6 +301,31 @@ module.exports = (app, logger) => { userId: req.authUser.userId, initiatorUserId: req.authUser.userId, }, logger); + + [ + ['spentBudget', BUS_API_EVENT.PROJECT_PHASE_UPDATE_PAYMENT], + ['progress', [BUS_API_EVENT.PROJECT_PHASE_UPDATE_PROGRESS, BUS_API_EVENT.PROJECT_PROGRESS_MODIFIED]], + ['details', BUS_API_EVENT.PROJECT_PHASE_UPDATE_SCOPE], + ['status', BUS_API_EVENT.PROJECT_PHASE_TRANSITION_ACTIVE, PROJECT_PHASE_STATUS.ACTIVE], + ['status', BUS_API_EVENT.PROJECT_PHASE_TRANSITION_COMPLETED, PROJECT_PHASE_STATUS.COMPLETED], + ].forEach(([key, events, sendIfEqual]) => { + // eslint-disable-next-line no-param-reassign + events = Array.isArray(events) ? events : [events]; + + // send event(s) only if the target field's value was updated, or when an update matches a "sendIfEqual" value + if ((!sendIfEqual && !_.isEqual(original[key], updated[key])) || + (original[key] !== sendIfEqual && updated[key] === sendIfEqual)) { + events.forEach(event => createEvent(event, { + projectId, + phaseId, + projectName: project.name, + userId: req.authUser.userId, + initiatorUserId: req.authUser.userId, + }, logger)); + } + }); + + return sendPlanReadyEventIfNeeded(req, project, updated); }).catch(err => null); // eslint-disable-line no-unused-vars });