from django.core.exceptions import PermissionDenied from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.urls import reverse_lazy from django.utils.decorators import method_decorator from django.views.generic import CreateView, ListView, DetailView, UpdateView from opentech.apply.funds.models import ApplicationSubmission from opentech.apply.users.decorators import staff_required from .forms import ConceptReviewForm, ProposalReviewForm from .models import Review class ReviewContextMixin: def get_context_data(self, **kwargs): staff_reviews = self.object.reviews.by_staff() reviewer_reviews = self.object.reviews.by_reviewers().exclude(id__in=staff_reviews) return super().get_context_data( staff_reviews=staff_reviews, reviewer_reviews=reviewer_reviews, **kwargs, ) def get_form_for_stage(submission): forms = [ConceptReviewForm, ProposalReviewForm] index = [ i for i, stage in enumerate(submission.workflow.stages) if submission.stage.name == stage.name ][0] return forms[index] class ReviewCreateView(CreateView): model = Review def dispatch(self, request, *args, **kwargs): self.submission = get_object_or_404(ApplicationSubmission, id=self.kwargs['submission_pk']) if not self.submission.phase.has_perm(request.user, 'review') or not self.submission.has_permission_to_review(request.user): raise PermissionDenied() if self.request.POST and self.submission.reviewed_by(request.user): return self.get(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): has_submitted_review = self.submission.reviewed_by(self.request.user) return super().get_context_data( submission=self.submission, has_submitted_review=has_submitted_review, **kwargs ) def get_form_class(self): return get_form_for_stage(self.submission) def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['request'] = self.request kwargs['submission'] = self.submission return kwargs def get_success_url(self): return self.submission.get_absolute_url() class ReviewDraftEditView(UpdateView): model = Review def dispatch(self, request, *args, **kwargs): self.submission = get_object_or_404(ApplicationSubmission, id=self.kwargs['submission_pk']) if not self.get_object().is_draft \ or not self.submission.phase.has_perm(request.user, 'review') \ or not self.submission.has_permission_to_review(request.user): raise PermissionDenied() if self.request.POST and self.submission.reviewed_by(request.user): return self.get(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): has_submitted_review = self.submission.reviewed_by(self.request.user) return super().get_context_data( submission=self.submission, has_submitted_review=has_submitted_review, title="Update Review draft", **kwargs ) def get_form_class(self): return get_form_for_stage(self.submission) def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['request'] = self.request kwargs['submission'] = self.submission kwargs['initial'] = self.object.review kwargs['initial']['recommendation'] = self.object.recommendation return kwargs def get_success_url(self): return self.submission.get_absolute_url() class ReviewDetailView(DetailView): model = Review def dispatch(self, request, *args, **kwargs): review = self.get_object() author = review.author if request.user != author and not request.user.is_superuser and request.user != review.submission.lead: raise PermissionDenied if review.is_draft: return HttpResponseRedirect(reverse_lazy('apply:reviews:draft', args=(review.submission.id, review.id))) return super().dispatch(request, *args, **kwargs) def get_context_data(self, **kwargs): review = self.get_object().review form_used = get_form_for_stage(self.get_object().submission) review_data = {} for name, field in form_used.base_fields.items(): try: # Add titles which exist title = form_used.titles[field.group] review_data.setdefault(title, []) except AttributeError: pass value = review[name] try: choices = dict(field.choices) except AttributeError: pass else: # Update the stored value to the display value value = choices[int(value)] review_data.setdefault(field.label, str(value)) return super().get_context_data( review_data=review_data, **kwargs ) @method_decorator(staff_required, name='dispatch') class ReviewListView(ListView): model = Review def get_queryset(self): self.submission = get_object_or_404(ApplicationSubmission, id=self.kwargs['submission_pk']) self.queryset = self.model.objects.filter(submission=self.submission) return super().get_queryset() def get_context_data(self, **kwargs): form_used = get_form_for_stage(self.submission) review_data = {} for review in self.object_list: # Add the name header row review_data.setdefault('', []).append(str(review.author)) review_data.setdefault('Score', []).append(str(review.score)) for name, field in form_used.base_fields.items(): try: # Add titles which exist title = form_used.titles[field.group] review_data.setdefault(title, []) except AttributeError: pass for review in self.object_list: value = review.review[name] try: choices = dict(field.choices) except AttributeError: pass else: # Update the stored value to the display value value = choices[int(value)] review_data.setdefault(field.label, []).append(str(value)) return super().get_context_data( submission=self.submission, review_data=review_data, **kwargs )