diff --git a/scipost_django/scipost/static/scipost/referee-accept-or-refuse.js b/scipost_django/scipost/static/scipost/referee-accept-or-refuse.js index 8bd1a0e9e5e8b5c6897badad2a140560a01d9dc2..60912463d3209d3133f905643a084271934c1e60 100644 --- a/scipost_django/scipost/static/scipost/referee-accept-or-refuse.js +++ b/scipost_django/scipost/static/scipost/referee-accept-or-refuse.js @@ -1,10 +1,18 @@ -$(document).ready(function(){ - $('[name="accept"]').on('change', function() { - if($('[name="accept"]:checked').val() == 'False') { +$(document).ready(function () { + $('[name="accept"]').on('change', function () { + if ($('[name="accept"]:checked').val() == 'False') { $('#id_refusal_reason').parents('.form-group').show(); - } - else { + } + else { $('#id_refusal_reason').parents('.form-group').hide(); - } + } + }).trigger('change'); + $('[name="refusal_reason"]').on('change', function () { + if ($('[name="refusal_reason"]').val() == 'OTH') { + $('#id_other_refusal_reason').parents('.form-group').show(); + } + else { + $('#id_other_refusal_reason').parents('.form-group').hide(); + } }).trigger('change'); }); diff --git a/scipost_django/submissions/forms/__init__.py b/scipost_django/submissions/forms/__init__.py index c24875bd302add6c59693d42675db1e14bcfc1b8..0eac0a9863bcbba0f5d1d06984cfecefd41b4700 100644 --- a/scipost_django/submissions/forms/__init__.py +++ b/scipost_django/submissions/forms/__init__.py @@ -2266,6 +2266,40 @@ class ConsiderRefereeInvitationForm(forms.Form): refusal_reason = forms.ChoiceField( choices=EditorialAssignment.REFUSAL_REASONS, required=False ) + other_refusal_reason = forms.CharField( + required=False, + widget=forms.Textarea( + { + "placeholder": "Please shortly describe your reason for declining. (255 characters max)" + } + ), + max_length=255, + ) + + def clean(self): + accepted = self.cleaned_data.get("accept", None) + reason = self.cleaned_data.get("refusal_reason", None) + other_refusal_reason = self.cleaned_data.get("other_refusal_reason", None) + + if accepted == "False": + if reason is None: + self.add_error( + "refusal_reason", "Please select a reason for declining." + ) + if reason == "other" and other_refusal_reason is None: + self.add_error( + "other_refusal_reason", "Please specify your reason for declining." + ) + elif reason != "other" and other_refusal_reason is not None: + self.add_error( + "other_refusal_reason", + 'Please select "Other" to specify your reason for declining.', + ) + elif reason is not None: + self.add_error( + "refusal_reason", + "You cannot select a refusal reason if you accept.", + ) class SetRefereeingDeadlineForm(forms.Form): diff --git a/scipost_django/submissions/migrations/0147_auto_20240220_1404.py b/scipost_django/submissions/migrations/0147_auto_20240220_1404.py new file mode 100644 index 0000000000000000000000000000000000000000..4e3f17904d4028fe9f43b66451bb13e1db295b3c --- /dev/null +++ b/scipost_django/submissions/migrations/0147_auto_20240220_1404.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.18 on 2024-02-20 13:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0146_submission_lifetime_dates'), + ] + + operations = [ + migrations.AddField( + model_name='refereeinvitation', + name='other_refusal_reason', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AlterField( + model_name='editorialassignment', + name='refusal_reason', + field=models.CharField(blank=True, choices=[('OFE', 'Outside of my field of expertise'), ('BUS', 'Too busy'), ('VAC', 'Away on vacation'), ('COI', 'Conflict of interest: coauthor in last 5 years'), ('CCC', 'Conflict of interest: close colleague'), ('CCM', 'Conflict of interest: close competitor'), ('COT', 'Conflict of interest: other'), ('NIR', 'Cannot give an impartial assessment'), ('NIE', 'Not interested enough'), ('DNP', 'SciPost should desk reject this paper'), ('OTH', 'Other')], max_length=3, null=True), + ), + migrations.AlterField( + model_name='refereeinvitation', + name='refusal_reason', + field=models.CharField(blank=True, choices=[('OFE', 'Outside of my field of expertise'), ('BUS', 'Too busy'), ('VAC', 'Away on vacation'), ('COI', 'Conflict of interest: coauthor in last 5 years'), ('CCC', 'Conflict of interest: close colleague'), ('CCM', 'Conflict of interest: close competitor'), ('COT', 'Conflict of interest: other'), ('NIR', 'Cannot give an impartial assessment'), ('NIE', 'Not interested enough'), ('DNP', 'SciPost should desk reject this paper'), ('OTH', 'Other')], max_length=3, null=True), + ), + ] diff --git a/scipost_django/submissions/models/assignment.py b/scipost_django/submissions/models/assignment.py index f93656a7eda52ee03fd24d09a28da6da0b4f6092..f73e5c39d063e9643a68369912ea71ac92ab1e40 100644 --- a/scipost_django/submissions/models/assignment.py +++ b/scipost_django/submissions/models/assignment.py @@ -27,6 +27,7 @@ class EditorialAssignment(SubmissionRelatedObjectMixin, models.Model): REFUSE_NOT_IMPARTIAL = "NIR" REFUSE_NOT_INTERESTED = "NIE" REFUSE_DESK_REJECT = "DNP" + REFUSE_OTHER = "OTH" REFUSAL_REASONS = ( (REFUSE_OUTSIDE_EXPERTISE, "Outside of my field of expertise"), (REFUSE_TOO_BUSY, "Too busy"), @@ -41,6 +42,7 @@ class EditorialAssignment(SubmissionRelatedObjectMixin, models.Model): REFUSE_DESK_REJECT, "SciPost should desk reject this paper", ), + (REFUSE_OTHER, "Other"), ) STATUS_PREASSIGNED = "preassigned" diff --git a/scipost_django/submissions/models/referee_invitation.py b/scipost_django/submissions/models/referee_invitation.py index 5063e8aa570863bc5b1348755510b0e0c884412b..15a8c7cce8a89e27812da23db6287c522b3325e1 100644 --- a/scipost_django/submissions/models/referee_invitation.py +++ b/scipost_django/submissions/models/referee_invitation.py @@ -71,6 +71,7 @@ class RefereeInvitation(SubmissionRelatedObjectMixin, models.Model): blank=True, null=True, ) + other_refusal_reason = models.CharField(max_length=255, blank=True, null=True) fulfilled = models.BooleanField( default=False ) # True if a Report has been submitted diff --git a/scipost_django/submissions/templates/submissions/_refereeing_status_card.html b/scipost_django/submissions/templates/submissions/_refereeing_status_card.html index e3109323b2d11cc1900285acddd467123afe7859..72092d1eabd417ade05689acd4c74fe48e8ac968 100644 --- a/scipost_django/submissions/templates/submissions/_refereeing_status_card.html +++ b/scipost_django/submissions/templates/submissions/_refereeing_status_card.html @@ -47,5 +47,8 @@ <h3>Your Referee Invitation</h3> <p>You have declined to contribute a Report. Nonetheless, we thank you very much for considering this refereeing invitation.</p> <p>Reason: {{ invitation.get_refusal_reason_display }}</p> + {% if invitation.refusal_reason == 'OTH' %} + <p>{{ invitation.other_refusal_reason }}</p> + {% endif %} {% endif %} </div> diff --git a/scipost_django/submissions/views/__init__.py b/scipost_django/submissions/views/__init__.py index 2f19bc680f820049fd6984cc2469d76e02779cbd..ba971351bbeba4f10ad6c7f99cbf67287dd7386d 100644 --- a/scipost_django/submissions/views/__init__.py +++ b/scipost_django/submissions/views/__init__.py @@ -1418,6 +1418,7 @@ def accept_or_decline_ref_invitations(request, invitation_id=None): invitation.accepted = False decision_string = "declined" invitation.refusal_reason = form.cleaned_data["refusal_reason"] + invitation.other_refusal_reason = form.cleaned_data["other_refusal_reason"] messages.success( request, ( @@ -2964,9 +2965,11 @@ def submissions_versus_fellows(submissions): "fellows_senior": fellows_senior, "fellows_regular": fellows_regular, "fellows_guest": fellows_guest, - "ratio": nr_streams / fellows_total - if fellows_total > 0 - else nr_streams, + "ratio": ( + nr_streams / fellows_total + if fellows_total > 0 + else nr_streams + ), } ) return sorted(stats, key=lambda tup: tup["ratio"], reverse=True) diff --git a/scipost_django/templates/email/eic/referee_response.html b/scipost_django/templates/email/eic/referee_response.html index bde0688f68bd71bfb15b5b316aedd106f2d40e5f..a0296d4d152dad181c870c72919d20ff8574f949 100644 --- a/scipost_django/templates/email/eic/referee_response.html +++ b/scipost_django/templates/email/eic/referee_response.html @@ -3,6 +3,9 @@ <p> Referee {% if invitation.referee %}{{ invitation.referee.profile.get_title_display }} {{ invitation.referee.user.last_name }}{% else %}{{ invitation.get_title_display }} {{ invitation.first_name }} {{ invitation.last_name }}{% endif %} has {% if invitation.accepted %}accepted{% else %}declined (due to reason: {{ invitation.get_refusal_reason_display }}){% endif %} to referee Submission </p> +{% if invitation.other_refusal_reason %} + <p>Their "other" refusal reason states: {{ invitation.other_refusal_reason }}</p> +{% endif %} <p> {{ invitation.submission.title }} <br/> diff --git a/scipost_django/templates/email/referees/confirmation_invitation_response.html b/scipost_django/templates/email/referees/confirmation_invitation_response.html index d8183c155607bcd9d4ba315e60dd5d95dcedd355..3273569176c73dfda7443da348fdbe59d3e93163 100644 --- a/scipost_django/templates/email/referees/confirmation_invitation_response.html +++ b/scipost_django/templates/email/referees/confirmation_invitation_response.html @@ -3,6 +3,9 @@ <p> We hereby confirm your choice to {% if invitation.accepted %}accept{% else %}decline (due to reason: {{ invitation.get_refusal_reason_display }}){% endif %} to referee Submission </p> +{% if invitation.other_refusal_reason %} + <p>Your "other" refusal reason states: {{ invitation.other_refusal_reason }}</p> +{% endif %} <p> {{ invitation.submission.title }} <br/>