Skip to content
Snippets Groups Projects
views.py 8.12 KiB
Newer Older
  • Learn to ignore specific revisions
  • from django.core.exceptions import PermissionDenied as DjangoPermissionDenied
    
    from django.db import transaction
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
    from django.db.models import Q, Prefetch
    
    from django.utils import timezone
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
    
    from wagtail.core.models import Page
    
    
    from rest_framework import generics, mixins, permissions
    
    from rest_framework.response import Response
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
    from rest_framework.exceptions import (NotFound, PermissionDenied,
                                           ValidationError)
    
    from rest_framework_api_key.permissions import HasAPIKey
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
    from django_filters import rest_framework as filters
    
    from opentech.apply.funds.models import ApplicationSubmission, RoundsAndLabs
    from opentech.apply.funds.workflow import PHASES
    
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
    from opentech.apply.activity.models import Activity, COMMENT
    from opentech.apply.activity.messaging import messenger, MESSAGES
    
    Tomasz Knapik's avatar
    Tomasz Knapik committed
    from opentech.apply.determinations.views import DeterminationCreateOrUpdateView
    
    George Hickman's avatar
    George Hickman committed
    from opentech.apply.review.models import Review
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
    from opentech.apply.funds.models import FundType, LabType
    
    from .pagination import StandardResultsSetPagination
    
    Todd Dembrey's avatar
    Todd Dembrey committed
    from .permissions import IsApplyStaffUser, IsAuthor
    
    from .serializers import (
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
        CommentSerializer,
    
        CommentCreateSerializer,
    
        CommentEditSerializer,
    
    Todd Dembrey's avatar
    Todd Dembrey committed
        RoundLabDetailSerializer,
    
        RoundLabSerializer,
    
        SubmissionActionSerializer,
    
    George Hickman's avatar
    George Hickman committed
        SubmissionListSerializer,
    
    Fredrik Jonsson's avatar
    Fredrik Jonsson committed
        SubmissionDetailSerializer,
    
    class RoundLabFilter(filters.ModelChoiceFilter):
        def filter(self, qs, value):
            if not value:
                return qs
    
            return qs.filter(Q(round=value) | Q(page=value))
    
    
    class SubmissionsFilter(filters.FilterSet):
    
        round = RoundLabFilter(queryset=RoundsAndLabs.objects.all())
    
        status = filters.MultipleChoiceFilter(choices=PHASES)
    
        active = filters.BooleanFilter(method='filter_active', label='Active')
    
        submit_date = filters.DateFromToRangeFilter(field_name='submit_time', label='Submit date')
    
        fund = filters.ModelMultipleChoiceFilter(
    
            field_name='page', label='fund',
    
            queryset=Page.objects.type(FundType) | Page.objects.type(LabType)
        )
    
    
        class Meta:
            model = ApplicationSubmission
    
            fields = ('status', 'round', 'active', 'submit_date', 'fund', )
    
        def filter_active(self, qs, name, value):
    
            if value is None:
                return qs
    
            if value:
                return qs.active()
            else:
                return qs.inactive()
    
    class SubmissionList(generics.ListAPIView):
    
        queryset = ApplicationSubmission.objects.current().with_latest_update()
    
        serializer_class = SubmissionListSerializer
        permission_classes = (
    
            HasAPIKey | permissions.IsAuthenticated, HasAPIKey | IsApplyStaffUser,
    
        filter_backends = (filters.DjangoFilterBackend,)
        filter_class = SubmissionsFilter
    
        pagination_class = StandardResultsSetPagination
    
    
    
    class SubmissionDetail(generics.RetrieveAPIView):
    
        queryset = ApplicationSubmission.objects.all().prefetch_related(
            Prefetch('reviews', Review.objects.submitted()),
        )
    
        serializer_class = SubmissionDetailSerializer
        permission_classes = (
            permissions.IsAuthenticated, IsApplyStaffUser,
        )
    
    class SubmissionAction(generics.RetrieveAPIView):
        queryset = ApplicationSubmission.objects.all()
        serializer_class = SubmissionActionSerializer
        permission_classes = (
            permissions.IsAuthenticated, IsApplyStaffUser,
        )
    
        def post(self, request, *args, **kwargs):
            action = request.data.get('action')
            if not action:
                raise ValidationError('Action must be provided.')
            obj = self.get_object()
    
    Tomasz Knapik's avatar
    Tomasz Knapik committed
    
            redirect = DeterminationCreateOrUpdateView.should_redirect(
                request, obj, action)
            if redirect:
                raise NotFound({
                    'detail': 'The action should be performed at the determination view',
                    'target': redirect.url,
                })
    
            try:
                obj.perform_transition(action, self.request.user, request=self.request)
            except DjangoPermissionDenied as e:
                raise PermissionDenied(str(e))
    
    Tomasz Knapik's avatar
    Tomasz Knapik committed
            # refresh_from_db() raises errors for particular actions.
    
    Tomasz Knapik's avatar
    Tomasz Knapik committed
            obj = self.get_object()
            serializer = SubmissionDetailSerializer(obj, context={
                'request': request,
            })
            return Response({
                'id': serializer.data['id'],
                'status': serializer.data['status'],
                'actions': serializer.data['actions'],
                'phase': serializer.data['phase'],
            })
    
    class RoundLabDetail(generics.RetrieveAPIView):
    
        queryset = RoundsAndLabs.objects.all()
    
    Todd Dembrey's avatar
    Todd Dembrey committed
        serializer_class = RoundLabDetailSerializer
    
        permission_classes = (
            permissions.IsAuthenticated, IsApplyStaffUser,
        )
    
        def get_object(self):
            return super().get_object().specific
    
    
    class RoundLabList(generics.ListAPIView):
        queryset = RoundsAndLabs.objects.specific()
        serializer_class = RoundLabSerializer
        permission_classes = (
            permissions.IsAuthenticated, IsApplyStaffUser,
        )
    
        pagination_class = StandardResultsSetPagination
    
    class NewerThanFilter(filters.ModelChoiceFilter):
        def filter(self, qs, value):
            if not value:
                return qs
    
            return qs.newer(value)
    
    
    
    class CommentFilter(filters.FilterSet):
        since = filters.DateTimeFilter(field_name="timestamp", lookup_expr='gte')
        before = filters.DateTimeFilter(field_name="timestamp", lookup_expr='lte')
    
        newer = NewerThanFilter(queryset=Activity.comments.all())
    
            fields = ['visibility', 'since', 'before', 'newer']
    
    
    class AllCommentFilter(CommentFilter):
        class Meta(CommentFilter.Meta):
    
            fields = CommentFilter.Meta.fields + ['source_object_id']
    
    class CommentList(generics.ListAPIView):
        queryset = Activity.comments.all()
        serializer_class = CommentSerializer
        permission_classes = (
            permissions.IsAuthenticated, IsApplyStaffUser,
        )
        filter_backends = (filters.DjangoFilterBackend,)
    
        filter_class = AllCommentFilter
    
        pagination_class = StandardResultsSetPagination
    
        def get_queryset(self):
            return super().get_queryset().visible_to(self.request.user)
    
    
    
    class CommentListCreate(generics.ListCreateAPIView):
    
        queryset = Activity.comments.all().select_related('user')
    
        serializer_class = CommentCreateSerializer
        permission_classes = (
            permissions.IsAuthenticated, IsApplyStaffUser,
        )
        filter_backends = (filters.DjangoFilterBackend,)
    
        filter_class = CommentFilter
    
        pagination_class = StandardResultsSetPagination
    
        def get_queryset(self):
            return super().get_queryset().filter(
                submission=self.kwargs['pk']
            ).visible_to(self.request.user)
    
        def perform_create(self, serializer):
            obj = serializer.save(
    
                timestamp=timezone.now(),
    
                type=COMMENT,
                user=self.request.user,
    
                source=ApplicationSubmission.objects.get(pk=self.kwargs['pk'])
    
            )
            messenger(
                MESSAGES.COMMENT,
                request=self.request,
                user=self.request.user,
    
                source=obj.submission,
    
    
    
    class CommentEdit(
            mixins.RetrieveModelMixin,
            mixins.CreateModelMixin,
            generics.GenericAPIView,
    ):
    
        queryset = Activity.comments.all().select_related('user')
    
        serializer_class = CommentEditSerializer
        permission_classes = (
            permissions.IsAuthenticated, IsAuthor
        )
    
        def post(self, request, *args, **kwargs):
            return self.edit(request, *args, **kwargs)
    
        @transaction.atomic
        def edit(self, request, *args, **kwargs):
            comment_to_edit = self.get_object()
            comment_to_update = self.get_object()
    
            comment_to_edit.previous = comment_to_update
            comment_to_edit.pk = None
            comment_to_edit.edited = timezone.now()
    
            serializer = self.get_serializer(comment_to_edit, data=request.data)
            serializer.is_valid(raise_exception=True)
    
            if serializer.validated_data['message'] != comment_to_update.message:
                self.perform_create(serializer)
                comment_to_update.current = False
                comment_to_update.save()
                return Response(serializer.data)
    
            return Response(self.get_serializer(comment_to_update).data)