diff --git a/site/gatsby-site/cypress/e2e/integration/apps/submitted.cy.js b/site/gatsby-site/cypress/e2e/integration/apps/submitted.cy.js index 8f6489dadd..ce8dee3cdc 100644 --- a/site/gatsby-site/cypress/e2e/integration/apps/submitted.cy.js +++ b/site/gatsby-site/cypress/e2e/integration/apps/submitted.cy.js @@ -171,21 +171,6 @@ describe('Submitted reports', () => { } ); - cy.conditionalIntercept( - '**/graphql', - (req) => - req.body.operationName == 'UpsertSubscription' && - req.body.variables?.query?.type === SUBSCRIPTION_TYPE.submissionPromoted, - 'UpsertSubscriptionPromoted', - { - data: { - upsertOneSubscription: { - _id: 'dummyIncidentId', - }, - }, - } - ); - cy.get('select[data-cy="promote-select"]').as('dropdown'); cy.get('@dropdown').select('Incident'); diff --git a/site/gatsby-site/cypress/e2e/unit/functions/processNotifications/processNewPromotionsNotifications.cy.js b/site/gatsby-site/cypress/e2e/unit/functions/processNotifications/processNewPromotionsNotifications.cy.js index a3f6855336..68b8d6868e 100644 --- a/site/gatsby-site/cypress/e2e/unit/functions/processNotifications/processNewPromotionsNotifications.cy.js +++ b/site/gatsby-site/cypress/e2e/unit/functions/processNotifications/processNewPromotionsNotifications.cy.js @@ -12,12 +12,14 @@ const pendingNotifications = [ type: SUBSCRIPTION_TYPE.submissionPromoted, incident_id: 217, processed: false, + userId: '63320ce63ec803072c9f5291', }, { _id: '63616f82d0db19c07d081401', type: SUBSCRIPTION_TYPE.submissionPromoted, incident_id: 218, processed: false, + userId: '63320ce63ec803072c9f5291', }, //Duplicated pending notification { @@ -25,6 +27,7 @@ const pendingNotifications = [ type: SUBSCRIPTION_TYPE.submissionPromoted, incident_id: 218, processed: false, + userId: '63320ce63ec803072c9f5291', }, ]; @@ -73,9 +76,7 @@ describe('Process New Promotions Pending Notifications', () => { const sendEmailCallArgs = sendEmailCalls[i].args[1]; - const userIds = subscriptions - .filter((s) => s.incident_id === pendingNotification.incident_id) - .map((subscription) => subscription.userId); + const userIds = pendingNotifications.map((n) => n.userId); const incident = incidents.find((i) => i.incident_id == pendingNotification.incident_id); @@ -107,12 +108,11 @@ describe('Process New Promotions Pending Notifications', () => { }); it('New Promotions - Should send pending submissions promoted notifications', () => { - const { notificationsCollection, subscriptionsCollection, incidentsCollection } = - stubEverything({ - subscriptionType: SUBSCRIPTION_TYPE.submissionPromoted, - pendingNotifications, - subscriptions, - }); + const { notificationsCollection, incidentsCollection } = stubEverything({ + subscriptionType: SUBSCRIPTION_TYPE.submissionPromoted, + pendingNotifications, + subscriptions, + }); cy.wrap(processNotifications()).then(() => { expect(notificationsCollection.find.getCall(3).args[0]).to.deep.equal({ @@ -120,30 +120,20 @@ describe('Process New Promotions Pending Notifications', () => { type: SUBSCRIPTION_TYPE.submissionPromoted, }); - for (const subscription of subscriptions) { + for (const notification of pendingNotifications) { expect(global.context.functions.execute).to.be.calledWith('getUser', { - userId: subscription.userId, + userId: notification.userId, }); } for (let i = 0; i < uniquePendingNotifications.length; i++) { const pendingNotification = uniquePendingNotifications[i]; - expect( - subscriptionsCollection.find.getCall(i).args[0], - 'Get subscriptions for Incident' - ).to.deep.equal({ - type: SUBSCRIPTION_TYPE.submissionPromoted, - incident_id: pendingNotification.incident_id, - }); - expect(incidentsCollection.findOne.getCall(i).args[0], 'Find incident').to.deep.equal({ incident_id: pendingNotification.incident_id, }); - const userIds = subscriptions - .filter((s) => s.incident_id === pendingNotification.incident_id) - .map((subscription) => subscription.userId); + const userIds = pendingNotifications.map((n) => n.userId); const incident = incidents.find((i) => i.incident_id == pendingNotification.incident_id); @@ -176,7 +166,7 @@ describe('Process New Promotions Pending Notifications', () => { }); it('New Promotions - Should mark pending notifications as processed if there are no subscribers', () => { - const { notificationsCollection, subscriptionsCollection } = stubEverything({ + const { notificationsCollection } = stubEverything({ subscriptionType: SUBSCRIPTION_TYPE.submissionPromoted, pendingNotifications, subscriptions: [], @@ -203,16 +193,9 @@ describe('Process New Promotions Pending Notifications', () => { type: SUBSCRIPTION_TYPE.submissionPromoted, }); - expect(global.context.functions.execute).not.to.be.called; - for (let i = 0; i < uniquePendingNotifications.length; i++) { const pendingNotification = uniquePendingNotifications[i]; - expect(subscriptionsCollection.find.getCall(i).args[0]).to.deep.equal({ - type: SUBSCRIPTION_TYPE.submissionPromoted, - incident_id: pendingNotification.incident_id, - }); - expect(notificationsCollection.updateOne.getCall(i).args[0]).to.deep.equal({ _id: pendingNotification._id, }); diff --git a/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js b/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js index 3c67252f39..6bc67a8a00 100644 --- a/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js +++ b/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js @@ -260,10 +260,11 @@ describe('Functions', () => { modifiedBy: submission.user, }); - expect(subscriptionsCollection.insertOne.firstCall.args[0]).to.deep.equal({ + expect(notificationsCollection.insertOne.firstCall.args[0]).to.deep.equal({ type: SUBSCRIPTION_TYPE.submissionPromoted, incident_id: 2, userId: 'user1', + processed: false, }); }); }); diff --git a/site/realm/data_sources/mongodb-atlas/customData/notifications/relationships.json b/site/realm/data_sources/mongodb-atlas/customData/notifications/relationships.json index 0967ef424b..c26202cf5c 100644 --- a/site/realm/data_sources/mongodb-atlas/customData/notifications/relationships.json +++ b/site/realm/data_sources/mongodb-atlas/customData/notifications/relationships.json @@ -1 +1,8 @@ -{} +{ + "userId": { + "ref": "#/relationship/mongodb-atlas/customData/users", + "source_key": "userId", + "foreign_key": "userId", + "is_list": false + } +} diff --git a/site/realm/data_sources/mongodb-atlas/customData/notifications/schema.json b/site/realm/data_sources/mongodb-atlas/customData/notifications/schema.json index 62d7133b7a..4217efc287 100644 --- a/site/realm/data_sources/mongodb-atlas/customData/notifications/schema.json +++ b/site/realm/data_sources/mongodb-atlas/customData/notifications/schema.json @@ -14,6 +14,9 @@ }, "type": { "bsonType": "string" + }, + "userId": { + "bsonType": "string" } }, "title": "notification" diff --git a/site/realm/functions/processNotifications.js b/site/realm/functions/processNotifications.js index 3ee9b13f7c..bd458a1a79 100644 --- a/site/realm/functions/processNotifications.js +++ b/site/realm/functions/processNotifications.js @@ -240,54 +240,54 @@ exports = async function () { if (!uniqueNotifications.some(n => n.incident_id === pendingNotification.incident_id && n.type === pendingNotification.type)) { uniqueNotifications.push(pendingNotification); - try { - const subscriptionsToIncidentUpdates = await subscriptionsCollection.find({ - type: 'incident', - incident_id: pendingNotification.incident_id - }).toArray(); + try { + const subscriptionsToIncidentUpdates = await subscriptionsCollection.find({ + type: 'incident', + incident_id: pendingNotification.incident_id + }).toArray(); - // Process subscriptions to Incident updates - if (subscriptionsToIncidentUpdates.length > 0) { + // Process subscriptions to Incident updates + if (subscriptionsToIncidentUpdates.length > 0) { - const userIds = subscriptionsToIncidentUpdates.map((subscription) => subscription.userId); + const userIds = subscriptionsToIncidentUpdates.map((subscription) => subscription.userId); - const uniqueUserIds = [...new Set(userIds)]; + const uniqueUserIds = [...new Set(userIds)]; - const recipients = await getRecipients(uniqueUserIds); + const recipients = await getRecipients(uniqueUserIds); - const incident = await incidentsCollection.findOne({ incident_id: pendingNotification.incident_id }); + const incident = await incidentsCollection.findOne({ incident_id: pendingNotification.incident_id }); - const newReportNumber = pendingNotification.report_number; + const newReportNumber = pendingNotification.report_number; - const newReport = newReportNumber ? await reportsCollection.findOne({ report_number: newReportNumber }) : null; + const newReport = newReportNumber ? await reportsCollection.findOne({ report_number: newReportNumber }) : null; - //Send email notification - const sendEmailParams = { - recipients, - subject: 'Incident {{incidentId}} was updated', - dynamicData: { - incidentId: `${incident.incident_id}`, - incidentTitle: incident.title, - incidentUrl: `https://incidentdatabase.ai/cite/${incident.incident_id}`, - reportUrl: `https://incidentdatabase.ai/cite/${incident.incident_id}#r${newReportNumber}`, - reportTitle: newReportNumber ? newReport.title : '', - reportAuthor: newReportNumber && newReport.authors[0] ? newReport.authors[0] : '', - }, - // Template value from function name sufix from "site/realm/functions/config.json" - templateId: newReportNumber ? 'NewReportAddedToAnIncident' : 'IncidentUpdate', - }; + //Send email notification + const sendEmailParams = { + recipients, + subject: 'Incident {{incidentId}} was updated', + dynamicData: { + incidentId: `${incident.incident_id}`, + incidentTitle: incident.title, + incidentUrl: `https://incidentdatabase.ai/cite/${incident.incident_id}`, + reportUrl: `https://incidentdatabase.ai/cite/${incident.incident_id}#r${newReportNumber}`, + reportTitle: newReportNumber ? newReport.title : '', + reportAuthor: newReportNumber && newReport.authors[0] ? newReport.authors[0] : '', + }, + // Template value from function name sufix from "site/realm/functions/config.json" + templateId: newReportNumber ? 'NewReportAddedToAnIncident' : 'IncidentUpdate', + }; - await context.functions.execute('sendEmail', sendEmailParams); + await context.functions.execute('sendEmail', sendEmailParams); - console.log(`Incident ${incident.incident_id} updates: Pending notification was processed.`); - } - } catch (error) { - // If there is an error sending the email > Mark the notification as not processed - await markNotificationsAsNotProcessed(notificationsCollection, [pendingNotification]); + console.log(`Incident ${incident.incident_id} updates: Pending notification was processed.`); + } + } catch (error) { + // If there is an error sending the email > Mark the notification as not processed + await markNotificationsAsNotProcessed(notificationsCollection, [pendingNotification]); - error.message = `[Process Pending Notifications: Incidents Updates]: ${error.message}`; - context.functions.execute('logRollbar', { error }); - } + error.message = `[Process Pending Notifications: Incidents Updates]: ${error.message}`; + context.functions.execute('logRollbar', { error }); + } } } } @@ -299,7 +299,6 @@ exports = async function () { context.functions.execute('logRollbar', { error }); } - // Notifications to New Promotions try { @@ -310,6 +309,12 @@ exports = async function () { result += pendingNotificationsToNewPromotions.length; + const userIds = pendingNotificationsToNewPromotions.map((subscription) => subscription.userId); + + const uniqueUserIds = [...new Set(userIds)]; + + const recipients = await getRecipients(uniqueUserIds); + let uniqueNotifications = []; for (const pendingNotification of pendingNotificationsToNewPromotions) { @@ -317,56 +322,38 @@ exports = async function () { // Mark the notification as processed before sending the email await markNotificationsAsProcessed(notificationsCollection, [pendingNotification]); - // Process each Incident only once if (!uniqueNotifications.includes(pendingNotification.incident_id)) { uniqueNotifications.push(pendingNotification.incident_id); - // Finds all subscriptions to New Promotions for this Incident - const subscriptionsToNewPromotions = await subscriptionsCollection.find({ - type: 'submission-promoted', - incident_id: pendingNotification.incident_id - }).toArray(); - - // Process subscriptions to New Incidents - if (subscriptionsToNewPromotions.length > 0) { - - const userIds = subscriptionsToNewPromotions.map((subscription) => subscription.userId); - - const uniqueUserIds = [...new Set(userIds)]; - - const recipients = await getRecipients(uniqueUserIds); - - try { - const incident = await incidentsCollection.findOne({ incident_id: pendingNotification.incident_id }); - - //Send email notification - const sendEmailParams = { - recipients, - subject: 'Your submission has been approved!', - dynamicData: { - incidentId: `${incident.incident_id}`, - incidentTitle: incident.title, - incidentUrl: `https://incidentdatabase.ai/cite/${incident.incident_id}`, - incidentDescription: incident.description, - incidentDate: incident.date, - }, - templateId: 'SubmissionApproved' // Template value from function name sufix from "site/realm/functions/config.json" - }; + try { + const incident = await incidentsCollection.findOne({ incident_id: pendingNotification.incident_id }); - await context.functions.execute('sendEmail', sendEmailParams); + //Send email notification + const sendEmailParams = { + recipients, + subject: 'Your submission has been approved!', + dynamicData: { + incidentId: `${incident.incident_id}`, + incidentTitle: incident.title, + incidentUrl: `https://incidentdatabase.ai/cite/${incident.incident_id}`, + incidentDescription: incident.description, + incidentDate: incident.date, + }, + templateId: 'SubmissionApproved' // Template value from function name sufix from "site/realm/functions/config.json" + }; - console.log(`Promoted notification for incident ${incident.incident_id} was processed.`); + await context.functions.execute('sendEmail', sendEmailParams); - } catch (error) { - // If there is an error sending the email > Mark the notification as not processed - await markNotificationsAsNotProcessed(notificationsCollection, [pendingNotification]); + } catch (error) { + // If there is an error sending the email > Mark the notification as not processed + await markNotificationsAsNotProcessed(notificationsCollection, [pendingNotification]); - error.message = `[Process Pending Notifications: Submission Promoted]: ${error.message}`; - context.functions.execute('logRollbar', { error }); - } + error.message = `[Process Pending Notifications: Submission Promoted]: ${error.message}`; + context.functions.execute('logRollbar', { error }); } } } + console.log(`New Promotions: ${pendingNotificationsToNewPromotions.length} pending notifications were processed.`); } else { diff --git a/site/realm/functions/promoteSubmissionToReport.js b/site/realm/functions/promoteSubmissionToReport.js index 71ca7aabd2..7cd0189b39 100644 --- a/site/realm/functions/promoteSubmissionToReport.js +++ b/site/realm/functions/promoteSubmissionToReport.js @@ -54,16 +54,12 @@ exports = async (input) => { await incidents.insertOne({ ...newIncident, incident_id: BSON.Int32(newIncident.incident_id) }); if (submission.user) { - await subscriptionsCollection.insertOne({ - type: 'submission-promoted', - incident_id: BSON.Int32(newIncident.incident_id), - userId: submission.user - }); await notificationsCollection.insertOne({ type: 'submission-promoted', incident_id: BSON.Int32(newIncident.incident_id), - processed: false + processed: false, + userId: submission.user }); }