Newer
Older
from django.core.exceptions import PermissionDenied as DjangoPermissionDenied
from django.db import transaction
from django.utils import timezone
from rest_framework import generics, mixins, permissions
from rest_framework.response import Response
from rest_framework.exceptions import (NotFound, PermissionDenied,
ValidationError)
from rest_framework_api_key.permissions import HasAPIKey
from django_filters import rest_framework as filters
from opentech.apply.funds.models import ApplicationSubmission, RoundsAndLabs
from opentech.apply.funds.workflow import PHASES
from opentech.apply.activity.models import Activity, COMMENT
from opentech.apply.activity.messaging import messenger, MESSAGES
from opentech.apply.determinations.views import DeterminationCreateOrUpdateView
from opentech.apply.funds.models import FundType, LabType
from .pagination import StandardResultsSetPagination
CommentCreateSerializer,
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)
Parbhat Puri
committed
active = filters.BooleanFilter(method='filter_active', label='Active')
submit_date = filters.DateFromToRangeFilter(field_name='submit_time', label='Submit date')
Parbhat Puri
committed
fund = filters.ModelMultipleChoiceFilter(
field_name='page', label='fund',
Parbhat Puri
committed
queryset=Page.objects.type(FundType) | Page.objects.type(LabType)
)
class Meta:
model = ApplicationSubmission
Parbhat Puri
committed
fields = ('status', 'round', 'active', 'submit_date', 'fund', )
Parbhat Puri
committed
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()
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))
# refresh_from_db() raises errors for particular actions.
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()
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())
class Meta:
model = Activity
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,)
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(
type=COMMENT,
user=self.request.user,
source=ApplicationSubmission.objects.get(pk=self.kwargs['pk'])
)
messenger(
MESSAGES.COMMENT,
request=self.request,
user=self.request.user,
related=obj,
)
class CommentEdit(
mixins.RetrieveModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView,
):
queryset = Activity.comments.all().select_related('user')
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
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)