From ab5a3e5591b0a950c7d6f9e03bcdadeb72df3014 Mon Sep 17 00:00:00 2001
From: "J.-S. Caux" <J.S.Caux@uva.nl>
Date: Sun, 10 Apr 2016 17:57:47 +0200
Subject: [PATCH] Building up editorial workflow: EIC and referee selection
 done

---
 .../commands/add_groups_and_permissions.py    | 30 +++++++++++++++----
 scipost/templates/scipost/personal_page.html  |  5 ++--
 scipost/views.py                              |  4 +--
 submissions/models.py                         |  7 +++++
 .../templates/submissions/editorial_page.html | 24 +++++++++++----
 .../templates/submissions/select_referee.html |  2 ++
 .../submissions/submission_detail.html        |  3 ++
 submissions/views.py                          | 23 ++++++++++++--
 8 files changed, 81 insertions(+), 17 deletions(-)

diff --git a/scipost/management/commands/add_groups_and_permissions.py b/scipost/management/commands/add_groups_and_permissions.py
index d59952054..656f94769 100644
--- a/scipost/management/commands/add_groups_and_permissions.py
+++ b/scipost/management/commands/add_groups_and_permissions.py
@@ -29,6 +29,20 @@ class Command(BaseCommand):
             name= 'Can manage registration invitations',
             content_type=content_type)
 
+        # Contributions (not related to submissions)
+        can_submit_comments, created = Permission.objects.get_or_create(
+            codename='can_submit_comments',
+            name= 'Can submit Comments',
+            content_type=content_type)
+        can_request_commentary_pages, created = Permission.objects.get_or_create(
+            codename='can_request_commentary_pages',
+            name= 'Can request opening of Commentara Pages',
+            content_type=content_type)
+        can_request_thesislinks, created = Permission.objects.get_or_create(
+            codename='can_request_thesislinks',
+            name= 'Can request Thesis Links',
+            content_type=content_type)
+
         # Vetting of simple objects
         can_vet_commentary_requests, created = Permission.objects.get_or_create(
             codename='can_vet_commentary_requests',
@@ -54,19 +68,25 @@ class Command(BaseCommand):
             content_type=content_type)
 
         # Submission handling
