From 018fb9f8f50c89861d822b85f7e0ab0708ecfa35 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Thu, 15 Sep 2016 22:12:17 +0200 Subject: [PATCH] Add cancel ref invitation facility --- scipost/views.py | 4 +-- submissions/models.py | 5 ++- .../templates/submissions/editorial_page.html | 29 +++++++++------- .../submissions/submission_detail.html | 2 +- submissions/urls.py | 2 ++ submissions/utils.py | 34 +++++++++++++++++++ submissions/views.py | 21 +++++++++++- 7 files changed, 79 insertions(+), 18 deletions(-) diff --git a/scipost/views.py b/scipost/views.py index 03d0ebe97..ec693b5a8 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -378,7 +378,7 @@ def vet_registration_request_ack(request, contributor_id): pending_ref_inv_exists = True try: pending_ref_inv = RefereeInvitation.objects.get( - invitation_key=contributor.invitation_key) + invitation_key=contributor.invitation_key, cancelled=False) pending_ref_inv.referee = contributor pending_ref_inv.save() except RefereeInvitation.DoesNotExist: @@ -591,7 +591,7 @@ def personal_page(request): nr_thesislink_requests_to_vet = ThesisLink.objects.filter(vetted=False).count() nr_authorship_claims_to_vet = AuthorshipClaim.objects.filter(status='0').count() nr_ref_inv_to_consider = RefereeInvitation.objects.filter( - referee=contributor, accepted=None).count() + referee=contributor, accepted=None, cancelled=False).count() pending_ref_tasks = RefereeInvitation.objects.filter( referee=contributor, accepted=True, fulfilled=False) # Verify if there exist objects authored by this contributor, diff --git a/submissions/models.py b/submissions/models.py index 6a0483549..7daf4528f 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -436,6 +436,7 @@ class RefereeInvitation(models.Model): refusal_reason = models.CharField(max_length=3, choices=ASSIGNMENT_REFUSAL_REASONS, blank=True, null=True) fulfilled = models.BooleanField(default=False) # True if a Report has been submitted + cancelled = models.BooleanField(default=False) # True if EIC has deactivated invitation def __str__(self): return (self.first_name + ' ' + self.last_name + ' to referee ' + @@ -464,7 +465,9 @@ class RefereeInvitation(models.Model): context = Context({'first_name': self.first_name, 'last_name': self.last_name, 'date_invited': self.date_invited.strftime('%Y-%m-%d %H:%M')}) output = '<td>{{ first_name }} {{ last_name }}</td><td>invited <br/>{{ date_invited }}</td><td>' - if self.accepted is not None: + if self.cancelled: + output += '<strong style="color: red;">cancelled</strong>' + elif self.accepted is not None: if self.accepted: output += '<strong style="color: green">task accepted</strong> ' else: diff --git a/submissions/templates/submissions/editorial_page.html b/submissions/templates/submissions/editorial_page.html index 3a162ca79..1e45d8ed1 100644 --- a/submissions/templates/submissions/editorial_page.html +++ b/submissions/templates/submissions/editorial_page.html @@ -76,7 +76,7 @@ {% for invitation in ref_invitations %} <tr> {{ invitation.summary_as_tds }} - {% if not invitation.accepted == False %} + {% if not invitation.accepted == False and not invitation.cancelled %} <td> {% if invitation.referee %} <a href="{% url 'submissions:communication' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr comtype='EtoR' referee_id=invitation.referee.id %}">Write a communication</a> @@ -85,21 +85,24 @@ {% endif %} </td> <td> - {% if not invitation.fulfilled %} - <a href="{% url 'submissions:ref_invitation_reminder' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr invitation_id=invitation.id %}">Send reminder email</a> - {% else %} - <strong style="color: green">Report has been delivered</strong> - {% endif %} + {% if not invitation.fulfilled %} + <a href="{% url 'submissions:ref_invitation_reminder' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr invitation_id=invitation.id %}">Send reminder email</a> + {% else %} + <strong style="color: green">Report has been delivered</strong> + {% endif %} </td> - {% else %} - <td></td><td></td> - {% endif %} <td> - {% if invitation.nr_reminders > 0 %} - (nr reminders sent: {{ invitation.nr_reminders }}, <br/>last on {{ invitation.date_last_reminded }}) - {% else %} - + {% if invitation.nr_reminders > 0 %} + (nr reminders sent: {{ invitation.nr_reminders }}, <br/>last on {{ invitation.date_last_reminded }}) + {% endif %} + </td> + <td> + {% if not invitation.fulfilled %} + <a href="{% url 'submissions:cancel_ref_invitation' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr invitation_id=invitation.id %}">Cancel invitation</a> + {% endif %} </td> + {% else %} + <td></td><td></td><td></td><td></td> {% endif %} </tr> {% endfor %} diff --git a/submissions/templates/submissions/submission_detail.html b/submissions/templates/submissions/submission_detail.html index d4b75979a..6122a406a 100644 --- a/submissions/templates/submissions/submission_detail.html +++ b/submissions/templates/submissions/submission_detail.html @@ -84,7 +84,7 @@ {% if submission.open_for_reporting %} {% if perms.scipost.can_referee and not is_author and not is_author_unchecked %} <li><h3><a href="{% url 'submissions:submit_report' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Contribute a Report</a></h3> - <div class="reportingDeadline">Deadline for reporting: {{ submission.reporting_deadline }}</div></li> + <div class="reportingDeadline">Deadline for reporting: {{ submission.reporting_deadline|date:"Y-m-d" }}</div></li> {% elif is_author_unchecked %} <li><h3>Contribute a Report [deactivated]: the system flagged you as a potential author of this Submission. Please go to your <a href="{% url 'scipost:personal_page' %}">personal page</a> diff --git a/submissions/urls.py b/submissions/urls.py index 8383c3911..0cb3e2984 100644 --- a/submissions/urls.py +++ b/submissions/urls.py @@ -48,6 +48,8 @@ urlpatterns = [ url(r'^accept_or_decline_ref_invitation/(?P<invitation_id>[0-9]+)$', views.accept_or_decline_ref_invitation_ack, name='accept_or_decline_ref_invitation_ack'), url(r'^ref_invitation_reminder/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<invitation_id>[0-9]+)$', views.ref_invitation_reminder, name='ref_invitation_reminder'), + url(r'^cancel_ref_invitation/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<invitation_id>[0-9]+)$', + views.cancel_ref_invitation, name='cancel_ref_invitation'), url(r'^extend_refereeing_deadline/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<days>[0-9]+)$', views.extend_refereeing_deadline, name='extend_refereeing_deadline'), url(r'^close_refereeing_round/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', diff --git a/submissions/utils.py b/submissions/utils.py index 49bb998f1..14652908e 100644 --- a/submissions/utils.py +++ b/submissions/utils.py @@ -282,6 +282,40 @@ class SubmissionUtils(object): ['submissions@scipost.org'], reply_to=['submissions@scipost.org']) emailmessage.send(fail_silently=False) + + + @classmethod + def send_ref_cancellation_email(cls): + """ + This method is used to inform a referee that his/her services are no longer required. + It is called from the cancel_ref_invitation method in submissions/views.py. + """ + email_text = ('Dear ' + title_dict[cls.invitation.title] + ' ' + cls.invitation.last_name + ',\n\n' + 'On behalf of the Editor-in-charge ' + + title_dict[cls.invitation.submission.editor_in_charge.title] + ' ' + + cls.invitation.submission.editor_in_charge.user.last_name + + ', we would like to inform you that your report on\n\n' + + cls.invitation.submission.title + ' by ' + + cls.invitation.submission.author_list + + '\n\nis no longer required.') + email_text += ('\n\nWe very much hope we can count on your expertise ' + 'at some other point in the future,' + '\n\nMany thanks for your time,\n\nThe SciPost Team') + if cls.invitation.referee is None: + email_text += ('\n\nP.S.: We would also like to renew ' + 'our invitation to become a Contributor on SciPost ' + '(our records show that you are not yet registered); ' + 'your partially pre-filled registration form is still available at\n\n' + 'https://scipost.org/invitation/' + cls.invitation.invitation_key + '\n\n' + 'after which your registration will be activated, giving you full access to ' + 'the portal\'s facilities (in particular allowing you to provide referee reports).') + emailmessage = EmailMessage( + 'SciPost: report no longer needed', email_text, + 'SciPost Submissions <submissions@scipost.org>', + [cls.invitation.email_address], + ['submissions@scipost.org'], + reply_to=['submissions@scipost.org']) + emailmessage.send(fail_silently=False) @classmethod diff --git a/submissions/views.py b/submissions/views.py index 8bce676c1..dfdd9bc5e 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -839,6 +839,25 @@ def accept_or_decline_ref_invitation_ack(request, invitation_id): return render(request, 'submissions/accept_or_decline_ref_invitation_ack.html', context) + +@login_required +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +def cancel_ref_invitation(request, arxiv_identifier_w_vn_nr, invitation_id): + """ + This method is used by the Editor-in-charge from the editorial_page + to remove a referee for the list of invited ones. + It can be used for registered as well as unregistered referees. + """ + invitation = get_object_or_404 (RefereeInvitation, pk=invitation_id) + invitation.cancelled=True + invitation.save() + SubmissionUtils.load({'invitation': invitation}) + SubmissionUtils.send_ref_cancellation_email() + return redirect(reverse('submissions:editorial_page', + kwargs={'arxiv_identifier_w_vn_nr': arxiv_identifier_w_vn_nr})) + + @login_required @permission_required_or_403('can_take_editorial_actions', (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) @@ -996,7 +1015,7 @@ def submit_report(request, arxiv_identifier_w_vn_nr): and not (request.user.contributor in submission.authors_false_claims.all()) and (request.user.last_name in submission.author_list)) errormessage = None - if timezone.now() > submission.reporting_deadline: + if timezone.now() > submission.reporting_deadline + datetime.timedelta(days=1): errormessage = ('The reporting deadline has passed. You cannot submit' ' a Report anymore.') if is_author: -- GitLab