diff --git a/comments/migrations/0012_auto_20170415_1659.py b/comments/migrations/0012_auto_20170415_1659.py new file mode 100644 index 0000000000000000000000000000000000000000..7764750cdc1b90b2c43ad4911f858404997d5fcb --- /dev/null +++ b/comments/migrations/0012_auto_20170415_1659.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.3 on 2017-04-15 14:59 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('comments', '0011_auto_20170326_1447'), + ] + + operations = [ + migrations.AlterField( + model_name='comment', + name='submission', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='submissions.Submission'), + ), + ] diff --git a/submissions/constants.py b/submissions/constants.py index 44b7a24f2c45f9ab3eedc648d2014ba6a981aa59..d6408cff1fbc2917e2832bea7d700de10b05ac5a 100644 --- a/submissions/constants.py +++ b/submissions/constants.py @@ -1,12 +1,15 @@ STATUS_UNASSIGNED = 'unassigned' STATUS_RESUBMISSION_SCREENING = 'resubmitted_incomin' STATUS_REVISION_REQUESTED = 'revision_requested' +STATUS_EIC_ASSIGNED = 'EICassigned' +STATUS_AWAITING_ED_REC = 'awaiting_ed_rec' +STATUS_REVIEW_CLOSED = 'review_closed' SUBMISSION_STATUS = ( (STATUS_UNASSIGNED, 'Unassigned, undergoing pre-screening'), (STATUS_RESUBMISSION_SCREENING, 'Resubmission incoming, undergoing pre-screening'), ('assignment_failed', 'Failed to assign Editor-in-charge; manuscript rejected'), - ('EICassigned', 'Editor-in-charge assigned, manuscript under review'), - ('review_closed', 'Review period closed, editorial recommendation pending'), + (STATUS_EIC_ASSIGNED, 'Editor-in-charge assigned, manuscript under review'), + (STATUS_REVIEW_CLOSED, 'Review period closed, editorial recommendation pending'), # If revisions required: resubmission creates a new Submission object (STATUS_REVISION_REQUESTED, 'Editor-in-charge has requested revision'), ('resubmitted', 'Has been resubmitted'), @@ -16,6 +19,7 @@ SUBMISSION_STATUS = ( # If acceptance/rejection: ('voting_in_preparation', 'Voting in preparation (eligible Fellows being selected)'), ('put_to_EC_voting', 'Undergoing voting at the Editorial College'), + (STATUS_AWAITING_ED_REC, 'Awaiting Editorial Recommendation'), ('EC_vote_completed', 'Editorial College voting rounded up'), ('accepted', 'Publication decision taken: accept'), ('rejected', 'Publication decision taken: reject'), @@ -34,6 +38,12 @@ SUBMISSION_STATUS_OUT_OF_POOL = [ 'rejected_visible', ] +SUBMISSION_EIC_RECOMMENDATION_REQUIRED = [ + STATUS_EIC_ASSIGNED, + STATUS_REVIEW_CLOSED, + STATUS_AWAITING_ED_REC +] + # Submissions which should not be viewable (except by admins, Fellows and authors) SUBMISSION_STATUS_PUBLICLY_INVISIBLE = [ STATUS_UNASSIGNED, diff --git a/submissions/forms.py b/submissions/forms.py index ba545eb05b6c62cbcbd7c80e211db3aa65a3e473..73f7f6fe50718aec0e89944e9908b6edfbb26385 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -277,5 +277,6 @@ class SubmissionCycleChoiceForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['refereeing_cycle'].default = None - self.fields['referees_reinvite'].queryset = (self.instance.other_versions() - .first().referee_invitations.all()) + other_submission = self.instance.other_versions().first() + if other_submission: + self.fields['referees_reinvite'].queryset = other_submission.referee_invitations.all() diff --git a/submissions/migrations/0037_auto_20170415_1659.py b/submissions/migrations/0037_auto_20170415_1659.py new file mode 100644 index 0000000000000000000000000000000000000000..4cdd6ab53537eea8f3884876bb7e4f3907a4b98c --- /dev/null +++ b/submissions/migrations/0037_auto_20170415_1659.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.3 on 2017-04-15 14:59 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0036_auto_20170415_1055'), + ] + + operations = [ + migrations.AlterField( + model_name='refereeinvitation', + name='submission', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='referee_invitations', to='submissions.Submission'), + ), + migrations.AlterField( + model_name='submission', + name='status', + field=models.CharField(choices=[('unassigned', 'Unassigned, undergoing pre-screening'), ('resubmitted_incomin', 'Resubmission incoming, undergoing pre-screening'), ('assignment_failed', 'Failed to assign Editor-in-charge; manuscript rejected'), ('EICassigned', 'Editor-in-charge assigned, manuscript under review'), ('review_closed', 'Review period closed, editorial recommendation pending'), ('revision_requested', 'Editor-in-charge has requested revision'), ('resubmitted', 'Has been resubmitted'), ('resubmitted_and_rejected', 'Has been resubmitted and subsequently rejected'), ('resubmitted_and_rejected_visible', 'Has been resubmitted and subsequently rejected (still publicly visible)'), ('voting_in_preparation', 'Voting in preparation (eligible Fellows being selected)'), ('put_to_EC_voting', 'Undergoing voting at the Editorial College'), ('awaiting_editorial_recommendation', 'Awaiting Editorial Recommendation'), ('EC_vote_completed', 'Editorial College voting rounded up'), ('accepted', 'Publication decision taken: accept'), ('rejected', 'Publication decision taken: reject'), ('rejected_visible', 'Publication decision taken: reject (still publicly visible)'), ('published', 'Published'), ('withdrawn', 'Withdrawn by the Authors')], default='unassigned', max_length=30), + ), + ] diff --git a/submissions/migrations/0038_auto_20170415_1701.py b/submissions/migrations/0038_auto_20170415_1701.py new file mode 100644 index 0000000000000000000000000000000000000000..9c05245587c16cd1071a262df440a0e725bedeff --- /dev/null +++ b/submissions/migrations/0038_auto_20170415_1701.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.3 on 2017-04-15 15:01 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0037_auto_20170415_1659'), + ] + + operations = [ + migrations.AlterField( + model_name='submission', + name='status', + field=models.CharField(choices=[('unassigned', 'Unassigned, undergoing pre-screening'), ('resubmitted_incomin', 'Resubmission incoming, undergoing pre-screening'), ('assignment_failed', 'Failed to assign Editor-in-charge; manuscript rejected'), ('EICassigned', 'Editor-in-charge assigned, manuscript under review'), ('review_closed', 'Review period closed, editorial recommendation pending'), ('revision_requested', 'Editor-in-charge has requested revision'), ('resubmitted', 'Has been resubmitted'), ('resubmitted_and_rejected', 'Has been resubmitted and subsequently rejected'), ('resubmitted_and_rejected_visible', 'Has been resubmitted and subsequently rejected (still publicly visible)'), ('voting_in_preparation', 'Voting in preparation (eligible Fellows being selected)'), ('put_to_EC_voting', 'Undergoing voting at the Editorial College'), ('awaiting_ed_rec', 'Awaiting Editorial Recommendation'), ('EC_vote_completed', 'Editorial College voting rounded up'), ('accepted', 'Publication decision taken: accept'), ('rejected', 'Publication decision taken: reject'), ('rejected_visible', 'Publication decision taken: reject (still publicly visible)'), ('published', 'Published'), ('withdrawn', 'Withdrawn by the Authors')], default='unassigned', max_length=30), + ), + ] diff --git a/submissions/models.py b/submissions/models.py index 48b71c13d3452f512cb70d8c8ea45d4820370bba..10bb121b01805007dd4ce6f011289ecbd7570b5e 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -9,7 +9,8 @@ from .constants import ASSIGNMENT_REFUSAL_REASONS, ASSIGNMENT_NULLBOOL,\ SUBMISSION_TYPE, ED_COMM_CHOICES, REFEREE_QUALIFICATION, QUALITY_SPEC,\ RANKING_CHOICES, REPORT_REC, SUBMISSION_STATUS, STATUS_UNASSIGNED,\ REPORT_STATUSES, STATUS_UNVETTED, STATUS_RESUBMISSION_SCREENING,\ - SUBMISSION_CYCLES, CYCLE_DEFAULT, CYCLE_SHORT, CYCLE_DIRECT_REC + SUBMISSION_CYCLES, CYCLE_DEFAULT, CYCLE_SHORT, CYCLE_DIRECT_REC,\ + SUBMISSION_EIC_RECOMMENDATION_REQUIRED from .managers import SubmissionManager, EditorialAssignmentManager, EICRecommendationManager,\ ReportManager from .utils import ShortSubmissionCycle, DirectRecommendationSubmissionCycle,\ @@ -88,17 +89,12 @@ class Submission(ArxivCallable, models.Model): ) def __init__(self, *args, **kwargs): - """ - Append the specific submission cycle to the instance to eventually handle the - complete submission cycle outside the submission instance itself. - """ super().__init__(*args, **kwargs) - if self.refereeing_cycle == CYCLE_SHORT: - self.cycle = ShortSubmissionCycle(self) - elif self.refereeing_cycle == CYCLE_DIRECT_REC: - self.cycle = DirectRecommendationSubmissionCycle(self) - else: - self.cycle = GeneralSubmissionCycle(self) + self._update_cycle() + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + self._update_cycle() def __str__(self): header = (self.arxiv_identifier_w_vn_nr + ', ' @@ -113,9 +109,24 @@ class Submission(ArxivCallable, models.Model): pass return header + def _update_cycle(self): + """ + Append the specific submission cycle to the instance to eventually handle the + complete submission cycle outside the submission instance itself. + """ + if self.refereeing_cycle == CYCLE_SHORT: + self.cycle = ShortSubmissionCycle(self) + elif self.refereeing_cycle == CYCLE_DIRECT_REC: + self.cycle = DirectRecommendationSubmissionCycle(self) + else: + self.cycle = GeneralSubmissionCycle(self) + def get_absolute_url(self): return reverse('submissions:submission', args=[self.arxiv_identifier_w_vn_nr]) + def eic_recommendation_required(self): + return self.status not in SUBMISSION_EIC_RECOMMENDATION_REQUIRED + @property def reporting_deadline_has_passed(self): return timezone.now() > self.reporting_deadline @@ -272,6 +283,14 @@ class RefereeInvitation(models.Model): return str(self.referee) return self.last_name + ', ' + self.first_name + def reset_content(self): + self.nr_reminders = 0 + self.date_last_reminded = None + self.accepted = None + self.refusal_reason = None + self.fulfilled = False + self.cancelled = False + ########### # Reports: @@ -351,7 +370,8 @@ class EditorialCommunication(models.Model): # From the Editor-in-charge of a Submission class EICRecommendation(models.Model): - submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE) + submission = models.ForeignKey('submissions.Submission', on_delete=models.CASCADE, + related_name='eicrecommendations') date_submitted = models.DateTimeField('date submitted', default=timezone.now) remarks_for_authors = models.TextField(blank=True, null=True) requested_changes = models.TextField(verbose_name="requested changes", blank=True, null=True) diff --git a/submissions/templates/submissions/_form_submission_cycle_choice.html b/submissions/templates/submissions/_form_submission_cycle_choice.html index 7b3e3f5fda5b721baf256eca8240bfe1d4f25db0..efd28543c1a4c95ecf8bdfaedf681b97fa2e7406 100644 --- a/submissions/templates/submissions/_form_submission_cycle_choice.html +++ b/submissions/templates/submissions/_form_submission_cycle_choice.html @@ -1,6 +1,7 @@ -<form method="post"> +<form method="post" action="{% url 'submissions:cycle_confirmation' submission.arxiv_identifier_w_vn_nr %}"> + {% csrf_token %} <h3 class="mb-2">This submission is a resubmission, please choose which submission cycle to proceed with</h3> - <div class="card-deck" id="id_submission_cycle"> + <div class="card-deck mb-5" id="id_submission_cycle"> {% for choice in form.refereeing_cycle %} <div class="card radio-option" for="{{choice.id_for_label}}" data-reinvite="{% if choice.choice_value == 'direct_rec' %}0{% else %}1{% endif %}"> <div class="card-block text-center"> @@ -53,7 +54,6 @@ <script> $(function(){ - console.log($('#id_submission_cycle .radio-option')); $('#id_submission_cycle .radio-option').on('click', function(){ var el_id = $('#id_submission_cycle .radio-option input[type="radio"]:checked'), radio_cards = $('#id_submission_cycle .radio-option'); diff --git a/submissions/templates/submissions/_submission_refereeing_status.html b/submissions/templates/submissions/_submission_refereeing_status.html index 7e059bd73f33cf19e4c11c935fabcbc6717f0ef5..94e9ba3cbd35ab3eccca9bcba9e3fc9c4d9585d7 100644 --- a/submissions/templates/submissions/_submission_refereeing_status.html +++ b/submissions/templates/submissions/_submission_refereeing_status.html @@ -1,4 +1,6 @@ -<div class="card-block"> - <p class="card-text">Nr referees invited: {{submission.referee_invitations.count}} <span>[{{submission.count_accepted_invitations}} acccepted / {{submission.count_declined_invitations}} declined / {{submission.count_pending_invitations}} response pending]</span></p> - <p class="card-text">Nr reports obtained: {{submission.count_obtained_reports}} [{{submission.count_invited_reports}} invited / {{submission.count_contrib_reports}} contributed], nr refused: {{submission.count_refused_resports}}, nr awaiting vetting: {{submission.count_awaiting_vetting}}</p> -</div> +{% if submission.refereeing_cycle != 'direct_rec' %} + <div class="card-block"> + <p class="card-text">Nr referees invited: {{submission.referee_invitations.count}} <span>[{{submission.count_accepted_invitations}} acccepted / {{submission.count_declined_invitations}} declined / {{submission.count_pending_invitations}} response pending]</span></p> + <p class="card-text">Nr reports obtained: {{submission.count_obtained_reports}} [{{submission.count_invited_reports}} invited / {{submission.count_contrib_reports}} contributed], nr refused: {{submission.count_refused_resports}}, nr awaiting vetting: {{submission.count_awaiting_vetting}}</p> + </div> +{% endif %} diff --git a/submissions/templates/submissions/editorial_page.html b/submissions/templates/submissions/editorial_page.html index a52050e5da183260baf2c442d59ad32ed9e67fdd..2abd377cf7487ddcba7aff7441d3e7d356bbfbe9 100644 --- a/submissions/templates/submissions/editorial_page.html +++ b/submissions/templates/submissions/editorial_page.html @@ -115,76 +115,80 @@ </div> </div> -<div class="row"> - <div class="col-12"> - <h3>Refereeing status summary:</h3> - {% include 'submissions/_submission_refereeing_status.html' with submission=submission %} - </div> -</div> - -<div class="row"> - <div class="col-12"> - <h3 class="mb-2">Detail of refereeing invitations:</h3> - {% include 'submissions/_submission_refereeing_invitations.html' with submission=submission invitations=ref_invitations %} +{% if submission.status == 'resubmitted_incomin' %} + <div class="row"> + <div class="col-12"> + {% include 'submissions/_form_submission_cycle_choice.html' with form=cycle_choice_form submission=submission %} + </div> </div> -</div> +{% else %} -<hr> + {% if submission.refereeing_cycle != 'direct_rec' %} + <div class="row"> + <div class="col-12"> + <h3>Refereeing status summary:</h3> + {% include 'submissions/_submission_refereeing_status.html' with submission=submission %} + </div> + </div> -{% if not submission.is_current %} -<div class="row"> - <div class="col-12"> - <div class="card card-outline-warning"> - <div class="card-block"> - <h3 class="mb-3 font-weight-bold">BEWARE: This is not the editorial page for the current version!</h3> - <p class="mb-0"> - The tools here are thus available only for exceptional circumstances (e.g. vetting a late report on a deprecated version). - <br>Please go to the current version's page using the link at the top. - </p> + <div class="row"> + <div class="col-12"> + <h3 class="mb-2">Detail of refereeing invitations:</h3> + {% include 'submissions/_submission_refereeing_invitations.html' with submission=submission invitations=ref_invitations %} </div> </div> - </div> -</div> -{% endif %} + {% endif %} -{% if submission.status == 'resubmitted_incomin' %} + <hr> + + {% if not submission.is_current %} <div class="row"> <div class="col-12"> - {% include 'submissions/_form_submission_cycle_choice.html' with form=cycle_choice_form %} + <div class="card card-outline-warning"> + <div class="card-block"> + <h3 class="mb-3 font-weight-bold">BEWARE: This is not the editorial page for the current version!</h3> + <p class="mb-0"> + The tools here are thus available only for exceptional circumstances (e.g. vetting a late report on a deprecated version). + <br>Please go to the current version's page using the link at the top. + </p> + </div> + </div> </div> </div> -{% else %} + {% endif %} + <div class="row"> <div class="col-12"> <h3>Actions:</h3> <ul> - <li> - <a href="{% url 'submissions:select_referee' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Select an additional referee</a> (bear in mind flagged referees if any) - </li> - <li>Extend the refereeing deadline (currently {{ submission.reporting_deadline|date:'Y-m-d' }}) by - <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=2 %}">2 days</a>, - <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=7 %}">1 week</a> or - <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=14 %}">2 weeks</a> - {% if submission.reporting_deadline_has_passed %} - <span class="ml-1 label label-sm label-outline-danger">THE REPORTING DEADLINE HAS PASSED</span> - {% endif %} - </li> - <li> - Set refereeing deadline: - <form class="form-inline" action="{% url 'submissions:set_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> - {% csrf_token %}{{ set_deadline_form|bootstrap_inline:'0,12' }} - <div class="ml-2 form-group row"> - <div class="col-12"> - <input class="btn btn-secondary" type="submit" value="Set deadline"/> + {% if submission.refereeing_cycle != 'direct_rec' %} + <li> + <a href="{% url 'submissions:select_referee' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Select an additional referee</a> (bear in mind flagged referees if any) + </li> + <li>Extend the refereeing deadline (currently {{ submission.reporting_deadline|date:'Y-m-d' }}) by + <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=2 %}">2 days</a>, + <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=7 %}">1 week</a> or + <a href="{% url 'submissions:extend_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr days=14 %}">2 weeks</a> + {% if submission.reporting_deadline_has_passed %} + <span class="ml-1 label label-sm label-outline-danger">THE REPORTING DEADLINE HAS PASSED</span> + {% endif %} + </li> + <li> + Set refereeing deadline: + <form class="form-inline" action="{% url 'submissions:set_refereeing_deadline' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}" method="post"> + {% csrf_token %}{{ set_deadline_form|bootstrap_inline:'0,12' }} + <div class="ml-2 form-group row"> + <div class="col-12"> + <input class="btn btn-secondary" type="submit" value="Set deadline"/> + </div> </div> - </div> - </form> - </li> - <li><a href="{% url 'submissions:vet_submitted_reports' %}">Vet submitted Reports</a> ({{ nr_reports_to_vet }})</li> - {% if not submission.reporting_deadline_has_passed %} - <li><a href="{% url 'submissions:close_refereeing_round' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Close the refereeing round</a> (deactivates submission of new Reports and Comments)</li> + </form> + </li> + <li><a href="{% url 'submissions:vet_submitted_reports' %}">Vet submitted Reports</a> ({{ nr_reports_to_vet }})</li> + {% if not submission.reporting_deadline_has_passed %} + <li><a href="{% url 'submissions:close_refereeing_round' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Close the refereeing round</a> (deactivates submission of new Reports and Comments)</li> + {% endif %} {% endif %} - <li>Communicate with a Referee: see the communication block below.</li> <li> <a href="{% url 'submissions:eic_recommendation' arxiv_identifier_w_vn_nr=submission.arxiv_identifier_w_vn_nr %}">Formulate an Editorial Recommendation</a> <p>If you recommend revisions, this will be communicated directly to the Authors, who will be asked to resubmit. diff --git a/submissions/urls.py b/submissions/urls.py index 57c4240a5e94626f2835b5b34a7712c30d894515..d23178730644d792914e5c62c16567da4b44caef 100644 --- a/submissions/urls.py +++ b/submissions/urls.py @@ -69,6 +69,8 @@ urlpatterns = [ views.communication, name='communication'), url(r'^eic_recommendation/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', views.eic_recommendation, name='eic_recommendation'), + url(r'^cycle/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/submit$', views.cycle_form_submit, + name='cycle_confirmation'), # Reports url(r'^submit_report/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', views.submit_report, name='submit_report'), diff --git a/submissions/utils.py b/submissions/utils.py index 968c8ec174f64914958193887f1657100b204ba2..754ea2987158998468ebdc9a805831300e997680 100644 --- a/submissions/utils.py +++ b/submissions/utils.py @@ -4,9 +4,9 @@ from django.core.mail import EmailMessage, EmailMultiAlternatives from django.template import Context, Template from django.utils import timezone -from .constants import STATUS_RESUBMISSION_SCREENING, SUBMISSION_STATUS_OUT_OF_POOL,\ - STATUS_REVISION_REQUESTED -# from .models import EditorialAssignment +from .constants import SUBMISSION_STATUS_OUT_OF_POOL,\ + STATUS_REVISION_REQUESTED, STATUS_EIC_ASSIGNED,\ + STATUS_RESUBMISSION_SCREENING, STATUS_AWAITING_ED_REC from scipost.utils import EMAIL_FOOTER @@ -47,7 +47,7 @@ class BaseSubmissionCycle: ''''Editor-in-charge has requested revision''' return False - if self.submission.eicrecommendation_set.exists(): + if self.submission.eicrecommendations.exists(): '''A Editorial Recommendation has already been submitted. Cycle done.''' return False @@ -93,9 +93,25 @@ class BaseSubmissionCycle: return True + def reinvite_referees(self, referees): + """ + Reinvite referees if allowed. This method does not check if it really is + an reinvitation or just a new invitation. + """ + if self.may_reinvite_referees: + for referee in referees: + invitation = referee + invitation.pk = None # Duplicate, do not remove the old invitation + invitation.submission = self.submission + invitation.reset_content() + invitation.date_invited = timezone.now() + invitation.save() + def update_deadline(self, period=None): - deadline = timezone.now() + datetime.timedelta(days=(period or self.default_days)) + delta_d = period or self.default_days + deadline = timezone.now() + datetime.timedelta(days=delta_d) self.submission.reporting_deadline = deadline + self.submission.save() def get_required_actions(self): '''Return list of the submission its required actions''' @@ -117,6 +133,11 @@ class BaseRefereeSubmissionCycle(BaseSubmissionCycle): This *abstract* submission cycle adds the specific actions needed for submission cycles that require referees to be invited. """ + def update_status(self): + if self.submission.status == STATUS_RESUBMISSION_SCREENING: + self.submission.status = STATUS_EIC_ASSIGNED + self.submission.save() + def _update_actions(self): continue_update = super()._update_actions() if not continue_update: @@ -188,7 +209,22 @@ class DirectRecommendationSubmissionCycle(BaseSubmissionCycle): may_add_referees = False may_reinvite_referees = False minimum_referees = 0 - pass + + def update_status(self): + if self.submission.status == STATUS_RESUBMISSION_SCREENING: + self.submission.status = STATUS_AWAITING_ED_REC + self.submission.save() + + def _update_actions(self): + continue_update = super()._update_actions() + if not continue_update: + return False + + # No EIC Recommendation has been formulated yet + text = 'Formulate an Editorial Recommendation.' + self.required_actions.append(('need_eic_rec', text,)) + + return True class SubmissionUtils(object): @@ -203,6 +239,9 @@ class SubmissionUtils(object): """ Called when a Fellow has accepted or volunteered to become EIC. """ + # Import here due to circular import error + from .models import EditorialAssignment + assignments_to_deprecate = (EditorialAssignment.objects .filter(submission=cls.assignment.submission, accepted=None) .exclude(to=cls.assignment.to)) @@ -216,6 +255,9 @@ class SubmissionUtils(object): Called when the pre-screening has failed. Requires loading 'submission' attribute. """ + # Import here due to circular import error + from .models import EditorialAssignment + assignments_to_deprecate = (EditorialAssignment.objects .filter(submission=cls.submission, accepted=None)) for atd in assignments_to_deprecate: diff --git a/submissions/views.py b/submissions/views.py index 856bdbeb54e7a63453ec9668b7dc24e753b1e521..1f4d44e6ef51911e0c222cd6e60eb36f60b451c1 100644 --- a/submissions/views.py +++ b/submissions/views.py @@ -647,6 +647,24 @@ def editorial_page(request, arxiv_identifier_w_vn_nr): return render(request, 'submissions/editorial_page.html', context) +@login_required +@permission_required_or_403('can_take_editorial_actions', + (Submission, 'arxiv_identifier_w_vn_nr', 'arxiv_identifier_w_vn_nr')) +def cycle_form_submit(request, arxiv_identifier_w_vn_nr): + submission = get_object_or_404(Submission.objects.get_pool(request.user), + arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) + form = SubmissionCycleChoiceForm(request.POST or None, instance=submission) + if form.is_valid(): + submission = form.save() + submission.cycle.update_status() + submission.cycle.update_deadline() + submission.cycle.reinvite_referees(form.cleaned_data['referees_reinvite']) + messages.success(request, ('<h3>Your choice has been confirmed</h3>' + 'The new cycle will be <em>%s</em>' + % submission.get_refereeing_cycle_display())) + return redirect(reverse('submissions:editorial_page', args=[submission.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')) @@ -772,7 +790,6 @@ def send_refereeing_invitation(request, arxiv_identifier_w_vn_nr, contributor_id date_invited=timezone.now(), invited_by=request.user.contributor) invitation.save() - # raise SubmissionUtils.load({'invitation': invitation}) SubmissionUtils.send_refereeing_invitation_email() return redirect(reverse('submissions:editorial_page', @@ -978,11 +995,12 @@ def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None): def eic_recommendation(request, arxiv_identifier_w_vn_nr): submission = get_object_or_404(Submission.objects.get_pool(request.user), arxiv_identifier_w_vn_nr=arxiv_identifier_w_vn_nr) - if submission.status not in ['EICassigned', 'review_closed']: - errormessage = ('This submission\'s current status is: ' + - submission.get_status_display() + '. ' - 'An Editorial Recommendation is not required.') - return render(request, 'scipost/error.html', {'errormessage': errormessage}) + if submission.eic_recommendation_required(): + messages.warning(request, ('<h3>An Editorial Recommendation is not required</h3>' + 'This submission\'s current status is: <em>%s</em>' + % submission.get_status_display())) + return redirect(reverse('scipost:editorial_page', + args=[submission.arxiv_identifier_w_vn_nr])) if request.method == 'POST': form = EICRecommendationForm(request.POST) if form.is_valid():