-        can_process_incoming_submissions, created = Permission.objects.get_or_create(
-            codename='can_process_incoming_submissions',
-            name= 'Can process incoming Submissions',
+        can_assign_submissions, created = Permission.objects.get_or_create(
+            codename='can_assign_submissions',
+            name= 'Can assign incoming Submissions to potential Editor-in-charge',
             content_type=content_type)
         can_take_charge_of_submissions, created = Permission.objects.get_or_create(
             codename='can_take_charge_of_submissions',
-            name= 'Can take charge of submissions',
+            name= 'Can take charge (become Editor-in-charge) of submissions',
             content_type=content_type)
         can_vet_submitted_reports, created = Permission.objects.get_or_create(
             codename='can_vet_submitted_reports', 
             name='Can vet submitted Reports', 
             content_type=content_type)
 
+        # Refereeing
+        can_referee, created = Permission.objects.get_or_create(
+            codename='can_referee',
+            name= 'Can act as a referee and submit reports on Submissions',
+            content_type=content_type)
+
         # Assign permissions to groups
         SciPostAdmin.permissions.add(can_manage_registration_invitations,
                                      can_vet_registration_requests,
@@ -74,7 +94,7 @@ class Command(BaseCommand):
                                      can_vet_thesislink_requests,
                                      can_vet_authorship_claims, 
                                      can_vet_comments,
-                                     can_process_incoming_submissions,
+                                     can_assign_submissions,
                                      )
         EditorialCollege.permissions.add(can_take_charge_of_submissions,
                                          can_vet_submitted_reports,
diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html
index af7fbde9a..dcbfd1a99 100644
--- a/scipost/templates/scipost/personal_page.html
+++ b/scipost/templates/scipost/personal_page.html
@@ -127,7 +127,7 @@
   <div class="col-4">
     <h3>Submissions assignments</h3>
     <ul>
-      {% if perms.scipost.can_process_incoming_submissions %}
+      {% if perms.scipost.can_assign_submissions %}
       <li><a href="{% url 'submissions:assign_submissions' %}">Assign SciPost Submissions</a> ({{ nr_submissions_to_assign }})</li>
       {% endif %}
       {% if perms.scipost.can_take_charge_of_submissions %}
@@ -148,6 +148,7 @@
 </section>
 {% endif %}
 
+{% if perms.scipost.can_referee %}
 <section>
   <hr class="hr12">
   <div class="flex-greybox">
@@ -164,8 +165,8 @@
     {% endfor %}
   </ul>
   {% endif %}
-  
 </section>
+{% endif %}
 
 <section>
   <hr class="hr12">
diff --git a/scipost/views.py b/scipost/views.py
index 4579f0ed7..3c95c514e 100644
--- a/scipost/views.py
+++ b/scipost/views.py
@@ -200,7 +200,7 @@ def request_new_activation_link(request, oldkey):
     return render (request, 'scipost/request_new_activation_link_ack.html')
 
 
-@permission_required('scipost.can_vet_registration_requests')
+@permission_required('scipost.can_vet_registration_requests', raise_exception=True)
 def vet_registration_requests(request):
     contributor = Contributor.objects.get(user=request.user)
     contributors_to_vet = Contributor.objects.filter(user__is_active=True, status=0).order_by('key_expires')
@@ -209,7 +209,7 @@ def vet_registration_requests(request):
     context = {'contributors_to_vet': contributors_to_vet, 'form': form }
     return render(request, 'scipost/vet_registration_requests.html', context)
 
-@permission_required('scipost.can_vet_registration_requests')
+@permission_required('scipost.can_vet_registration_requests', raise_exception=True)
 def vet_registration_request_ack(request, contributor_id):
     # process the form
     if request.method == 'POST':
diff --git a/submissions/models.py b/submissions/models.py
index f00e94e89..1c1bb9171 100644
--- a/submissions/models.py
+++ b/submissions/models.py
@@ -42,6 +42,7 @@ SUBMISSION_ACTION_REQUIRED = (
 class Submission(models.Model):
     submitted_by = models.ForeignKey(Contributor)
     assigned = models.BooleanField(default=False)
+    editor_in_charge = models.ForeignKey(Contributor, related_name='EIC', blank=True, null=True)
     submitted_to_journal = models.CharField(max_length=30, choices=SCIPOST_JOURNALS_SUBMIT, verbose_name="Journal to be submitted to")
     discipline = models.CharField(max_length=20, choices=SCIPOST_DISCIPLINES, default='physics')
     domain = models.CharField(max_length=3, choices=SCIPOST_JOURNALS_DOMAINS)
@@ -64,6 +65,12 @@ class Submission(models.Model):
     def __str__ (self):
         return self.title
 
+    @property
+    def reporting_deadline_has_passed(self):
+        if timezone.now() > self.reporting_deadline:
+            return True
+        return False
+
     def header_as_table (self):
         # for Submission page
         header = '<table>'
diff --git a/submissions/templates/submissions/editorial_page.html b/submissions/templates/submissions/editorial_page.html
index bae5c49c7..d39d82d72 100644
--- a/submissions/templates/submissions/editorial_page.html
+++ b/submissions/templates/submissions/editorial_page.html
@@ -16,6 +16,7 @@
 <section>
   <div class="flex-greybox">
     <h1>Editorial Page for Submission</h1>
+    <h3>(go to the <a href="{% url 'submissions:submission' submission_id=submission.id %}">Submissions Page</a> to view Reports and Comments)</h3>
   </div>
 
   <hr class="hr12">
@@ -38,22 +39,35 @@
   <h3>Status:</h3>
   {{ submission.status_info_as_table }}
 
+  <hr class="hr6"/>
   <h3>Actions:</h3>
   <ul>
     <li><a href="{% url 'submissions:select_referee' submission_id=submission.id %}">Select an additional referee</a></li>
+    <li>Extend the reporting deadline
+      (currently {{ submission.reporting_deadline }})
+      {% if submission.reporting_deadline_has_passed %}
+      <b style="color: red">THE REPORTING DEADLINE HAS PASSED</b>
+      {% endif %}
+      </li>
+    {% if not submission.reporting_deadline_has_passed %}
     <li><a href="{% url 'submissions:close_refereeing_round' submission_id=submission.id %}">Close the refereeing round</a></li>
+    {% endif %}
+    <li>Request author response to Reports and Comments</li>
+    <li>Formulate an Editorial Recommendation and send it to Editorial College for ratification</li>
+    <li>Inform authors of Editorial Decisions</li>
   </ul>
-</section>
 
-<section>
-  <div class="flex-greybox">
-    <h1>Refereeing invitations</h1>
-  </div>
+  <hr class="hr6"/>
+  <h3>Refereeing invitations</h3>
+  {% if ref_invitations %}
   <ul>
     {% for invitation in ref_invitations %}
     {{ invitation.summary_as_li }}
     {% endfor %}
   </ul>
+  {% else %}
+  <p>You have not invited any referees yet.</p>
+  {% endif %}
 </section>
 
 {% endif %} <!-- Temporary strip -->
diff --git a/submissions/templates/submissions/select_referee.html b/submissions/templates/submissions/select_referee.html
index f25bfd342..2344cd950 100644
--- a/submissions/templates/submissions/select_referee.html
+++ b/submissions/templates/submissions/select_referee.html
@@ -16,6 +16,8 @@
 <section>
   <div class="flex-greybox">
     <h1>Referee Selection Page for Submission</h1>
+    <h3>(go to the <a href="{% url 'submissions:submission' submission_id=submission.id %}">Submissions Page</a> to view Reports and Comments)</h3>
+    <h3>(go back to the <a href="{% url 'submissions:editorial_page' submission_id=submission.id %}">Editorial Page</a> to take editorial actions)</h3>
   </div>
 
   <hr class="hr12">
diff --git a/submissions/templates/submissions/submission_detail.html b/submissions/templates/submissions/submission_detail.html
index 267adef6c..bc26873ce 100644
--- a/submissions/templates/submissions/submission_detail.html
+++ b/submissions/templates/submissions/submission_detail.html
@@ -30,6 +30,9 @@
 <section>
   <div class="flex-greybox">
     <h1>SciPost Submission Page &nbsp; (for papers submitted to SciPost)</h1>
+    {% if user.contributor == submission.editor_in_charge %}
+    <h3>(You are the Editor-in-charge, go to the <a href="{% url 'submissions:editorial_page' submission_id=submission.id %}">Editorial Page</a> to take editorial actions)</h3>
+    {% endif %}
   </div>
 
   <hr class="hr12">
diff --git a/submissions/views.py b/submissions/views.py
index 9378dbe78..44f22698b 100644
--- a/submissions/views.py
+++ b/submissions/views.py
@@ -26,7 +26,6 @@ from comments.forms import CommentForm
 # SUBMISSIONS:
 ###############
 
-#@permission_required('scipost.can_submit_manuscript', raise_exception=True)
 def submit_manuscript(request):
     if request.method == 'POST':
         form = SubmissionForm(request.POST)
@@ -152,7 +151,7 @@ def submission_detail(request, submission_id):
 # Editorial workflow #
 ######################
 
-
+@permission_required('scipost.can_assign_submissions', raise_exception=True)
 def assign_submissions(request):
     submission_to_assign = Submission.objects.filter(status='unassigned').first() # only handle one at at time
     if submission_to_assign is not None:
@@ -164,6 +163,7 @@ def assign_submissions(request):
     return render(request, 'submissions/assign_submissions.html', context)
 
 
+@permission_required('scipost.can_assign_submissions', raise_exception=True)
 def assign_submission_ack(request, submission_id):
     submission = Submission.objects.get(pk=submission_id)
     if request.method == 'POST':
@@ -175,7 +175,6 @@ def assign_submission_ack(request, submission_id):
                                                 date_created=timezone.now())
             ed_assignment.save()
             submission.assigned = True
-            submission.assignment = ed_assignment
             submission.status = 'assigned'
             submission.latest_activity = timezone.now()
             submission.save()
@@ -183,6 +182,7 @@ def assign_submission_ack(request, submission_id):
     return render(request, 'submissions/assign_submission_ack.html', context)
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def accept_or_decline_assignments(request):
     contributor = Contributor.objects.get(user=request.user)
     assignment = EditorialAssignment.objects.filter(to=contributor, accepted=None).first()
@@ -191,6 +191,7 @@ def accept_or_decline_assignments(request):
     return render(request, 'submissions/accept_or_decline_assignments.html', context)
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def accept_or_decline_assignment_ack(request, assignment_id):
     contributor = Contributor.objects.get(user=request.user)
     assignment = get_object_or_404 (EditorialAssignment, pk=assignment_id)
@@ -198,10 +199,15 @@ def accept_or_decline_assignment_ack(request, assignment_id):
         form = ConsiderAssignmentForm(request.POST)
         if form.is_valid():
             assignment.date_answered = timezone.now()
+            deadline = timezone.now() + datetime.timedelta(days=28) # for papers
+            if assignment.submission.submitted_to_journal == 'SciPost Physics Lecture Notes':
+                deadline += datetime.timedelta(days=28)
             if form.cleaned_data['accept'] == 'True':
                 assignment.accepted = True
                 assignment.to = contributor
                 assignment.submission.status = 'EICassigned'
+                assignment.submission.editor_in_charge = contributor
+                assignment.submission.reporting_deadline = deadline
                 assignment.submission.save()
             else:
                 assignment.accepted = False
@@ -212,13 +218,16 @@ def accept_or_decline_assignment_ack(request, assignment_id):
     return render(request, 'submissions/accept_or_decline_assignment_ack.html', context)
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def editorial_page(request, submission_id):
     submission = get_object_or_404(Submission, pk=submission_id)
     ref_invitations = RefereeInvitation.objects.filter(submission=submission)
+    
     context = {'submission': submission, 'ref_invitations': ref_invitations}
     return render(request, 'submissions/editorial_page.html', context)
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def select_referee(request, submission_id):
     submission = get_object_or_404(Submission, pk=submission_id)
     if request.method == 'POST':
@@ -234,6 +243,7 @@ def select_referee(request, submission_id):
     return render(request, 'submissions/select_referee.html', context)
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def recruit_referee(request, submission_id):
     """
     If the Editor-in-charge does not find the desired referee among Contributors,
@@ -279,6 +289,7 @@ def recruit_referee(request, submission_id):
     return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id}))
 
             
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def send_refereeing_invitation(request, submission_id, contributor_id):
     submission = get_object_or_404(Submission, pk=submission_id)
     contributor = get_object_or_404(Contributor, pk=contributor_id)
@@ -292,6 +303,7 @@ def send_refereeing_invitation(request, submission_id, contributor_id):
     return redirect(reverse('submissions:editorial_page', kwargs={'submission_id': submission_id}))
 
 
+@permission_required('scipost.can_referee', raise_exception=True)
 def accept_or_decline_ref_invitations(request):
     contributor = Contributor.objects.get(user=request.user)
     invitation = RefereeInvitation.objects.filter(referee=contributor, accepted=None).first()
@@ -300,6 +312,7 @@ def accept_or_decline_ref_invitations(request):
     return render(request, 'submissions/accept_or_decline_ref_invitations.html', context)
 
 
+@permission_required('scipost.can_referee', raise_exception=True)
 def accept_or_decline_ref_invitation_ack(request, invitation_id):
     contributor = Contributor.objects.get(user=request.user)
     invitation = get_object_or_404 (RefereeInvitation, pk=invitation_id)
@@ -318,6 +331,7 @@ def accept_or_decline_ref_invitation_ack(request, invitation_id):
     return render(request, 'submissions/accept_or_decline_ref_invitation_ack.html', context)
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def close_refereeing_round(request, submission_id):
     submission = get_object_or_404 (Submission, pk=submission_id)
     submission.open_for_reporting = False
@@ -331,6 +345,7 @@ def close_refereeing_round(request, submission_id):
 # Reports
 ###########
 
+@permission_required('scipost.can_referee', raise_exception=True)
 def submit_report(request, submission_id):
     submission = get_object_or_404 (Submission, pk=submission_id)
     if request.method == 'POST':
@@ -374,6 +389,7 @@ def submit_report(request, submission_id):
     return render(request, 'submissions/submit_report.html', context)
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def vet_submitted_reports(request):
     contributor = Contributor.objects.get(user=request.user)
     report_to_vet = Report.objects.filter(status=0).first() # only handle one at a time
@@ -382,6 +398,7 @@ def vet_submitted_reports(request):
     return(render(request, 'submissions/vet_submitted_reports.html', context))
 
 
+@permission_required('scipost.can_take_charge_of_submissions', raise_exception=True)
 def vet_submitted_report_ack(request, report_id):
     if request.method == 'POST':
         form = VetReportForm(request.POST)
-- 
GitLab