Skip to content
Snippets Groups Projects
Commit 5fb77dbd authored by Sebastian Mihalache's avatar Sebastian Mihalache :hammer_pick: Committed by Bogdan Cochior
Browse files

Send EQA email after final publish

parent d003b489
No related branches found
No related tags found
1 merge request!43Sprint #19
...@@ -4,6 +4,7 @@ const getEmailCopy = ({ ...@@ -4,6 +4,7 @@ const getEmailCopy = ({
titleText, titleText,
comments = '', comments = '',
targetUserName = '', targetUserName = '',
eicName = 'Editor in Chief',
}) => { }) => {
let paragraph let paragraph
let hasLink = true let hasLink = true
...@@ -80,6 +81,11 @@ const getEmailCopy = ({ ...@@ -80,6 +81,11 @@ const getEmailCopy = ({
case 'eqa-manuscript-request-for-approval': case 'eqa-manuscript-request-for-approval':
paragraph = `Manuscript ID ${customId} has passed peer-review and is now ready for EQA. Please click on the link below to either approve or return the manuscript to the Editor in Chief:` paragraph = `Manuscript ID ${customId} has passed peer-review and is now ready for EQA. Please click on the link below to either approve or return the manuscript to the Editor in Chief:`
break break
case 'eqa-manuscript-published':
hasLink = false
paragraph = `${titleText} has been accepted for publication by ${eicName}. <br/><br/>
Please approve QA screening in MTS system, so that manuscript can be published in Hindawi on hindawi.com`
break
default: default:
throw new Error(`The ${emailType} email type is not defined.`) throw new Error(`The ${emailType} email type is not defined.`)
} }
......
...@@ -51,84 +51,87 @@ module.exports = { ...@@ -51,84 +51,87 @@ module.exports = {
}, },
}) })
if ( // the EiC recommends to publish so an email to the EQA needs to be sent,
!hasEQA && // one requesting approval or one informing them that the manuscript has been published
isEditorInChief && if (isEditorInChief && newRecommendation.recommendation === 'publish') {
newRecommendation.recommendation === 'publish'
) {
sendEQAEmail({ sendEQAEmail({
email, email,
eicName, eicName,
baseUrl, baseUrl,
titleText,
collection, collection,
subjectBaseText, subjectBaseText,
}) })
} else { }
let comments
if (isEditorInChief) {
const eicComments = chain(newRecommendation)
.get('comments')
.find(comm => !comm.public)
.get('content')
.value()
comments = eicComments
}
const hasPeerReview = (collection = {}) => let comments
!isEmpty(collection.handlingEditor) if (isEditorInChief) {
const eicComments = chain(newRecommendation)
.get('comments')
.find(comm => !comm.public)
.get('content')
.value()
comments = eicComments
}
const hasPeerReview = (collection = {}) =>
!isEmpty(collection.handlingEditor)
if (
(isEditorInChief || newRecommendation.recommendationType === 'review') &&
hasPeerReview(collection)
) {
// the request came from either the Editor in Chief or a reviewer, so the HE needs to be notified
sendHandlingEditorEmail({
email,
hasEQA,
baseUrl,
eicName,
comments,
titleText,
targetUserName,
subjectBaseText,
handlingEditor: get(collection, 'handlingEditor', {}),
recommendation: newRecommendation.recommendation,
recommendationType: newRecommendation.recommendationType,
})
}
if ( if (
(isEditorInChief || newRecommendation.recommendationType !== 'review' &&
newRecommendation.recommendationType === 'review') && newRecommendation.recommendation !== 'return-to-handling-editor'
hasPeerReview(collection) ) {
) { if (isEditorInChief || collection.status === 'revisionRequested') {
// the request came from either the Editor in Chief or a reviewer, so the HE needs to be notified sendAuthorsEmail({
sendHandlingEditorEmail({
email, email,
eicName: await userHelper.getEiCName(), hasEQA,
baseUrl, baseUrl,
comments,
titleText, titleText,
targetUserName, parsedFragment,
fragmentAuthors,
isEditorInChief,
subjectBaseText, subjectBaseText,
handlingEditor: get(collection, 'handlingEditor', {}), newRecommendation,
recommendation: newRecommendation.recommendation, handlingEditorName: get(collection, 'handlingEditor.name', eicName),
recommendationType: newRecommendation.recommendationType,
}) })
} }
if ( if (hasPeerReview(collection)) {
newRecommendation.recommendationType !== 'review' && sendReviewersEmail({
newRecommendation.recommendation !== 'return-to-handling-editor' email,
) { hasEQA,
if (isEditorInChief || collection.status === 'revisionRequested') { baseUrl,
sendAuthorsEmail({ UserModel,
email, titleText,
baseUrl, fragmentHelper,
titleText, isEditorInChief,
parsedFragment, subjectBaseText,
fragmentAuthors, recommendation: newRecommendation.recommendation,
isEditorInChief, handlingEditorName: get(collection, 'handlingEditor.name', eicName),
subjectBaseText, })
newRecommendation,
handlingEditorName: get(collection, 'handlingEditor.name', eicName),
})
}
if (hasPeerReview(collection)) {
sendReviewersEmail({
email,
baseUrl,
UserModel,
titleText,
fragmentHelper,
isEditorInChief,
subjectBaseText,
recommendation: newRecommendation.recommendation,
handlingEditorName: get(collection, 'handlingEditor.name', eicName),
})
if (!isEditorInChief) {
sendEiCsEmail({ sendEiCsEmail({
email, email,
baseUrl, baseUrl,
...@@ -145,6 +148,7 @@ module.exports = { ...@@ -145,6 +148,7 @@ module.exports = {
const sendHandlingEditorEmail = ({ const sendHandlingEditorEmail = ({
email, email,
hasEQA,
eicName, eicName,
baseUrl, baseUrl,
comments, comments,
...@@ -161,6 +165,13 @@ const sendHandlingEditorEmail = ({ ...@@ -161,6 +165,13 @@ const sendHandlingEditorEmail = ({
emailType = 'he-review-submitted' emailType = 'he-review-submitted'
} else { } else {
email.content.subject = `${subjectBaseText} Decision` email.content.subject = `${subjectBaseText} Decision`
if (recommendation === 'publish' && !hasEQA) {
// the EiC recommended to publish but the manuscript has not passed through the EQA process
// so the HE should not receive any email
return
}
switch (recommendation) { switch (recommendation) {
case 'return-to-handling-editor': case 'return-to-handling-editor':
emailType = 'he-manuscript-return-with-comments' emailType = 'he-manuscript-return-with-comments'
...@@ -199,6 +210,7 @@ const sendHandlingEditorEmail = ({ ...@@ -199,6 +210,7 @@ const sendHandlingEditorEmail = ({
const sendAuthorsEmail = async ({ const sendAuthorsEmail = async ({
email, email,
hasEQA,
baseUrl, baseUrl,
titleText, titleText,
isEditorInChief, isEditorInChief,
...@@ -222,6 +234,11 @@ const sendAuthorsEmail = async ({ ...@@ -222,6 +234,11 @@ const sendAuthorsEmail = async ({
} }
if (newRecommendation.recommendation === 'publish') { if (newRecommendation.recommendation === 'publish') {
if (!hasEQA) {
// the manuscript did not pass through the EQA process
return
}
emailType = 'author-manuscript-published' emailType = 'author-manuscript-published'
email.content.subject = `${subjectBaseText} Published` email.content.subject = `${subjectBaseText} Published`
} else { } else {
...@@ -283,6 +300,7 @@ const sendAuthorsEmail = async ({ ...@@ -283,6 +300,7 @@ const sendAuthorsEmail = async ({
const sendReviewersEmail = async ({ const sendReviewersEmail = async ({
email, email,
baseUrl, baseUrl,
hasEQA,
eicName, eicName,
titleText, titleText,
UserModel, UserModel,
...@@ -300,6 +318,12 @@ const sendReviewersEmail = async ({ ...@@ -300,6 +318,12 @@ const sendReviewersEmail = async ({
? 'submitted-reviewers-after-publish' ? 'submitted-reviewers-after-publish'
: 'submitted-reviewers-after-reject' : 'submitted-reviewers-after-reject'
if (recommendation === 'publish' && !hasEQA) {
// the manuscript has not passed through the EQA process
// so the reviewers should not receive any email
return
}
reviewers = (await fragmentHelper.getReviewers({ reviewers = (await fragmentHelper.getReviewers({
UserModel, UserModel,
type: 'submitted', type: 'submitted',
...@@ -416,10 +440,35 @@ const sendEQAEmail = ({ ...@@ -416,10 +440,35 @@ const sendEQAEmail = ({
email, email,
eicName, eicName,
baseUrl, baseUrl,
titleText,
collection, collection,
subjectBaseText, subjectBaseText,
}) => { }) => {
const emailType = 'eqa-manuscript-request-for-approval' let emailType
switch (collection.status) {
case 'accepted':
emailType = 'eqa-manuscript-published'
email.content.subject = `${subjectBaseText} Decision`
break
case 'inQA':
emailType = 'eqa-manuscript-request-for-approval'
email.content.subject = `${subjectBaseText} Request for EQA Approval`
email.content.ctaLink = services.createUrl(
baseUrl,
config.get('eqa-decision.url'),
{
collectionId: collection.id,
customId: collection.customId,
token: collection.technicalChecks.token,
},
)
email.content.ctaText = 'MAKE DECISION'
break
default:
throw new Error(
`Cannot send EQA email when collection status is ${collection.status} `,
)
}
email.toUser = { email.toUser = {
email: editorialAssistantEmail, email: editorialAssistantEmail,
...@@ -428,20 +477,11 @@ const sendEQAEmail = ({ ...@@ -428,20 +477,11 @@ const sendEQAEmail = ({
email.content.unsubscribeLink = baseUrl email.content.unsubscribeLink = baseUrl
email.content.signatureName = eicName email.content.signatureName = eicName
email.content.subject = `${subjectBaseText} Request for EQA Approval`
email.content.ctaLink = services.createUrl(
baseUrl,
config.get('eqa-decision.url'),
{
collectionId: collection.id,
customId: collection.customId,
token: collection.technicalChecks.token,
},
)
email.content.ctaText = 'MAKE DECISION'
const { html, text } = email.getBody({ const { html, text } = email.getBody({
body: getEmailCopy({ body: getEmailCopy({
eicName,
titleText,
emailType, emailType,
customId: collection.customId, customId: collection.customId,
}), }),
......
...@@ -77,8 +77,8 @@ module.exports = models => async (req, res) => { ...@@ -77,8 +77,8 @@ module.exports = models => async (req, res) => {
} }
const technicalChecks = get(collection, 'technicalChecks', {}) const technicalChecks = get(collection, 'technicalChecks', {})
const { hasEQA } = technicalChecks const hasEQA = has(technicalChecks, 'eqa')
// the manuscript has not yet passed through the EQA process so we need to upload it to the FTP server
if (isEditorInChief && recommendation === 'publish' && !hasEQA) { if (isEditorInChief && recommendation === 'publish' && !hasEQA) {
const { journal, xmlParser, ftp } = mtsConfig const { journal, xmlParser, ftp } = mtsConfig
const MTS = new MTSService(journal, xmlParser, s3Config, ftp) const MTS = new MTSService(journal, xmlParser, s3Config, ftp)
...@@ -94,7 +94,7 @@ module.exports = models => async (req, res) => { ...@@ -94,7 +94,7 @@ module.exports = models => async (req, res) => {
collection.status = 'inQA' collection.status = 'inQA'
set(collection, 'technicalChecks.token', v4()) set(collection, 'technicalChecks.token', v4())
set(collection, 'technicalChecks.hasEQA', false) set(collection, 'technicalChecks.eqa', false)
await collection.save() await collection.save()
} }
...@@ -105,7 +105,7 @@ module.exports = models => async (req, res) => { ...@@ -105,7 +105,7 @@ module.exports = models => async (req, res) => {
if ( if (
isEditorInChief && isEditorInChief &&
recommendation === 'return-to-handling-editor' && recommendation === 'return-to-handling-editor' &&
has(collection.technicalChecks, 'hasEQA') hasEQA
) { ) {
collection.technicalChecks = {} collection.technicalChecks = {}
await collection.save() await collection.save()
......
...@@ -37,8 +37,8 @@ module.exports = ({ Collection, Fragment, User }) => async (req, res) => { ...@@ -37,8 +37,8 @@ module.exports = ({ Collection, Fragment, User }) => async (req, res) => {
} }
delete collection.technicalChecks.token delete collection.technicalChecks.token
if (step === TECHNICAL_STEPS.EQA) { if (step === TECHNICAL_STEPS.EQA && agree) {
collection.technicalChecks.hasEQA = true collection.technicalChecks.eqa = true
} }
collection.status = setNewStatus(step, agree) collection.status = setNewStatus(step, agree)
await collection.save() await collection.save()
......
...@@ -14,7 +14,7 @@ jest.mock('@pubsweet/component-send-email', () => ({ ...@@ -14,7 +14,7 @@ jest.mock('@pubsweet/component-send-email', () => ({
jest.mock('pubsweet-component-mts-package') jest.mock('pubsweet-component-mts-package')
const reqBody = { const reqBody = {
recommendation: 'accept', recommendation: 'publish',
comments: [ comments: [
{ {
content: chance.paragraph(), content: chance.paragraph(),
...@@ -262,8 +262,8 @@ describe('Post fragments recommendations route handler', () => { ...@@ -262,8 +262,8 @@ describe('Post fragments recommendations route handler', () => {
const data = JSON.parse(res._getData()) const data = JSON.parse(res._getData())
expect(collection.status).toBe('inQA') expect(collection.status).toBe('inQA')
expect(collection.technicalChecks).toHaveProperty('hasEQA') expect(collection.technicalChecks).toHaveProperty('eqa')
expect(collection.technicalChecks.hasEQA).toBeFalsy() expect(collection.technicalChecks.eqa).toBeFalsy()
expect(data.userId).toEqual(editorInChief.id) expect(data.userId).toEqual(editorInChief.id)
expect(data.recommendation).toBe('publish') expect(data.recommendation).toBe('publish')
}) })
...@@ -274,7 +274,7 @@ describe('Post fragments recommendations route handler', () => { ...@@ -274,7 +274,7 @@ describe('Post fragments recommendations route handler', () => {
body.recommendation = 'publish' body.recommendation = 'publish'
body.recommendationType = 'editorRecommendation' body.recommendationType = 'editorRecommendation'
collection.technicalChecks.hasEQA = true collection.technicalChecks.eqa = true
const res = await requests.sendRequest({ const res = await requests.sendRequest({
body, body,
...@@ -308,7 +308,7 @@ describe('Post fragments recommendations route handler', () => { ...@@ -308,7 +308,7 @@ describe('Post fragments recommendations route handler', () => {
delete fragment.invitations delete fragment.invitations
delete collection.invitations delete collection.invitations
delete collection.handlingEditor delete collection.handlingEditor
collection.technicalChecks.hasEQA = false collection.technicalChecks.eqa = false
const res = await requests.sendRequest({ const res = await requests.sendRequest({
body, body,
...@@ -327,7 +327,7 @@ describe('Post fragments recommendations route handler', () => { ...@@ -327,7 +327,7 @@ describe('Post fragments recommendations route handler', () => {
expect(collection.status).toBe('reviewCompleted') expect(collection.status).toBe('reviewCompleted')
expect(collection.technicalChecks).not.toHaveProperty('token') expect(collection.technicalChecks).not.toHaveProperty('token')
expect(collection.technicalChecks).not.toHaveProperty('hasEQA') expect(collection.technicalChecks).not.toHaveProperty('eqa')
expect(data.userId).toEqual(editorInChief.id) expect(data.userId).toEqual(editorInChief.id)
expect(data.recommendation).toBe('return-to-handling-editor') expect(data.recommendation).toBe('return-to-handling-editor')
......
...@@ -13,7 +13,7 @@ module.exports = { ...@@ -13,7 +13,7 @@ module.exports = {
handlingEditor: Joi.object(), handlingEditor: Joi.object(),
technicalChecks: Joi.object({ technicalChecks: Joi.object({
token: Joi.string(), token: Joi.string(),
hasEQA: Joi.boolean(), eqa: Joi.boolean(),
}), }),
}, },
fragment: [ fragment: [
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment