Skip to content
Snippets Groups Projects
Commit 3dea23d9 authored by Audrey Hamelers's avatar Audrey Hamelers
Browse files

#1233 email grant PIs

parent a50e8a0d
No related branches found
No related tags found
1 merge request!414release version 4.2.0
......@@ -3,10 +3,8 @@ import { Mutation } from 'react-apollo'
import styled from 'styled-components'
import { th, darken } from '@pubsweet/ui-toolkit'
import { Button, H3, Icon, RadioGroup, Action } from '@pubsweet/ui'
import { states } from 'config'
import { Buttons } from '../ui'
import GrantSearch from '../grant-search'
import { ALERT_PIS } from '../operations'
import { EXCEPTION_ALERT, QUERY_ACTIVITY_INFO } from './operations'
import { NoteMutations, WithFunders } from '../SubmissionMutations'
......@@ -64,8 +62,6 @@ class GrantsEdit extends React.Component {
const { close, fundingGroup, manuscript } = this.props
const { notes } = manuscript.meta
const planS = notes && notes.find(n => n.notesType === 'planS')
const noPIEmails =
states.indexOf(manuscript.status) < states.indexOf('tagging')
return (
<React.Fragment>
<GrantSearch
......@@ -135,85 +131,56 @@ class GrantsEdit extends React.Component {
},
]}
>
{(epmc_emailException, { data: data1 }) => (
<Mutation mutation={ALERT_PIS}>
{(epmc_emailGrantPis, { data: data2 }) => {
const checkException = async () => {
const checkArray = ['newNote', 'deleteNote', 'updateGrants']
await checkArray.reduce(async (promise, func) => {
await promise
const funcVal = this.state[func]
if (funcVal) {
return this.props[func](funcVal)
}
return Promise.resolve()
}, Promise.resolve())
const { isPlanS, selectedLicense } = this.state
const { notes } = this.props.manuscript.meta
const planS =
notes && notes.find(n => n.notesType === 'planS')
if (isPlanS && planS) {
const changeLicense =
(selectedLicense && !planS.content) ||
(planS.content && planS.content !== selectedLicense)
if (changeLicense) {
await this.props.changeNote({
id: planS.id,
notesType: 'planS',
content: selectedLicense,
})
if (selectedLicense) {
await epmc_emailException({
variables: {
manuscriptId: manuscript.id,
license: selectedLicense,
},
})
}
}
}
{(epmc_emailException, { data }) => {
const checkException = async () => {
const checkArray = ['newNote', 'deleteNote', 'updateGrants']
await checkArray.reduce(async (promise, func) => {
await promise
const funcVal = this.state[func]
if (funcVal) {
return this.props[func](funcVal)
}
const sendAlert = async () => {
const { originalData, updateGrants } = this.state
const newGrants = updateGrants.filter(
p =>
!originalData.some(
o =>
o.awardId === p.awardId &&
o.fundingSource === p.fundingSource &&
o.pi.surname === p.pi.surname,
),
)
await checkException()
await epmc_emailGrantPis({
variables: { manuscriptId: manuscript.id, newGrants },
return Promise.resolve()
}, Promise.resolve())
const { isPlanS, selectedLicense } = this.state
const { notes } = this.props.manuscript.meta
const planS = notes && notes.find(n => n.notesType === 'planS')
if (isPlanS && planS) {
const changeLicense =
(selectedLicense && !planS.content) ||
(planS.content && planS.content !== selectedLicense)
if (changeLicense) {
await this.props.changeNote({
id: planS.id,
notesType: 'planS',
content: selectedLicense,
})
close()
if (selectedLicense) {
await epmc_emailException({
variables: {
manuscriptId: manuscript.id,
license: selectedLicense,
},
})
}
}
return (
<Buttons right>
<Button
onClick={async () => {
await checkException()
close()
}}
primary
>
Save &amp; close
</Button>
<Button
disabled={noPIEmails}
onClick={() => sendAlert()}
primary
>
Save &amp; send PI emails
</Button>
</Buttons>
)
}}
</Mutation>
)}
}
}
return (
<Buttons right>
<Button
onClick={async () => {
await checkException()
close()
}}
primary
>
Save &amp; close
</Button>
</Buttons>
)
}}
</Mutation>
</React.Fragment>
)
......
......@@ -201,12 +201,6 @@ export const UPDATE_NOTE = gql`
}
`
export const ALERT_PIS = gql`
mutation EmailGrantPis($manuscriptId: ID!, $newGrants: [FundingGroupInput]) {
epmc_emailGrantPis(manuscriptId: $manuscriptId, newGrants: $newGrants)
}
`
export const GET_PREPRINT_SELECTIONS = gql`
query($id: ID!) {
getPreprintSelections(manuscriptId: $id) {
......
......@@ -4,7 +4,6 @@ import { withRouter } from 'react-router'
import { europepmcUrl } from 'config'
import { Button, CheckboxGroup, Icon } from '@pubsweet/ui'
import { A, Portal, Buttons, Fieldset } from '../ui'
import { ALERT_PIS } from '../operations'
import { SUBMIT_MANUSCRIPT } from './operations'
const SubmitApprove = ({
......@@ -69,25 +68,13 @@ const SubmitApprove = ({
(preprint && adminButton === 'review')
) {
return (
<Mutation mutation={ALERT_PIS}>
{(epmc_emailGrantPis, { data }) => {
const sendAlert = async () => {
await epmc_emailGrantPis({ variables: { manuscriptId } })
}
return (
<Button
disabled={disabled}
onClick={() => {
sendAlert()
submit('tagging')
}}
primary
>
Approve for tagging
</Button>
)
}}
</Mutation>
<Button
disabled={disabled}
onClick={() => submit('tagging')}
primary
>
Approve for tagging
</Button>
)
}
if (adminButton === 'review') {
......
const logger = require('@pubsweet/logger')
const { checkJobStatus, uncaughtError } = require('../job-runner')
const Manuscript = require('../xpub-model/entities/manuscript/data-access')
const {
gManuscript,
} = require('../xpub-model/entities/manuscript/helpers/transform')
const { transaction } = require('objection')
const { errorDevEmail } = require('../email')
const { createGrantLinks } = require('./linkGrants')
......@@ -51,10 +48,12 @@ async function grantLinkCheck() {
const linkingManuscripts = await Manuscript.query()
.where('fundingState', 'Linking grants')
.whereNull('manuscript.deleted')
.eager('teams.users.identities')
.modifyEager('teams', builder => {
builder.whereNull('deleted')
})
if (linkingManuscripts.length > 0) {
const grantLinkDone = await createGrantLinks(
linkingManuscripts.map(manuscript => gManuscript(manuscript)),
)
const grantLinkDone = await createGrantLinks(linkingManuscripts)
if (!grantLinkDone.success) {
throw new Error(grantLinkDone.message)
}
......
......@@ -3,10 +3,12 @@ const logger = require('@pubsweet/logger')
const moment = require('moment')
const Client = require('ftp')
const { Readable } = require('stream')
const { grantEmail } = require('../email')
module.exports.createGrantLinks = async function createGrantLinks(
manuscripts,
removeFundingGroup,
addFundingGroup,
) {
try {
const filename = `grants${
......@@ -14,14 +16,14 @@ module.exports.createGrantLinks = async function createGrantLinks(
}.${moment().format('YYYY_MM_DD-HH_mm_SS')}.xml`
const sendManuscripts = manuscripts.reduce((list, manuscript) => {
const articleIds =
manuscript.meta.articleIds &&
manuscript.meta.articleIds
manuscript['meta,article_ids'] &&
manuscript['meta,article_ids']
.filter(a => ['pmcid', 'pmid'].includes(a.pubIdType))
.sort((a, b) => (a.pubIdType > b.pubIdType ? 1 : -1))
const fundingGroup =
(manuscript.meta.fundingGroup &&
manuscript.meta.fundingGroup.length > 0 &&
manuscript.meta.fundingGroup) ||
(manuscript['meta,funding_group'] &&
manuscript['meta,funding_group'].length > 0 &&
manuscript['meta,funding_group']) ||
undefined
if (
articleIds &&
......@@ -29,10 +31,9 @@ module.exports.createGrantLinks = async function createGrantLinks(
(fundingGroup || removeFundingGroup)
) {
list.push({
id: manuscript.id,
manuscript,
articleIds,
fundingGroup,
removeFundingGroup,
})
} else {
logger.info(`${manuscript.id} No grants to link or no ID to link to`)
......@@ -47,9 +48,10 @@ module.exports.createGrantLinks = async function createGrantLinks(
const grantList = await createGrantXML(
each.articleIds,
each.fundingGroup,
each.removeFundingGroup,
removeFundingGroup,
)
logger.info(`${each.id} Grant list created`)
logger.info(`${each.manuscript.id} Grant list created`)
emailGrantPis(each.manuscript, addFundingGroup || each.fundingGroup)
return grantList
}),
)
......@@ -114,3 +116,43 @@ function sendXML(contents, filename) {
ftp.connect({ host, user, password })
})
}
async function emailGrantPis(manuscript, grantList) {
const { teams, id } = manuscript
const releaseDelay = manuscript['meta,release_delay']
const title = manuscript['meta,title']
const fundingGroup = manuscript['meta,funding_group']
const emails = teams.map(t => t.users[0].identities[0].email)
const { teamMembers: rTeam } = teams.find(t => t.role === 'reviewer') || {}
const [reviewer] = rTeam || []
if (!fundingGroup || fundingGroup.length === 0) return true
if (fundingGroup.some(g => emails.includes(g.pi.email))) return true
const piList = grantList.reduce((pis, curr) => {
const exists = pis.findIndex(p => p.pi.email === curr.pi.email)
const award = {
awardId: curr.awardId,
fundingSource: curr.fundingSource,
title: curr.title,
}
if (exists > -1) {
pis[exists].awards.push(award)
} else {
pis.push({
pi: curr.pi,
awards: [award],
})
}
return pis
}, [])
const manInfo = {
id,
title,
releaseDelay,
}
const reviewerName = reviewer && reviewer.alias.name
await Promise.all(
piList.map(async li => grantEmail(li.pi, li.awards, manInfo, reviewerName)),
)
return true
}
......@@ -57,7 +57,7 @@ const grantCheck = (origMan, changeMan) => {
),
)
if (added.length > 0 || removed.length > 0) {
return { send: true, removeGroup: removed }
return { send: true, added, removed }
}
}
}
......@@ -376,13 +376,13 @@ const Manuscript = {
const teams = await TeamAccess.selectByManuscriptId(id)
const subTeam = teams.find(t => t.roleName === 'submitter')
if (userId === subTeam.userId) {
const submitter = await UserAccess.findById(subTeam.userId)
const [submitter] = subTeam.users
const emails = submitter ? [submitter.identities[0].email] : []
const manInfo = { id, title: manuscript['meta,title'] }
const revTeam = teams.find(t => t.roleName === 'reviewer')
let reviewer = null
if (revTeam && revTeam.userId !== subTeam.userId) {
reviewer = await UserAccess.findById(revTeam.userId)
;[reviewer] = revTeam.user
if (reviewer) {
emails.push(reviewer.identities[0].email)
}
......@@ -526,7 +526,7 @@ const Manuscript = {
const emailTeam =
teams.find(t => t.roleName === 'reviewer') ||
teams.find(t => t.roleName === 'submitter')
const emailPerson = await UserAccess.findById(emailTeam.userId)
const [emailPerson] = emailTeam.users
await alreadyCompleteEmail(emailPerson, manuscript)
return {
success: true,
......@@ -556,8 +556,8 @@ const Manuscript = {
const teams = await TeamAccess.selectByManuscriptId(input.manuscriptId)
const subTeam = teams.find(t => t.roleName === 'submitter')
const revTeam = teams.find(t => t.roleName === 'reviewer')
const submitter = await UserAccess.findById(subTeam.userId)
const reviewer = await UserAccess.findById(revTeam.userId)
const [submitter] = subTeam.users
const [reviewer] = revTeam.users
const email = JSON.parse(input.content)
const errors = []
try {
......@@ -615,11 +615,11 @@ const Manuscript = {
replace: async (keepId, throwId, userId) => {
const keepMan = await ManuscriptAccess.selectById(keepId)
const throwMan = await ManuscriptAccess.selectById(throwId, true)
const emailId =
(throwMan.teams.find(t => t.roleName === 'reviewer') &&
throwMan.teams.find(t => t.roleName === 'reviewer').users[0].id) ||
throwMan.teams.find(t => t.roleName === 'submitter').users[0].id
const user = await UserAccess.findById(emailId)
const teams = await TeamAccess.selectByManuscriptId(throwId)
const emailTeam =
teams.find(t => t.roleName === 'reviewer') ||
teams.find(t => t.roleName === 'submitter')
const [user] = emailTeam.users
const keepFunds = keepMan['meta,fundingGroup'] || []
const throwFunds = throwMan['meta,fundingGroup'] || []
const newFunds = keepFunds.concat(
......@@ -641,12 +641,13 @@ const Manuscript = {
'meta,fundingGroup': newFunds,
updatedBy: userId,
}
const { send, removeGroup } = await grantCheck(keepMan, input)
const { send, added, removed } = await grantCheck(keepMan, input)
lodash.assign(keepMan, input)
try {
await keepMan.save()
if (send) {
await createGrantLinks([gManuscript(keepMan)], removeGroup)
keepMan.teams = await TeamAccess.selectByManuscriptId(keepId)
await createGrantLinks([keepMan], removed, added)
}
await ManuscriptAccess.delete(throwId, userId)
await removeDuplicateEmail(user, throwMan, keepMan)
......@@ -1021,7 +1022,7 @@ const Manuscript = {
}
}
const manuscriptUpdate = dManuscriptUpdate(input, userId)
const { send, removeGroup } = await grantCheck(
const { send, added, removed } = await grantCheck(
originalMan,
manuscriptUpdate,
)
......@@ -1030,7 +1031,8 @@ const Manuscript = {
const updatedMan = await ManuscriptAccess.selectById(input.id, true, trx)
const manuscript = gManuscript(updatedMan)
if (send) {
await createGrantLinks([manuscript], removeGroup)
updatedMan.teams = await TeamAccess.selectByManuscriptId(input.id)
await createGrantLinks([updatedMan], removed, added)
}
if (commit) {
await trx.commit()
......
......@@ -87,6 +87,7 @@ class Team extends EpmcBaseModel {
static async selectByManuscriptId(manId, trx) {
const manuscriptRoles = await Team.query(trx)
.eager('users.identities')
.where({
'team.manuscript_id': manId,
})
......
......@@ -2,9 +2,7 @@ const rfr = require('rfr')
const logger = require('@pubsweet/logger')
const authentication = require('../user/authentication')
const { userMessage, resetPassword, grantEmail, licenseEmail } = rfr(
'server/email',
)
const { userMessage, resetPassword, licenseEmail } = rfr('server/email')
const {
ManuscriptManager,
UserManager,
......@@ -65,58 +63,6 @@ const resolvers = {
await NoteManager.create(note, user)
return true
},
async epmc_emailGrantPis(_, { manuscriptId, newGrants = null }, { user }) {
const manuscript = await ManuscriptManager.findById(manuscriptId, user)
const { meta, teams } = manuscript
const { fundingGroup, releaseDelay, title } = meta
if (!fundingGroup) return true
const { teamMembers: sTeam } =
teams.find(team => team.role === 'submitter') || {}
const [submitter] = sTeam || []
const sEmail =
submitter && (await UserManager.findEmail(submitter.user.id))
const { teamMembers: rTeam } =
teams.find(team => team.role === 'reviewer') || {}
const [reviewer] = rTeam || []
const rEmail = reviewer && (await UserManager.findEmail(reviewer.user.id))
if (
sEmail &&
rEmail &&
fundingGroup.some(g => [rEmail, sEmail].includes(g.pi.email))
) {
return true
}
const grantList = newGrants || fundingGroup
const piList = grantList.reduce((pis, curr) => {
const exists = pis.findIndex(p => p.pi.email === curr.pi.email)
const award = {
awardId: curr.awardId,
fundingSource: curr.fundingSource,
title: curr.title,
}
if (exists > -1) {
pis[exists].awards.push(award)
} else {
pis.push({
pi: curr.pi,
awards: [award],
})
}
return pis
}, [])
const manInfo = {
id: manuscriptId,
title,
releaseDelay,
}
const reviewerName = reviewer && reviewer.alias.name
await Promise.all(
piList.map(async li =>
grantEmail(li.pi, li.awards, manInfo, reviewerName),
),
)
return true
},
async epmc_emailException(_, { manuscriptId, license: l }, { user }) {
const manuscript = await ManuscriptManager.findById(manuscriptId, user)
const { meta, teams, status, version } = manuscript
......
......@@ -5,9 +5,6 @@ extend type Mutation {
# Send email to reset password
epmc_emailPasswordResetLink(email: String!): Boolean!
# Check and send email to grant PIs
epmc_emailGrantPis(manuscriptId: ID!, newGrants: [FundingGroupInput]): Boolean!
# Send email to confirm license exception
epmc_emailException(manuscriptId: ID!, license: String): Boolean!
}
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