Newer
Older

Sebastian Mihalache
committed
const config = require('config')
const { v4 } = require('uuid')
const logger = require('@pubsweet/logger')

Sebastian Mihalache
committed
const {
findLast,
isEmpty,
maxBy,
get,
flatMap,
last,
has,
set,
} = require('lodash')
Andrei Cioromila
committed
const Fragment = require('./Fragment')

Mihail Hagiu
committed
class Collection {
constructor({ collection = {} }) {
this.collection = collection
}
async updateStatusByRecommendation({
recommendation,
isHandlingEditor = false,
Andrei Cioromila
committed
fragments,
}) {
let newStatus
if (isHandlingEditor) {
newStatus = 'pendingApproval'
if (['minor', 'major'].includes(recommendation)) {
newStatus = 'revisionRequested'
}
} else {
if (recommendation === 'minor') {
Andrei Cioromila
committed
newStatus = this.hasAtLeastOneReviewReport(fragments)
? 'reviewCompleted'
: 'heAssigned'
if (recommendation === 'major') {
}
}
return this.updateStatus({ newStatus })
}
async updateStatus({ newStatus }) {
this.collection.status = newStatus
await this.collection.save()
}
async addHandlingEditor({ user, invitation }) {
this.collection.handlingEditor = {
id: user.id,
name: `${user.firstName} ${user.lastName}`,
invitedOn: invitation.invitedOn,
respondedOn: invitation.respondedOn,
email: user.email,
hasAnswer: invitation.hasAnswer,
isAccepted: invitation.isAccepted,
}
await this.updateStatus({ newStatus: 'heInvited' })
}
async updateHandlingEditor({ isAccepted }) {
const { collection: { handlingEditor } } = this
handlingEditor.hasAnswer = true
handlingEditor.isAccepted = isAccepted
handlingEditor.respondedOn = Date.now()
const newStatus = isAccepted ? 'heAssigned' : 'submitted'
await this.updateStatus({ newStatus })
async updateStatusByNumberOfReviewers({ invitations }) {
const reviewerInvitations = invitations.filter(
inv => inv.role === 'reviewer',
)
if (reviewerInvitations.length === 0)
await this.updateStatus({ newStatus: 'heAssigned' })
}
Sebastian Mihalache
committed
getHELastName() {
Sebastian Mihalache
committed
const [firstName, lastName] = this.collection.handlingEditor.name.split(' ')
return lastName || firstName
Sebastian Mihalache
committed
}

Mihail Hagiu
committed
Andrei Cioromila
committed
async getReviewerNumber({ userId }) {
const allCollectionFragments = await this.collection.getFragments()
const allCollectionInvitations = flatMap(
allCollectionFragments,
fragment => fragment.invitations,

Tania Fecheta
committed
).filter(Boolean)
const allNumberedInvitationsForUser = allCollectionInvitations

Mihail Hagiu
committed
.filter(invite => invite.userId === userId)

Mihail Hagiu
committed
.filter(invite => invite.reviewerNumber)
if (isEmpty(allNumberedInvitationsForUser)) {
const maxReviewerNumber = get(
maxBy(allCollectionInvitations, 'reviewerNumber'),
'reviewerNumber',
0,
)
return maxReviewerNumber + 1
}

Mihail Hagiu
committed
return allNumberedInvitationsForUser[0].reviewerNumber
}
Andrei Cioromila
committed
// eslint-disable-next-line class-methods-use-this
hasAtLeastOneReviewReport(fragments) {
return fragments.some(fragment =>
new Fragment({ fragment }).hasReviewReport(),
)
}
canHEMakeRecommendation(fragments, fragmentHelper) {
if (this.collection.fragments.length === 1) {
return fragmentHelper.hasReviewReport()
}
const previousVersionRecommendations = get(
fragments[fragments.length - 2],
'recommendations',
[],
)

Sebastian Mihalache
committed
const lastEditorRecommendation = findLast(
Andrei Cioromila
committed
previousVersionRecommendations,
recommendation =>
recommendation.recommendationType === 'editorRecommendation',
)

Sebastian Mihalache
committed
if (lastEditorRecommendation.recommendation === 'minor') {
Andrei Cioromila
committed
return this.hasAtLeastOneReviewReport(fragments)

Tania Fecheta
committed
} else if (
['major', 'revision'].includes(lastEditorRecommendation.recommendation)
) {
Andrei Cioromila
committed
return fragmentHelper.hasReviewReport()
}

Sebastian Mihalache
committed
return false
Andrei Cioromila
committed
}
Andrei Cioromila
committed
async getAllFragments({ FragmentModel }) {
return Promise.all(
this.collection.fragments.map(async fragment =>
FragmentModel.find(fragment),
),
)
}

Sebastian Mihalache
committed
isLatestVersion(fragmentId) {
return last(this.collection.fragments) === fragmentId
}
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
hasEQA() {
const technicalChecks = get(this.collection, 'technicalChecks', {})
return has(technicalChecks, 'eqa')
}
async setTechnicalChecks() {
set(this.collection, 'technicalChecks.token', v4())
set(this.collection, 'technicalChecks.eqa', false)
await this.collection.save()
}
async sendToMTS({ FragmentModel, UserModel, fragmentHelper }) {
await Promise.all(
this.collection.fragments.map(async fragmentId => {
const fragment = await FragmentModel.find(fragmentId)
let fragmentUsers = []
try {
fragmentUsers = await fragmentHelper.getReviewersAndEditorsData({
collection: this.collection,
UserModel,
})
await sendMTSPackage({
collection: this.collection,
fragment,
isEQA: true,
fragmentUsers,
})
} catch (e) {
logger.error(e)
}
}),
).catch(e => {
throw new Error('Something went wrong.')
})
}
async removeTechnicalChecks() {
this.collection.technicalChecks = {}
await this.collection.save()
}
hasHandlingEditor() {
return has(this.collection, 'handlingEditor')
}
async addFragment(newFragmentId) {
this.collection.fragments.push(newFragmentId)
await this.collection.save()
}
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
}
const sendMTSPackage = async ({
fragment,
collection,
isEQA = false,
fragmentUsers = [],
}) => {
const s3Config = get(config, 'pubsweet-component-aws-s3', {})
const mtsConfig = get(config, 'mts-service', {})
const { sendPackage } = require('pubsweet-component-mts-package')
const { journal, xmlParser, ftp } = mtsConfig
const packageFragment = {
...fragment,
metadata: {
...fragment.metadata,
customId: collection.customId,
},
}
await sendPackage({
isEQA,
s3Config,
fragmentUsers,
ftpConfig: ftp,
config: journal,
options: xmlParser,
fragment: packageFragment,
})
}
module.exports = Collection