diff --git a/submissions/forms.py b/submissions/forms.py index 8d8fa809847e1fb5fc2c33f1cd4d056af1824a57..3e6db3bf30eacf7946c466a7ca85e65643ae811e 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -13,7 +13,7 @@ from .constants import ASSIGNMENT_BOOL, ASSIGNMENT_REFUSAL_REASONS, STATUS_RESUB POST_PUBLICATION_STATUSES, REPORT_POST_PUBLICATION, REPORT_NORMAL from . import exceptions, helpers from .models import Submission, RefereeInvitation, Report, EICRecommendation, EditorialAssignment,\ - iThenticateReport + iThenticateReport, EditorialCommunication from colleges.models import Fellowship from journals.constants import SCIPOST_JOURNAL_PHYSICS_PROC @@ -663,11 +663,24 @@ class VetReportForm(forms.Form): # Communications # ################### -class EditorialCommunicationForm(forms.Form): - text = forms.CharField(widget=forms.Textarea(), label='') +class EditorialCommunicationForm(forms.ModelForm): + class Meta: + model = EditorialCommunication + fields = ('text',) +# class EditorialCommunication(SubmissionRelatedObjectMixin, models.Model): +# """ +# Each individual communication between Editor-in-charge +# to and from Referees and Authors becomes an instance of this class. +# """ +# submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE) +# referee = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE, +# blank=True, null=True) +# comtype = models.CharField(max_length=4, choices=ED_COMM_CHOICES) +# timestamp = models.DateTimeField(default=timezone.now) +# text = models.TextField() def __init__(self, *args, **kwargs): - super(EditorialCommunicationForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields['text'].widget.attrs.update( {'rows': 5, 'cols': 50, 'placeholder': 'Write your message in this box.'}) diff --git a/submissions/managers.py b/submissions/managers.py index 20b455d39e4a976872434f2fe05a23abdd23c572..d74e9cc560e9b65e4ae85f9a99f2222357de4b92 100644 --- a/submissions/managers.py +++ b/submissions/managers.py @@ -112,6 +112,14 @@ class SubmissionQuerySet(models.QuerySet): qs = qs.filter(editor_in_charge=user.contributor) return qs + def filter_for_author(self, user): + """ + Return the set of Submissions for which the user is a registered author. + """ + if not hasattr(user, 'contributor'): + return self.none() + return self.filter(authors=user.contributor) + def prescreening(self): """ Return submissions just coming in and going through pre-screening. diff --git a/submissions/views.py b/submissions/views.py index 21a0dbbe5e99f518a3805c3b5a41171538285151..156b791599aa39f691a36a8a07e302e221c4b449 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -4,6 +4,7 @@ import feedparser from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.models import Group +from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse, reverse_lazy from django.db import transaction, IntegrityError from django.http import Http404, HttpResponse, HttpResponseRedirect @@ -1105,57 +1106,60 @@ def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None): occurring during the submission refereeing. """ referee = None - if comtype == 'AtoE': - submissions_qs = Submission.objects.filter(authors__user=request.user) + if comtype in ['EtoA', 'EtoR', 'EtoS']: + # Editor to {Author, Referee, Editorial Administration} + submissions_qs = Submission.objects.filter_for_eic(request.user) + elif comtype == 'AtoE': + # Author to Editor + submissions_qs = Submission.objects.filter_for_author(request.user) + referee = request.user.contributor + elif comtype == 'RtoE': + # Referee to Editor (Contributor account required) + if not hasattr(request.user, 'contributor'): + # Raise PermissionDenied to let the user know something is wrong with its account. + raise PermissionDenied + + submissions_qs = Submission.objects.filter( + referee_invitations__referee__user=request.user) + referee = request.user.contributor + elif comtype == 'StoE': + # Editorial Administration to Editor + if not request.user.has_perm('scipost.can_oversee_refereeing'): + raise PermissionDenied + submissions_qs = Submission.objects.filter_for_author(request.user) + referee = request.user.contributor else: - submissions_qs = Submission.objects.pool_full(request.user) + # Invalid commtype in the url! + raise Http404 + + # Get the showpiece itself or return 404 submission = get_object_or_404(submissions_qs, arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) - errormessage = None - if comtype not in dict(ED_COMM_CHOICES).keys(): - errormessage = 'Unknown type of cummunication.' - # TODO: Verify that this is requested by an authorized contributor (eic, ref, author) - elif (comtype in ['EtoA', 'EtoR', 'EtoS'] and - submission.editor_in_charge != request.user.contributor): - errormessage = 'Only the Editor-in-charge can perform this action.' - elif (comtype in ['AtoE'] and - not (request.user.contributor == submission.submitted_by)): - errormessage = 'Only the corresponding author can perform this action.' - elif (comtype in ['RtoE'] and - not (RefereeInvitation.objects - .filter(submission=submission, referee=request.user.contributor).exists())): - errormessage = 'Only invited referees for this Submission can perform this action.' - elif (comtype in ['StoE'] and - not request.user.groups.filter(name='Editorial Administrators').exists()): - errormessage = 'Only Editorial Administrators can perform this action.' - if errormessage is not None: - messages.warning(request, errormessage) - return redirect(reverse('submissions:pool')) + + if referee_id and not referee: + # Get the Contributor to communicate with if not already defined (`Eto?` communication) + # To Fix: Assuming the Editorial Administrator won't make any `referee_id` mistakes + referee = get_object_or_404(Contributor, pk=referee_id) form = EditorialCommunicationForm(request.POST or None) if form.is_valid(): - communication = EditorialCommunication(submission=submission, - comtype=comtype, - timestamp=timezone.now(), - text=form.cleaned_data['text']) - if referee_id is not None: - referee = get_object_or_404(Contributor, pk=referee_id) - communication.referee = referee - - if comtype == 'RtoE': - communication.referee = request.user.contributor + communication = form.save(commit=False) + communication.submission = submission + communication.comtype = comtype + communication.referee = referee communication.save() + SubmissionUtils.load({'communication': communication}) SubmissionUtils.send_communication_email() - if comtype == 'EtoA' or comtype == 'EtoR' or comtype == 'EtoS': + + if comtype in ['EtoA', 'EtoR', 'EtoS']: return redirect(reverse('submissions:editorial_page', kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) elif comtype == 'AtoE': return redirect(reverse('scipost:personal_page')) - elif comtype == 'RtoE': - return redirect(submission.get_absolute_url()) elif comtype == 'StoE': return redirect(reverse('submissions:pool')) + return redirect(submission.get_absolute_url()) context = { 'submission': submission,