From 85feffbb2e19885e33ec2f4f1e6dac83a25dd649 Mon Sep 17 00:00:00 2001
From: Sebastian <sebastian.mihalache@thinslices.com>
Date: Wed, 25 Apr 2018 13:45:35 +0300
Subject: [PATCH] feat(component-invite): send email to HE when reviewer agrees

---
 .../src/helpers/Collection.js                 | 63 +++++--------------
 .../src/helpers/Invitation.js                 | 29 +++++----
 packages/component-invite/src/helpers/User.js | 51 ++++++++-------
 .../component-invite/src/helpers/helpers.js   |  3 +
 .../routes/collectionsInvitations/decline.js  | 13 ++--
 .../routes/collectionsInvitations/patch.js    | 50 ++++++++-------
 .../collectionsInvitations/decline.test.js    |  2 +-
 .../collectionsInvitations/patch.test.js      |  2 +-
 8 files changed, 96 insertions(+), 117 deletions(-)

diff --git a/packages/component-invite/src/helpers/Collection.js b/packages/component-invite/src/helpers/Collection.js
index c1a4c3a33..9da0b0d10 100644
--- a/packages/component-invite/src/helpers/Collection.js
+++ b/packages/component-invite/src/helpers/Collection.js
@@ -1,47 +1,8 @@
-const invitationHelper = require('./Invitation')
-const mailService = require('pubsweet-component-mail-service')
-const logger = require('@pubsweet/logger')
 const config = require('config')
 const last = require('lodash/last')
 
 const statuses = config.get('statuses')
 
