From 2fa47934ad6ed7b9ca68559fcc432dfc64691326 Mon Sep 17 00:00:00 2001
From: Jorran de Wit <jorrandewit@outlook.com>
Date: Tue, 6 Jun 2017 16:23:08 +0200
Subject: [PATCH] Move logic to VetReportForm

---
 submissions/constants.py  |  6 ++--
 submissions/exceptions.py |  8 +++++
 submissions/forms.py      | 64 ++++++++++++++++++++++++++++++++++-----
 3 files changed, 68 insertions(+), 10 deletions(-)

diff --git a/submissions/constants.py b/submissions/constants.py
index 43ce5c8f1..0f6656719 100644
--- a/submissions/constants.py
+++ b/submissions/constants.py
@@ -156,8 +156,8 @@ REPORT_REC = (
 #
 # Reports
 #
-REPORT_ACTION_ACCEPT = 1
-REPORT_ACTION_REFUSE = 2
+REPORT_ACTION_ACCEPT = 'accept'
+REPORT_ACTION_REFUSE = 'refuse'
 REPORT_ACTION_CHOICES = (
     (REPORT_ACTION_ACCEPT, 'accept'),
     (REPORT_ACTION_REFUSE, 'refuse'),
@@ -172,7 +172,7 @@ STATUS_NOT_USEFUL = 'notuseful'
 STATUS_NOT_ACADEMIC = 'notacademic'
 
 REPORT_REFUSAL_CHOICES = (
-    (STATUS_UNVETTED, '-'),
+    (None, '-'),
     (STATUS_UNCLEAR, 'insufficiently clear'),
     (STATUS_INCORRECT, 'not fully factually correct'),
     (STATUS_NOT_USEFUL, 'not useful for the authors'),
diff --git a/submissions/exceptions.py b/submissions/exceptions.py
index 19c5684bd..0e8794a8c 100644
--- a/submissions/exceptions.py
+++ b/submissions/exceptions.py
@@ -4,3 +4,11 @@ class CycleUpdateDeadlineError(Exception):
 
     def __str__(self):
         return self.name
+
+
+class InvalidReportVettingValue(Exception):
+    def __init__(self, name):
+        self.name = name
+
+    def __str__(self):
+        return self.name
diff --git a/submissions/forms.py b/submissions/forms.py
index d5dc7376e..7f2d39772 100644
--- a/submissions/forms.py
+++ b/submissions/forms.py
@@ -1,13 +1,16 @@
 from django import forms
 from django.contrib.auth.models import Group
 from django.db import transaction
+from django.utils import timezone
 
 from guardian.shortcuts import assign_perm
 
 from .constants import ASSIGNMENT_BOOL, ASSIGNMENT_REFUSAL_REASONS, STATUS_RESUBMITTED,\
                        REPORT_ACTION_CHOICES, REPORT_REFUSAL_CHOICES, STATUS_REVISION_REQUESTED,\
                        STATUS_REJECTED, STATUS_REJECTED_VISIBLE, STATUS_RESUBMISSION_INCOMING,\
-                       STATUS_DRAFT, STATUS_UNVETTED
+                       STATUS_DRAFT, STATUS_UNVETTED, REPORT_ACTION_ACCEPT, REPORT_ACTION_REFUSE,\
+                       STATUS_VETTED
+from .exceptions import InvalidReportVettingValue
 from .models import Submission, RefereeInvitation, Report, EICRecommendation, EditorialAssignment
 
 from scipost.constants import SCIPOST_SUBJECT_AREAS
@@ -437,17 +440,35 @@ class ReportForm(forms.ModelForm):
             'cols': 100
         })
 
-    def save(self, commit=False):
+    def save(self, submission, current_contributor):
         """
+        Update meta data if ModelForm is submitted (non-draft).
         Possibly overwrite the default status if user asks for saving as draft.
         """
         report = super().save(commit=False)
+
+        report.submission = submission
+        report.author = current_contributor
+        report.date_submitted = timezone.now()
+
+        # Save with right status asked by user
         if 'save_draft' in self.data:
             report.status = STATUS_DRAFT
         elif 'save_submit' in self.data:
             report.status = STATUS_UNVETTED
-        if commit:
-            report.save()
+
+            # Update invitation and report meta data if exist
+            invitation = submission.referee_invitations.filter(referee=current_contributor).first()
+            if invitation:
+                invitation.fulfilled = True
+                invitation.save()
+                report.invited = True
+
+            # Check if report author if the report is being flagged on the submission
+            if submission.referees_flagged:
+                if current_contributor.user.last_name in submission.referees_flagged:
+                    report.flagged = True
+        report.save()
         return report
 
 
@@ -458,12 +479,41 @@ class VetReportForm(forms.Form):
     refusal_reason = forms.ChoiceField(choices=REPORT_REFUSAL_CHOICES, required=False)
     email_response_field = forms.CharField(widget=forms.Textarea(),
                                            label='Justification (optional)', required=False)
+    report = forms.ModelChoiceField(queryset=Report.objects.awaiting_vetting(), required=True,
+                                    widget=forms.HiddenInput())
 
     def __init__(self, *args, **kwargs):
         super(VetReportForm, self).__init__(*args, **kwargs)
-        self.fields['email_response_field'].widget.attrs.update(
-            {'placeholder': 'Optional: give a textual justification (will be included in the email to the Report\'s author)',
-             'rows': 5})
+        self.fields['email_response_field'].widget.attrs.update({
+            'placeholder': ('Optional: give a textual justification '
+                            '(will be included in the email to the Report\'s author)'),
+            'rows': 5
+        })
+
+    def clean_refusal_reason(self):
+        '''Require a refusal reason if report is rejected.'''
+        reason = self.cleaned_data['refusal_reason']
+        if self.cleaned_data['action_option'] == REPORT_ACTION_REFUSE:
+            if not reason:
+                self.add_error('refusal_reason', 'A reason must be given to refuse a report.')
+        return reason
+
+    def process_vetting(self, current_contributor):
+        '''Set the right report status and update submission fields if needed.'''
+        report = self.cleaned_data['report']
+        report.vetted_by = current_contributor
+        if self.cleaned_data['action_option'] == REPORT_ACTION_ACCEPT:
+            # Accept the report as is
+            report.status = STATUS_VETTED
+            report.submission.latest_activity = timezone.now()
+            report.submission.save()
+        elif self.cleaned_data['action_option'] == REPORT_ACTION_REFUSE:
+            # The report is rejected
+            report.status = self.cleaned_data['refusal_reason']
+        else:
+            raise InvalidReportVettingValue(self.cleaned_data['action_option'])
+        report.save()
+        return report
 
 
 ###################
-- 
GitLab