From 3debb84b1e70f63b9af295c48775712a29586125 Mon Sep 17 00:00:00 2001 From: Jorran de Wit <jorrandewit@outlook.com> Date: Tue, 23 Jan 2018 23:57:37 +0100 Subject: [PATCH] Reformulate EICRecommendation v1 --- submissions/admin.py | 1 + submissions/forms.py | 101 +++++++++++++-- submissions/managers.py | 3 + .../migrations/0005_auto_20180123_2312.py | 28 +++++ .../0006_eicrecommendation_active.py | 20 +++ submissions/models.py | 34 ++--- .../_recommendation_author_content.html | 2 +- .../templates/submissions/editorial_page.html | 26 ++-- .../recommendation_formulate_rewrite.html | 68 ++++++++++ submissions/urls.py | 23 ++-- submissions/views.py | 116 ++++++++++-------- 11 files changed, 330 insertions(+), 92 deletions(-) create mode 100644 submissions/migrations/0005_auto_20180123_2312.py create mode 100644 submissions/migrations/0006_eicrecommendation_active.py create mode 100644 submissions/templates/submissions/pool/recommendation_formulate_rewrite.html diff --git a/submissions/admin.py b/submissions/admin.py index 0466fba0c..c052e6718 100644 --- a/submissions/admin.py +++ b/submissions/admin.py @@ -233,6 +233,7 @@ class EICRecommendationAdminForm(forms.ModelForm): class EICRecommendationAdmin(admin.ModelAdmin): search_fields = ['submission__title'] + list_display = (submission_short_title, 'recommendation', 'active', 'version') form = EICRecommendationAdminForm diff --git a/submissions/forms.py b/submissions/forms.py index 4e3ce90c7..64da2d530 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -1,3 +1,4 @@ +import datetime import re from django import forms @@ -681,6 +682,10 @@ class EditorialCommunicationForm(forms.ModelForm): ###################### class EICRecommendationForm(forms.ModelForm): + DAYS_TO_VOTE = 7 + assignment = None + earlier_recommendations = None + class Meta: model = EICRecommendation fields = [ @@ -689,17 +694,97 @@ class EICRecommendationForm(forms.ModelForm): 'requested_changes', 'remarks_for_editorial_college' ] + widgets = { + 'remarks_for_authors': forms.Textarea({ + 'placeholder': 'Your general remarks for the authors', + 'rows': 10, + }), + 'requested_changes': forms.Textarea({ + 'placeholder': ('If you request revisions, give a numbered (1-, 2-, ...)' + ' list of specifically requested changes'), + }), + 'remarks_for_editorial_college': forms.Textarea({ + 'placeholder': ('If you recommend to accept or refuse, the Editorial College ' + 'will vote; write any relevant remarks for the EC here.'), + }), + } def __init__(self, *args, **kwargs): + self.submission = kwargs.pop('submission') + self.reformulate = kwargs.pop('reformulate', False) + if self.reformulate: + self.load_earlier_recommendations() + latest_recommendation = self.earlier_recommendations.first() + if latest_recommendation: + kwargs['initial'] = { + 'recommendation': latest_recommendation.recommendation, + 'remarks_for_authors': latest_recommendation.remarks_for_authors, + 'requested_changes': latest_recommendation.requested_changes, + 'remarks_for_editorial_college': + latest_recommendation.remarks_for_editorial_college, + } + super().__init__(*args, **kwargs) - self.fields['remarks_for_authors'].widget.attrs.update( - {'placeholder': 'Your general remarks for the authors', - 'rows': 10, 'cols': 100}) - self.fields['requested_changes'].widget.attrs.update( - {'placeholder': 'If you request revisions, give a numbered (1-, 2-, ...) list of specifically requested changes', - 'cols': 100}) - self.fields['remarks_for_editorial_college'].widget.attrs.update( - {'placeholder': 'If you recommend to accept or refuse, the Editorial College will vote; write any relevant remarks for the EC here.'}) + self.load_assignment() + + def save(self, commit=True): + recommendation = super().save(commit=False) + recommendation.submission = self.submission + recommendation.voting_deadline += datetime.timedelta(days=self.DAYS_TO_VOTE) # Test this + if self.reformulate: + # Increment version number + recommendation.version = len(self.earlier_recommendations) + 1 + event_text = 'The Editorial Recommendation has been reformulated: {}.' + else: + event_text = 'An Editorial Recommendation has been formulated: {}.' + + if recommendation.recommendation in [1, 2, 3, -3]: + # Accept/Reject: Forward to the Editorial College for voting + self.submission.status = 'voting_in_preparation' + + if commit: + # Add SubmissionEvent for EIC only + self.submission.add_event_for_eic(event_text.format( + recommendation.get_recommendation_display())) + elif recommendation.recommendation in [-1, -2]: + # Minor/Major revision: return to Author; ask to resubmit + self.submission.status = 'revision_requested' + self.submission.open_for_reporting = False + + if commit: + # Add SubmissionEvents for both Author and EIC + self.submission.add_general_event(event_text.format( + recommendation.get_recommendation_display())) + + if commit: + if self.earlier_recommendations: + self.earlier_recommendations.update(active=False) + + recommendation.save() + self.submission.save() + + if self.assignment: + # The EIC has fulfilled this editorial assignment. + self.assignment.completed = True + self.assignment.save() + + def revision_requested(self): + return self.instance.recommendation in [-1, -2] + + def has_assignment(self): + return self.assignment is not None + + def load_assignment(self): + # Find EditorialAssignment for Submission + try: + self.assignment = self.submission.editorial_assignments.accepted().get( + to=self.submission.editor_in_charge) + return True + except EditorialAssignment.DoesNotExist: + return False + + def load_earlier_recommendations(self): + self.earlier_recommendations = self.submission.eicrecommendations.all() ############### diff --git a/submissions/managers.py b/submissions/managers.py index d74e9cc56..e85f7218c 100644 --- a/submissions/managers.py +++ b/submissions/managers.py @@ -302,6 +302,9 @@ class EICRecommendationQuerySet(models.QuerySet): def voting_in_preparation(self): return self.filter(submission__status=STATUS_VOTING_IN_PREPARATION) + def active(self): + return self.filter(active=True) + class ReportQuerySet(models.QuerySet): def accepted(self): diff --git a/submissions/migrations/0005_auto_20180123_2312.py b/submissions/migrations/0005_auto_20180123_2312.py new file mode 100644 index 000000000..35d948ca9 --- /dev/null +++ b/submissions/migrations/0005_auto_20180123_2312.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-23 22:12 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0004_merge_20180123_2041'), + ] + + operations = [ + migrations.AlterModelOptions( + name='eicrecommendation', + options={'ordering': ['version']}, + ), + migrations.AddField( + model_name='eicrecommendation', + name='version', + field=models.SmallIntegerField(default=1), + ), + migrations.AlterUniqueTogether( + name='eicrecommendation', + unique_together=set([('submission', 'version')]), + ), + ] diff --git a/submissions/migrations/0006_eicrecommendation_active.py b/submissions/migrations/0006_eicrecommendation_active.py new file mode 100644 index 000000000..94d1c1555 --- /dev/null +++ b/submissions/migrations/0006_eicrecommendation_active.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-01-23 22:42 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0005_auto_20180123_2312'), + ] + + operations = [ + migrations.AddField( + model_name='eicrecommendation', + name='active', + field=models.BooleanField(default=True), + ), + ] diff --git a/submissions/models.py b/submissions/models.py index 00a262f1e..804a1a32d 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -15,7 +15,8 @@ from .constants import ASSIGNMENT_REFUSAL_REASONS, ASSIGNMENT_NULLBOOL,\ REPORT_STATUSES, STATUS_UNVETTED, SUBMISSION_EIC_RECOMMENDATION_REQUIRED,\ SUBMISSION_CYCLES, CYCLE_DEFAULT, CYCLE_SHORT, CYCLE_DIRECT_REC,\ EVENT_GENERAL, EVENT_TYPES, EVENT_FOR_AUTHOR, EVENT_FOR_EIC,\ - REPORT_TYPES, REPORT_NORMAL, STATUS_DRAFT, STATUS_VETTED + REPORT_TYPES, REPORT_NORMAL, STATUS_DRAFT, STATUS_VETTED,\ + STATUS_VOTING_IN_PREPARATION, STATUS_PUT_TO_EC_VOTING from .managers import SubmissionQuerySet, EditorialAssignmentQuerySet, EICRecommendationQuerySet,\ ReportQuerySet, SubmissionEventQuerySet, RefereeInvitationQuerySet,\ EditorialCommunicationQueryset @@ -508,16 +509,6 @@ class Report(SubmissionRelatedObjectMixin, models.Model): submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr, submission__arxiv_vn_nr__lt=self.submission.arxiv_vn_nr).exists()) - def save(self, *args, **kwargs): - # Control Report count per Submission. - if not self.report_nr: - self.report_nr = self.submission.reports.count() + 1 - return super().save(*args, **kwargs) - - def create_doi_label(self): - self.doi_label = 'SciPost.Report.' + str(self.id) - self.save() - def latest_report_from_series(self): """ Get latest Report from the same author for the Submission series. @@ -526,7 +517,6 @@ class Report(SubmissionRelatedObjectMixin, models.Model): submission__arxiv_identifier_wo_vn_nr=self.submission.arxiv_identifier_wo_vn_nr) .order_by('submission__arxiv_identifier_wo_vn_nr').last()) - @property def associated_published_doi(self): """ @@ -622,6 +612,8 @@ class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): verbose_name='optional remarks for the' ' Editorial College') recommendation = models.SmallIntegerField(choices=REPORT_REC) + version = models.SmallIntegerField(default=1) + active = models.BooleanField(default=True) # Editorial Fellows who have assessed this recommendation: eligible_to_vote = models.ManyToManyField('scipost.Contributor', blank=True, @@ -635,9 +627,17 @@ class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): objects = EICRecommendationQuerySet.as_manager() + class Meta: + unique_together = ('submission', 'version') + ordering = ['version'] + def __str__(self): - return (self.submission.title[:20] + ' by ' + self.submission.author_list[:30] + - ', ' + self.get_recommendation_display()) + return '{title} by {author}, {recommendation} version {version}'.format( + title=self.submission.title[:20], + author=self.submission.author_list[:30], + recommendation=self.get_recommendation_display(), + version=self.version, + ) def get_absolute_url(self): # TODO: Fix this weird redirect, but it's neccesary for the notifications to have one. @@ -659,6 +659,12 @@ class EICRecommendation(SubmissionRelatedObjectMixin, models.Model): def nr_abstained(self): return self.voted_abstain.count() + def may_be_reformulated(self): + if not self.active: + # Already reformulated before; please use the latest version + return False + return self.submission.status in [STATUS_VOTING_IN_PREPARATION, STATUS_PUT_TO_EC_VOTING] + class iThenticateReport(TimeStampedModel): """ diff --git a/submissions/templates/submissions/_recommendation_author_content.html b/submissions/templates/submissions/_recommendation_author_content.html index d646512ba..39743bb93 100644 --- a/submissions/templates/submissions/_recommendation_author_content.html +++ b/submissions/templates/submissions/_recommendation_author_content.html @@ -1,6 +1,6 @@ <div class="card bg-white"> <div class="card-body"> - <h2 class="pb-0 mb-0">Editorial Recommendation</h2> + <h2 class="card-title mb-0">Editorial Recommendation <small>(version {{ recommendation.version }}){% if not recommendation.active %} (Deprecated: This Editorial Recommendation has been reformulated){% endif %}</small></h2> {% block recommendation_header %} <h3 class="card-title text-muted">Date {{recommendation.date_submitted}}</h3> diff --git a/submissions/templates/submissions/editorial_page.html b/submissions/templates/submissions/editorial_page.html index 66b4ad1c6..bb0048c3e 100644 --- a/submissions/templates/submissions/editorial_page.html +++ b/submissions/templates/submissions/editorial_page.html @@ -76,17 +76,16 @@ </div> </div> -{% with recommendation as submission.eicrecommendations.first %} - {% if recommendation %} - <div class="row"> - <div class="col-12"> - <div class="card card-outline-secondary"> - {% include 'submissions/_recommendation_author_content.html' with recommendation=recommendation %} - </div> - </div> - </div> - {% endif %} -{% endwith %} +<div class="row"> + <div class="col-12"> + {% for recommendation in submission.eicrecommendations.all %} + {% include 'submissions/_recommendation_author_content.html' with recommendation=recommendation %} + {% if recommendation.may_be_reformulated %} + <a href="{% url 'submissions:reformulate_eic_recommendation' submission.arxiv_identifier_w_vn_nr %}">Reformulate this Editorial Recommendation</a> + {% endif %} + {% endfor %} + </div> +</div> <div class="card card-grey my-4"> <div class="card-body"> @@ -237,6 +236,11 @@ </p> </li> {% endif %} + {% if submission.eicrecommendations.active.first %} + {% if submission.eicrecommendations.active.first.may_be_reformulated %} + <li><a href="{% url 'submissions:reformulate_eic_recommendation' submission.arxiv_identifier_w_vn_nr %}">Reformulate Editorial Recommendation</a></li> + {% endif %} + {% endif %} </ul> </div> </div> diff --git a/submissions/templates/submissions/pool/recommendation_formulate_rewrite.html b/submissions/templates/submissions/pool/recommendation_formulate_rewrite.html new file mode 100644 index 000000000..58b73d22d --- /dev/null +++ b/submissions/templates/submissions/pool/recommendation_formulate_rewrite.html @@ -0,0 +1,68 @@ +{% extends 'submissions/pool/base.html' %} + +{% block pagetitle %}: Editorial Recommendation for Submission{% endblock pagetitle %} + +{% load scipost_extras %} +{% load bootstrap %} + +{% block breadcrumb_items %} + {{block.super}} + <a href="{% url 'submissions:editorial_page' submission.arxiv_identifier_w_vn_nr %}" class="breadcrumb-item">Editorial Page ({{submission.arxiv_identifier_w_vn_nr}})</a> + <span class="breadcrumb-item">Reformulate Editorial Recommendation</span> +{% endblock %} + +{% block content %} + +<h1 class="highlight">Reformulate Editorial Recommendation for Submission</h1> + +<br> +{% include 'submissions/_submission_summary.html' with submission=submission %} + +<br> +<div class="card card-grey"> + <div class="card-body"> + <h2 class="card-title">Reformulate Editorial Recommendation</h2> + <p class="card-text">You recommendation will be processed by the Editorial Administration.</p> + <ul> + <li>acceptance or rejection: forwarded to the Editorial College for ratification</li> + <li>request for revision: sent directly to the authors</li> + </ul> + + <p class="card-text"> + This recommendation will be saved with a new version number and any other Editorial Recommendation will be deactived. <b>All obtained votes will be lost.</b> + </p> + </div> +</div> + +{% if submission.editor_in_charge != request.user.contributor %} + <div class="row"> + <div class="col-12"> + <div class="card border-danger"> + <div class="card-body d-flex flex-row"> + <div class="p-2"> + <i class="fa fa-2x fa-exclamation-triangle text-warning" aria-hidden="true"></i> + </div> + <div class="px-2"> + You are not assigned as Editor in charge. However, you can formulate an Editorial Recommendation because you are Editorial Administrator. <strong>This Editorial Recommendation will still be signed by the Editor-in-charge.</strong> + </div> + + </div> + </div> + </div> + </div> +{% endif %} + +<br> + +<div class="row"> + <div class="col-12"> + <form method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input class="btn btn-primary" type="submit" value="Submit Recommendation"/> + </form> + </div> +</div> + + +{% endblock content %} diff --git a/submissions/urls.py b/submissions/urls.py index 3981f846e..139dc2528 100644 --- a/submissions/urls.py +++ b/submissions/urls.py @@ -68,7 +68,8 @@ urlpatterns = [ views.select_referee, name='select_referee'), url(r'^recruit_referee/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.recruit_referee, name='recruit_referee'), - url(r'^send_refereeing_invitation/{regex}/(?P<contributor_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + url(r'^send_refereeing_invitation/{regex}/(?P<contributor_id>[0-9]+)$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.send_refereeing_invitation, name='send_refereeing_invitation'), url(r'^accept_or_decline_ref_invitations/$', views.accept_or_decline_ref_invitations, name='accept_or_decline_ref_invitations'), @@ -76,23 +77,30 @@ urlpatterns = [ views.accept_or_decline_ref_invitations, name='accept_or_decline_ref_invitations'), url(r'^decline_ref_invitation/(?P<invitation_key>.+)$', views.decline_ref_invitation, name='decline_ref_invitation'), - url(r'^ref_invitation_reminder/{regex}/(?P<invitation_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + url(r'^ref_invitation_reminder/{regex}/(?P<invitation_id>[0-9]+)$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.ref_invitation_reminder, name='ref_invitation_reminder'), - url(r'^cancel_ref_invitation/{regex}/(?P<invitation_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + url(r'^cancel_ref_invitation/{regex}/(?P<invitation_id>[0-9]+)$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.cancel_ref_invitation, name='cancel_ref_invitation'), - url(r'^extend_refereeing_deadline/{regex}/(?P<days>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + url(r'^extend_refereeing_deadline/{regex}/(?P<days>[0-9]+)$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.extend_refereeing_deadline, name='extend_refereeing_deadline'), url(r'^set_refereeing_deadline/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.set_refereeing_deadline, name='set_refereeing_deadline'), url(r'^close_refereeing_round/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.close_refereeing_round, name='close_refereeing_round'), url(r'^refereeing_overview$', views.refereeing_overview, name='refereeing_overview'), - url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.communication, name='communication'), - url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})/(?P<referee_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})/(?P<referee_id>[0-9]+)$'.format( + regex=SUBMISSIONS_COMPLETE_REGEX), views.communication, name='communication'), url(r'^eic_recommendation/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.eic_recommendation, name='eic_recommendation'), + url(r'^eic_recommendation/{regex}/reformulate$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + views.reformulate_eic_recommendation, name='reformulate_eic_recommendation'), url(r'^cycle/{regex}/submit$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.cycle_form_submit, name='cycle_confirmation'), @@ -104,7 +112,8 @@ urlpatterns = [ name='vet_submitted_report'), # Voting - url(r'^prepare_for_voting/(?P<rec_id>[0-9]+)$', views.prepare_for_voting, name='prepare_for_voting'), + url(r'^prepare_for_voting/(?P<rec_id>[0-9]+)$', views.prepare_for_voting, + name='prepare_for_voting'), url(r'^vote_on_rec/(?P<rec_id>[0-9]+)$', views.vote_on_rec, name='vote_on_rec'), url(r'^remind_Fellows_to_vote$', views.remind_Fellows_to_vote, name='remind_Fellows_to_vote'), diff --git a/submissions/views.py b/submissions/views.py index 5e9c27c23..5ab6f37ae 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -20,10 +20,11 @@ from django.views.generic.list import ListView from guardian.shortcuts import assign_perm from .constants import STATUS_VETTED, STATUS_EIC_ASSIGNED,\ - SUBMISSION_STATUS_PUBLICLY_INVISIBLE, SUBMISSION_STATUS, ED_COMM_CHOICES,\ - STATUS_DRAFT, CYCLE_DIRECT_REC + SUBMISSION_STATUS_PUBLICLY_INVISIBLE, SUBMISSION_STATUS,\ + STATUS_DRAFT, CYCLE_DIRECT_REC, STATUS_VOTING_IN_PREPARATION,\ + STATUS_PUT_TO_EC_VOTING from .models import Submission, EICRecommendation, EditorialAssignment,\ - RefereeInvitation, Report, EditorialCommunication, SubmissionEvent + RefereeInvitation, Report, SubmissionEvent from .mixins import SubmissionAdminViewMixin from .forms import SubmissionIdentifierForm, RequestSubmissionForm, SubmissionSearchForm,\ RecommendationVoteForm, ConsiderAssignmentForm, AssignSubmissionForm,\ @@ -221,7 +222,7 @@ def submission_detail(request, arxiv_identifier_w_vn_nr): context['communication'] = submission.editorial_communications.for_referees().filter( referee__user=request.user) - recommendations = submission.eicrecommendations.all() + recommendations = submission.eicrecommendations.active() context.update({ 'submission': submission, @@ -358,8 +359,7 @@ def pool(request, arxiv_identifier_w_vn_nr=None): # Mainly as fallback for the old-pool while in test phase. submissions = Submission.objects.pool(request.user) - # submissions = Submission.objects.pool(request.user) - recommendations = EICRecommendation.objects.filter(submission__in=submissions) + recommendations = EICRecommendation.objects.active().filter(submission__in=submissions) recs_to_vote_on = recommendations.user_may_vote_on(request.user) assignments_to_consider = EditorialAssignment.objects.open().filter( to=request.user.contributor) @@ -1192,11 +1192,9 @@ def eic_recommendation(request, arxiv_identifier_w_vn_nr): return redirect(reverse('submissions:editorial_page', args=[submission.arxiv_identifier_w_vn_nr])) + form = EICRecommendationForm(request.POST or None, submission=submission) # Find EditorialAssignment for user - try: - assignment = submission.editorial_assignments.accepted().get( - to=submission.editor_in_charge) - except EditorialAssignment.DoesNotExist: + if not form.has_assignment(): messages.warning(request, ('You cannot formulate an Editorial Recommendation,' ' because the Editorial Assignment has not been set properly.' ' Please ' @@ -1204,53 +1202,68 @@ def eic_recommendation(request, arxiv_identifier_w_vn_nr): return redirect(reverse('submissions:editorial_page', args=[submission.arxiv_identifier_w_vn_nr])) - form = EICRecommendationForm(request.POST or None) if form.is_valid(): - # Create new EICRecommendation - recommendation = form.save(commit=False) - recommendation.submission = submission - recommendation.voting_deadline = timezone.now() + datetime.timedelta(days=7) - recommendation.save() - - # If recommendation is to accept or reject, - # it is forwarded to the Editorial College for voting - # If it is to carry out minor or major revisions, - # it is returned to the Author who is asked to resubmit - if (recommendation.recommendation == 1 or - recommendation.recommendation == 2 or - recommendation.recommendation == 3 or - recommendation.recommendation == -3): - submission.status = 'voting_in_preparation' - - # Add SubmissionEvent for EIC - submission.add_event_for_eic('An Editorial Recommendation has been formulated: %s.' - % recommendation.get_recommendation_display()) - - elif (recommendation.recommendation == -1 or - recommendation.recommendation == -2): - submission.status = 'revision_requested' - SubmissionUtils.load({'submission': submission, - 'recommendation': recommendation}) + recommendation = form.save() + if form.revision_requested(): + # Send mail to authors to notify about the request for revision. + SubmissionUtils.load({ + 'submission': form.submission, + 'recommendation': recommendation, + }) SubmissionUtils.send_author_revision_requested_email() - # Add SubmissionEvents - submission.add_general_event('An Editorial Recommendation has been formulated: %s.' - % recommendation.get_recommendation_display()) - submission.open_for_reporting = False - submission.save() - - # The EIC has fulfilled this editorial assignment. - assignment.completed = True - assignment.save() - messages.success(request, 'Your Editorial Recommendation has been succesfully submitted') + messages.success(request, 'Editorial Recommendation succesfully submitted') return redirect(reverse('submissions:editorial_page', kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) - context = {'submission': submission, - 'form': form} + context = { + 'submission': submission, + 'form': form + } return render(request, 'submissions/pool/recommendation_formulate.html', context) +@login_required +@fellowship_or_admin_required() +@transaction.atomic +def reformulate_eic_recommendation(request, arxiv_identifier_w_vn_nr): + """ + Reformulate EIC Recommendation. + + Accessible for: Editor-in-charge and Editorial Administration + """ + submission = get_object_or_404(Submission.objects.filter_for_eic(request.user), + arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + + if submission.status not in [STATUS_VOTING_IN_PREPARATION, STATUS_PUT_TO_EC_VOTING]: + messages.warning(request, ('With the current status of the Submission you are not ' + 'allowed to reformulate the Editorial Recommendation')) + return redirect(reverse('submissions:editorial_page', + args=[submission.arxiv_identifier_w_vn_nr])) + + form = EICRecommendationForm(request.POST or None, submission=submission, reformulate=True) + + if form.is_valid(): + recommendation = form.save() + if form.revision_requested(): + # Send mail to authors to notify about the request for revision. + SubmissionUtils.load({ + 'submission': form.submission, + 'recommendation': recommendation, + }) + SubmissionUtils.send_author_revision_requested_email() + + messages.success(request, 'Editorial Recommendation succesfully reformulated') + return redirect(reverse('submissions:editorial_page', + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) + + context = { + 'submission': submission, + 'form': form + } + return render(request, 'submissions/pool/recommendation_formulate_rewrite.html', context) + + ########### # Reports ########### @@ -1401,7 +1414,7 @@ def vet_submitted_report(request, report_id): def prepare_for_voting(request, rec_id): submissions = Submission.objects.pool_editable(request.user) recommendation = get_object_or_404( - EICRecommendation.objects.filter(submission__in=submissions), id=rec_id) + EICRecommendation.objects.active().filter(submission__in=submissions), id=rec_id) fellows_with_expertise = recommendation.submission.fellows.filter( contributor__expertises__contains=[recommendation.submission.subject_area]) @@ -1453,7 +1466,7 @@ def prepare_for_voting(request, rec_id): def vote_on_rec(request, rec_id): submissions = Submission.objects.pool_editable(request.user) recommendation = get_object_or_404( - EICRecommendation.objects.filter(submission__in=submissions), id=rec_id) + EICRecommendation.objects.active().filter(submission__in=submissions), id=rec_id) form = RecommendationVoteForm(request.POST or None) if form.is_valid(): @@ -1507,7 +1520,8 @@ def remind_Fellows_to_vote(request): TODO: This reminder function doesn't filter per submission?! """ submissions = Submission.objects.pool_editable(request.user) - recommendations = EICRecommendation.objects.filter(submission__in=submissions).put_to_voting() + recommendations = EICRecommendation.objects.active().filter( + submission__in=submissions).put_to_voting() Fellow_emails = [] Fellow_names = [] -- GitLab