-const addInvitation = async (collection, userId, role) => {
-  collection.invitations = collection.invitations || []
-  let matchingInvitation = collection.invitations.find(
-    invitation =>
-      invitation.userId === userId &&
-      invitation.role === role &&
-      invitation.hasAnswer === false,
-  )
-  if (matchingInvitation === undefined) {
-    matchingInvitation = await invitationHelper.setupInvitation(
-      userId,
-      role,
-      collection,
-    )
-  } else {
-    matchingInvitation.timestamp = Date.now()
-  }
-
-  await collection.save()
-  return matchingInvitation
-}
-
-const addAuthor = async (collection, user, res, url) => {
-  if (collection.owners.includes(user.id)) {
-    return res.status(200).json(user)
-  }
-  try {
-    await mailService.setupAssignEmail(user.email, 'assign-author', url)
-
-    return res.status(200).json(user)
-  } catch (e) {
-    logger.error(e)
-    return res.status(500).json({ error: 'Email could not be sent.' })
-  }
-}
-
 const addHandlingEditor = async (collection, user, invitation) => {
   collection.handlingEditor = {
     id: user.id,
@@ -63,18 +24,28 @@ const updateHandlingEditor = async (collection, isAccepted) => {
   await updateStatus(collection, status)
 }
 
-const getFragmentAndAuthorData = async (models, collection) => {
-  const fragment = await models.Fragment.find(last(collection.fragments))
-  let { title } = fragment.metadata
+const getFragmentAndAuthorData = async ({
+  UserModel,
+  FragmentModel,
+  collection: { fragments, authors },
+}) => {
+  const fragment = await FragmentModel.find(last(fragments))
+  let { title, abstract } = fragment.metadata
   title = title.replace(/<(.|\n)*?>/g, '')
+  abstract = abstract ? abstract.replace(/<(.|\n)*?>/g, '') : ''
 
-  const submittingAuthorData = collection.authors.find(
+  const submittingAuthorData = authors.find(
     author => author.isSubmitting === true,
   )
-  const author = await models.User.find(submittingAuthorData.userId)
+  const author = await UserModel.find(submittingAuthorData.userId)
   const authorName = `${author.firstName} ${author.lastName}`
+  const authorsPromises = authors.map(async author => {
+    const user = await UserModel.find(author.userId)
+    return `${user.firstName} ${user.lastName}`
+  })
+  const authorsList = await Promise.all(authorsPromises)
   const { id } = fragment
-  return { title, authorName, id }
+  return { title, authorName, id, abstract, authorsList }
 }
 
 const updateReviewerCollectionStatus = async collection => {
@@ -92,8 +63,6 @@ const updateStatus = async (collection, newStatus) => {
 }
 
 module.exports = {
-  addInvitation,
-  addAuthor,
   addHandlingEditor,
   updateHandlingEditor,
   getFragmentAndAuthorData,
diff --git a/packages/component-invite/src/helpers/Invitation.js b/packages/component-invite/src/helpers/Invitation.js
index b95bfb071..b7ae10f4f 100644
--- a/packages/component-invite/src/helpers/Invitation.js
+++ b/packages/component-invite/src/helpers/Invitation.js
@@ -1,4 +1,5 @@
 const uuid = require('uuid')
+const collectionHelper = require('./Collection')
 
 const getInvitationData = (invitations, userId, role) => {
   const matchingInvitation = invitations.find(
@@ -41,34 +42,32 @@ const setupReviewerInvitation = async ({
   timestamp,
   resend = false,
 }) => {
-  const fragment = await FragmentModel.find(collection.fragments[0])
-  const submittingAuthorData = collection.authors.find(
-    author => author.isSubmitting === true,
-  )
-  const submittingAuthor = await UserModel.find(submittingAuthorData.userId)
-  const authorsPromises = collection.authors.map(async author => {
-    const user = await UserModel.find(author.userId)
-    return `${user.firstName} ${user.lastName}`
+  const {
+    title,
+    authorName,
+    id,
+    abstract,
+    authrosList,
+  } = await collectionHelper.getFragmentAndAuthorData({
+    UserModel,
+    FragmentModel,
+    collection,
   })
-  const authors = await Promise.all(authorsPromises)
-  let { abstract, title } = fragment.metadata
-  title = title.replace(/<(.|\n)*?>/g, '')
-  abstract = abstract ? abstract.replace(/<(.|\n)*?>/g, '') : ''
 
   const params = {
     invitedUser: user,
     baseUrl,
     collection: {
       id: collection.id,
-      authorName: `${submittingAuthor.firstName} ${submittingAuthor.lastName}`,
+      authorName,
       handlingEditor: collection.handlingEditor,
     },
     subject: `${collection.customId}: Review Requested`,
     fragment: {
-      id: fragment.id,
+      id,
       title,
       abstract,
-      authors,
+      authrosList,
     },
     invitation: {
       id: invitationId,
diff --git a/packages/component-invite/src/helpers/User.js b/packages/component-invite/src/helpers/User.js
index 05adf5362..ebcd946ff 100644
--- a/packages/component-invite/src/helpers/User.js
+++ b/packages/component-invite/src/helpers/User.js
@@ -41,38 +41,37 @@ const getEditorInChief = async UserModel => {
   return eic
 }
 
-const setupReviewerDeclinedEmailData = async (
-  models,
+const setupReviewerDecisionEmailData = async ({
+  baseUrl,
+  UserModel,
+  FragmentModel,
   collection,
-  req,
-  res,
-  user,
+  reviewerName,
   mailService,
-) => {
+  agree,
+  timestamp = Date.now(),
+}) => {
   const {
     title,
     authorName,
     id,
-  } = await collectionHelper.getFragmentAndAuthorData(models, collection)
-  const eic = await getEditorInChief(models.User)
+  } = await collectionHelper.getFragmentAndAuthorData({
+    UserModel,
+    FragmentModel,
+    collection,
+  })
+  const eic = await getEditorInChief(UserModel)
   const toEmail = collection.handlingEditor.email
-  try {
-    await mailService.setupReviewerDeclinedEmail(
-      toEmail,
-      user,
-      collection,
-      title,
-      authorName,
-      id,
-      `${eic.firstName} ${eic.lastName}`,
-      `${req.protocol}://${req.get('host')}`,
-    )
-    await user.save()
-    res.status(200).json({})
-  } catch (e) {
-    logger.error(e)
-    return res.status(500).json({ error: 'Email could not be sent.' })
-  }
+  await mailService.setupReviewerDecisionEmail({
+    toEmail,
+    reviewerName,
+    collection,
+    eicName: `${eic.firstName} ${eic.lastName}`,
+    baseUrl,
+    fragment: { id, title, authorName },
+    agree,
+    timestamp,
+  })
 }
 
 const setupReviewerUnassignEmail = async (
@@ -97,6 +96,6 @@ const setupReviewerUnassignEmail = async (
 module.exports = {
   setupNewUser,
   getEditorInChief,
-  setupReviewerDeclinedEmailData,
+  setupReviewerDecisionEmailData,
   setupReviewerUnassignEmail,
 }
diff --git a/packages/component-invite/src/helpers/helpers.js b/packages/component-invite/src/helpers/helpers.js
index 429c91f29..b48472146 100644
--- a/packages/component-invite/src/helpers/helpers.js
+++ b/packages/component-invite/src/helpers/helpers.js
@@ -112,9 +112,12 @@ const createNewUser = async (
   }
 }
 
+const getBaseUrl = req => `${req.protocol}://${req.get('host')}`
+
 module.exports = {
   checkForUndefinedParams,
   validateEmailAndToken,
   handleNotFoundError,
   createNewUser,
+  getBaseUrl,
 }
diff --git a/packages/component-invite/src/routes/collectionsInvitations/decline.js b/packages/component-invite/src/routes/collectionsInvitations/decline.js
index 97714177f..64daa1e63 100644
--- a/packages/component-invite/src/routes/collectionsInvitations/decline.js
+++ b/packages/component-invite/src/routes/collectionsInvitations/decline.js
@@ -37,14 +37,15 @@ module.exports = models => async (req, res) => {
     invitation.hasAnswer = true
     invitation.isAccepted = false
     await collection.save()
-    return await userHelper.setupReviewerDeclinedEmailData(
-      models,
+    return await userHelper.setupReviewerDecisionEmailData({
+      baseUrl: helpers.getBaseUrl(req),
+      UserModel: models.User,
+      FragmentModel: models.Fragment,
       collection,
-      req,
-      res,
-      user,
+      reviewerName: `${user.firstName} ${user.lastName}`,
       mailService,
-    )
+      agree: false,
+    })
   } catch (e) {
     const notFoundError = await helpers.handleNotFoundError(e, 'item')
     return res.status(notFoundError.status).json({
diff --git a/packages/component-invite/src/routes/collectionsInvitations/patch.js b/packages/component-invite/src/routes/collectionsInvitations/patch.js
index da754a1fc..03dada906 100644
--- a/packages/component-invite/src/routes/collectionsInvitations/patch.js
+++ b/packages/component-invite/src/routes/collectionsInvitations/patch.js
@@ -4,9 +4,7 @@ const teamHelper = require('../../helpers/Team')
 const mailService = require('pubsweet-component-mail-service')
 const userHelper = require('../../helpers/User')
 const collectionHelper = require('../../helpers/Collection')
-const config = require('config')
 
-const statuses = config.get('statuses')
 module.exports = models => async (req, res) => {
   const { collectionId, invitationId } = req.params
   const { isAccepted, reason } = req.body
@@ -38,6 +36,14 @@ module.exports = models => async (req, res) => {
         }`,
       })
 
+    const params = {
+      baseUrl: helpers.getBaseUrl(req),
+      UserModel: models.User,
+      FragmentModel: models.Fragment,
+      collection,
+      reviewerName: `${user.firstName} ${user.lastName}`,
+      mailService,
+    }
     if (invitation.role === 'handlingEditor')
       await collectionHelper.updateHandlingEditor(collection, isAccepted)
     invitation.timestamp = Date.now()
@@ -51,19 +57,25 @@ module.exports = models => async (req, res) => {
       if (
         invitation.role === 'reviewer' &&
         collection.status === 'reviewersInvited'
-      ) {
-        collection.status = 'underReview'
-        collection.visibleStatus = statuses[collection.status].private
-      }
+      )
+        await collectionHelper.updateStatus(collection, 'underReview')
+
       await collection.save()
       try {
-        await mailService.setupAgreeEmail(
-          toEmail,
-          user,
-          invitation.role,
-          `${req.protocol}://${req.get('host')}`,
-          collection.customId,
-        )
+        if (invitation.role === 'handlingEditor')
+          await mailService.setupAgreeEmail(
+            toEmail,
+            user,
+            invitation.role,
+            `${req.protocol}://${req.get('host')}`,
+            collection.customId,
+          )
+        if (invitation.role === 'reviewer')
+          await userHelper.setupReviewerDecisionEmailData({
+            ...params,
+            agree: true,
+            timestamp: invitation.timestamp,
+          })
       } catch (e) {
         logger.error(e)
         return res.status(500).json({ error: 'Email could not be sent.' })
@@ -93,14 +105,10 @@ module.exports = models => async (req, res) => {
           )
         } else if (invitation.role === 'reviewer') {
           await collectionHelper.updateReviewerCollectionStatus(collection)
-          return await userHelper.setupReviewerDeclinedEmailData(
-            models,
-            collection,
-            req,
-            res,
-            user,
-            mailService,
-          )
+          return await userHelper.setupReviewerDecisionEmailData({
+            ...params,
+            agree: false,
+          })
         }
       } catch (e) {
         logger.error(e)
diff --git a/packages/component-invite/src/tests/collectionsInvitations/decline.test.js b/packages/component-invite/src/tests/collectionsInvitations/decline.test.js
index 2d9941282..9da12457d 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/decline.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/decline.test.js
@@ -7,7 +7,7 @@ const Model = require('./../helpers/Model')
 const cloneDeep = require('lodash/cloneDeep')
 
 jest.mock('pubsweet-component-mail-service', () => ({
-  setupReviewerDeclinedEmail: jest.fn(),
+  setupReviewerDecisionEmail: jest.fn(),
 }))
 
 const reqBody = {
diff --git a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
index c03b6779d..fba9ffbe3 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
@@ -10,7 +10,7 @@ jest.mock('pubsweet-component-mail-service', () => ({
   setupAssignEmail: jest.fn(),
   setupAgreeEmail: jest.fn(),
   setupDeclineEmail: jest.fn(),
-  setupReviewerDeclinedEmail: jest.fn(),
+  setupReviewerDecisionEmail: jest.fn(),
 }))
 
 const reqBody = {
-- 
GitLab