const { flatten, isEmpty, maxBy, get } = require('lodash') class Collection { constructor({ collection = {} }) { this.collection = collection } async updateStatusByRecommendation({ recommendation, isHandlingEditor = false, }) { let newStatus if (isHandlingEditor) { newStatus = 'pendingApproval' if (['minor', 'major'].includes(recommendation)) { newStatus = 'revisionRequested' } } else { if (recommendation === 'minor') { newStatus = 'reviewCompleted' } if (recommendation === 'major') { newStatus = 'underReview' } } this.updateStatus({ newStatus }) } async updateFinalStatusByRecommendation({ recommendation }) { let newStatus switch (recommendation) { case 'reject': newStatus = 'rejected' break case 'publish': newStatus = 'accepted' break case 'return-to-handling-editor': newStatus = 'reviewCompleted' break default: break } await 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' }) } async updateStatusOnRecommendation({ isEditorInChief, recommendation }) { if (isEditorInChief) { if (recommendation === 'return-to-handling-editor') { this.updateStatus({ newStatus: 'reviewCompleted' }) } else { this.updateFinalStatusByRecommendation({ recommendation, }) } } else { this.updateStatusByRecommendation({ recommendation, isHandlingEditor: true, }) } } getHELastName() { const [firstName, lastName] = this.collection.handlingEditor.name.split(' ') return lastName || firstName } async getAllCollectionFragments({ FragmentModel }) { const allCollectionFragments = await Promise.all( get(this.collection, 'fragments', []).map(async fragmentId => { const fragment = await FragmentModel.find(fragmentId) return fragment }), ) return allCollectionFragments } async getReviewerNumber({ userId, FragmentModel }) { const allCollectionFragments = await this.getAllCollectionFragments({ FragmentModel, }) const allCollectionInvitations = flatten( allCollectionFragments.map(fragment => fragment.invitations), ) const allNumberedInvitationsForUser = allCollectionInvitations .filter(invite => invite.userId === userId) .filter(invite => invite.reviewerNumber) if (isEmpty(allNumberedInvitationsForUser)) { const maxReviewerNumber = get( maxBy(allCollectionInvitations, 'reviewerNumber'), 'reviewerNumber', 0, ) return maxReviewerNumber + 1 } return allNumberedInvitationsForUser[0].reviewerNumber } } module.exports = Collection