You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
721 lines
26 KiB
721 lines
26 KiB
import json
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.db.models import Q
|
|
from rest_framework import status, views, viewsets, generics, mixins
|
|
from rest_framework.decorators import detail_route, list_route, action, permission_classes, authentication_classes
|
|
from rest_framework.response import Response
|
|
|
|
from . import ExtendedModelViewSet
|
|
|
|
from .serializers.config import ConfigSerializer
|
|
from .serializers.course import (
|
|
CategorySerializer, LikeSerializer,
|
|
CourseSerializer, CourseCreateSerializer,
|
|
CourseBulkChangeCategorySerializer,
|
|
CommentSerializer, CommentCreateSerializer,
|
|
MaterialSerializer, MaterialCreateSerializer,
|
|
LessonSerializer, LessonCreateSerializer,
|
|
LikeCreateSerializer, CourseCommentSerializer, LessonCommentSerializer,
|
|
LiveLessonCommentSerializer,)
|
|
from .serializers.content import (
|
|
BanerSerializer,
|
|
ImageSerializer, ImageCreateSerializer,
|
|
TextSerializer, TextCreateSerializer,
|
|
ImageTextSerializer, ImageTextCreateSerializer,
|
|
VideoSerializer, VideoCreateSerializer,
|
|
GallerySerializer,
|
|
GalleryImageSerializer, GalleryImageCreateSerializer,
|
|
ImageObjectSerializer,
|
|
)
|
|
from .serializers.school import (
|
|
SchoolScheduleSerializer,
|
|
LiveLessonCreateSerializer,
|
|
LiveLessonSerializer,
|
|
)
|
|
from .serializers.payment import (
|
|
AuthorBalanceSerializer, AuthorBalanceCreateSerializer,
|
|
PaymentSerializer,
|
|
CoursePaymentCreateSerializer, SchoolPaymentCreateSerializer)
|
|
from .serializers.user import (
|
|
AuthorRequestSerializer,
|
|
UserSerializer, UserPhotoSerializer,
|
|
UserGallerySerializer, UserGalleryUpdateSerializer)
|
|
from .serializers.contest import (
|
|
ContestCreateSerializer, ContestSerializer, ContestWorkSerializer, ContestWorkCreateSerializer
|
|
)
|
|
|
|
from .permissions import (
|
|
IsAdmin,
|
|
IsAuthorOrAdmin, IsAuthorObjectOrAdmin,
|
|
IsTeacherOrAdmin,
|
|
)
|
|
|
|
from apps.course.models import (
|
|
Category, Course,
|
|
Comment, CourseComment, LessonComment,
|
|
Material, Lesson,
|
|
Like,
|
|
LiveLessonComment)
|
|
from apps.config.models import Config
|
|
from apps.content.models import (
|
|
Baner, Image, Text, ImageText, Video,
|
|
Gallery, GalleryImage, ImageObject,
|
|
Contest, ContestWork)
|
|
from apps.payment.models import (
|
|
AuthorBalance, Payment,
|
|
CoursePayment, SchoolPayment,
|
|
)
|
|
from apps.school.models import SchoolSchedule, LiveLesson
|
|
from apps.user.models import AuthorRequest
|
|
from project.pusher import pusher
|
|
from project.sengrid import get_sendgrid_client
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class AuthorBalanceViewSet(ExtendedModelViewSet):
|
|
queryset = AuthorBalance.objects.filter(
|
|
Q(type=1) | Q(payment__status__in=Payment.PW_PAID_STATUSES),
|
|
# author__role__in=[User.AUTHOR_ROLE, User.ADMIN_ROLE, User.TEACHER_ROLE],
|
|
)
|
|
serializer_class = AuthorBalanceCreateSerializer
|
|
serializer_class_map = {
|
|
'list': AuthorBalanceSerializer,
|
|
}
|
|
permission_classes = (IsAdmin,)
|
|
filter_fields = ('author', 'status', 'type')
|
|
search_fields = (
|
|
'author__email',
|
|
'author__first_name',
|
|
'author__last_name',
|
|
)
|
|
|
|
def list(self, request, *args, **kwargs):
|
|
queryset = self.filter_queryset(self.get_queryset())
|
|
|
|
if request.query_params.get('page'):
|
|
page = self.paginate_queryset(queryset)
|
|
if page is not None:
|
|
serializer = self.get_serializer(page, many=True)
|
|
return self.get_paginated_response(serializer.data)
|
|
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(methods=['post'], detail=False, url_path='add-withdrawal')
|
|
def add_withdrawal(self, request):
|
|
author_id = request.data.get('author_id')
|
|
amount = request.data.get('amount')
|
|
card = request.data.get('card')
|
|
if not all([author_id, amount,]):
|
|
return Response(status=status.HTTP_400_BAD_REQUEST)
|
|
AuthorBalance.objects.create(
|
|
author_id=author_id,
|
|
type=AuthorBalance.OUT,
|
|
amount=Decimal(amount),
|
|
status=AuthorBalance.ACCEPTED,
|
|
card=card,
|
|
)
|
|
return Response(status=status.HTTP_200_OK)
|
|
|
|
|
|
class AuthorBalanceUsersViewSet(views.APIView):
|
|
|
|
def get(self, request):
|
|
users = AuthorBalance.objects.filter(amount__gt=0).values_list('author', flat=True)
|
|
users = User.objects.filter(id__in=users, is_active=True).order_by('first_name', 'last_name')
|
|
return Response(UserSerializer(users, many=True).data)
|
|
|
|
|
|
class BanerViewSet(ExtendedModelViewSet):
|
|
queryset = Baner.objects.all()
|
|
serializer_class = BanerSerializer
|
|
permission_classes = (IsAdmin,)
|
|
filter_fields = ('use',)
|
|
ordering_fields = ('created_at', 'update_at',)
|
|
search_fields = ('text',)
|
|
|
|
def perform_create(self, serializer):
|
|
files = dict()
|
|
for k, v in self.request.FILES.items():
|
|
if v:
|
|
files[k] = v
|
|
serializer.save(**files)
|
|
|
|
def perform_update(self, serializer):
|
|
files = dict()
|
|
for k, v in self.request.FILES.items():
|
|
if v:
|
|
files[k] = v
|
|
serializer.save(**files)
|
|
|
|
|
|
class ImageObjectViewSet(ExtendedModelViewSet):
|
|
queryset = ImageObject.objects.all()
|
|
serializer_class = ImageObjectSerializer
|
|
# FIXME
|
|
authentication_classes = []
|
|
# permission_classes = (IsAuthorOrAdmin,)
|
|
|
|
|
|
class MaterialViewSet(ExtendedModelViewSet):
|
|
queryset = Material.objects.all()
|
|
serializer_class = MaterialCreateSerializer
|
|
serializer_class_map = {
|
|
'list': MaterialSerializer,
|
|
'retrieve': MaterialSerializer,
|
|
}
|
|
search_fields = ('title', 'short_description',)
|
|
ordering_fields = ('title', 'created_at', 'update_at',)
|
|
# permission_classes = (IsAdmin,)
|
|
|
|
|
|
class LikeViewSet(ExtendedModelViewSet):
|
|
OBJ_TYPE_CONTEST_WORK = 'contest_work'
|
|
|
|
queryset = Like.objects.select_related('user').all()
|
|
serializer_class = LikeCreateSerializer
|
|
serializer_class_map = {
|
|
'list': LikeSerializer,
|
|
'retrieve': LikeSerializer,
|
|
}
|
|
search_fields = ('user__email', 'user__firstname', 'user__lastname',)
|
|
ordering_fields = ('created_at', 'update_at',)
|
|
# permission_classes = (IsAdmin,)
|
|
# FIXME
|
|
authentication_classes = []
|
|
|
|
def create(self, request, *args, **kwargs):
|
|
serializer = self.get_serializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
obj_type = request.data.get('obj_type')
|
|
obj_id = request.data.get('obj_id')
|
|
user = serializer.validated_data.get('user')
|
|
if not user.is_active: # FIXME and user.is_authenticated):
|
|
return Response(status=status.HTTP_403_FORBIDDEN)
|
|
if obj_type == self.OBJ_TYPE_CONTEST_WORK:
|
|
contest_work = ContestWork.objects.get(pk=obj_id)
|
|
if contest_work.user == user:
|
|
return Response({'error': u'Нельзя голосовать за свою работу'}, status=status.HTTP_400_BAD_REQUEST)
|
|
if contest_work.likes.filter(user=user).exists():
|
|
return Response({'error': u'Вы уже голосовали за эту работу'}, status=status.HTTP_400_BAD_REQUEST)
|
|
if contest_work.contest.finished:
|
|
return Response({'error': u'Голосование закончено'}, status=status.HTTP_400_BAD_REQUEST)
|
|
instance = serializer.save()
|
|
if obj_type == self.OBJ_TYPE_CONTEST_WORK:
|
|
contest_work.likes.add(instance)
|
|
headers = self.get_success_headers(serializer.data)
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
|
|
|
|
|
class CategoryViewSet(ExtendedModelViewSet):
|
|
queryset = Category.objects.order_by('-id')
|
|
serializer_class = CategorySerializer
|
|
search_fields = ('title',)
|
|
ordering_fields = ('title',)
|
|
# permission_classes = (IsAdmin,)
|
|
|
|
|
|
class CourseViewSet(ExtendedModelViewSet):
|
|
queryset = Course.objects.select_related(
|
|
'author', 'category', 'cover', 'gallery',
|
|
).prefetch_related(
|
|
'likes', 'materials', 'content',
|
|
).all()
|
|
serializer_class = CourseCreateSerializer
|
|
serializer_class_map = {
|
|
'list': CourseSerializer,
|
|
'retrieve': CourseSerializer,
|
|
'draft': CourseSerializer,
|
|
'change_category_bulk': CourseBulkChangeCategorySerializer,
|
|
}
|
|
filter_fields = ('category', 'status', 'is_infinite', 'is_featured',)
|
|
search_fields = ('author__email', 'title', 'category__title',)
|
|
ordering_fields = ('id', 'title', 'created_at', 'update_at',)
|
|
# permission_classes = (IsAuthorObjectOrAdmin,)
|
|
# permission_map = {
|
|
# 'create': IsAuthorOrAdmin,
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
def list(self, request, *args, **kwargs):
|
|
queryset = self.filter_queryset(self.get_queryset())
|
|
|
|
if request.query_params.get('page'):
|
|
page = self.paginate_queryset(queryset)
|
|
if page is not None:
|
|
serializer = self.get_serializer(page, many=True)
|
|
return self.get_paginated_response(serializer.data)
|
|
else:
|
|
return Response({'results': []})
|
|
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@list_route(methods=['get'])
|
|
def draft(self, request):
|
|
drafts = Course.objects.filter(author=request.user, status=Course.DRAFT)
|
|
serializer = self.get_serializer_class()
|
|
serialized_data = serializer(instance=drafts.last())
|
|
return Response(serialized_data.data)
|
|
|
|
@list_route(methods=['patch'], url_path='change-category-bulk')
|
|
def change_category_bulk(self, request):
|
|
serializer_class = self.get_serializer_class()
|
|
serializer = serializer_class(data=request.data)
|
|
if serializer.is_valid():
|
|
old_category_id = serializer.validated_data['old_category']
|
|
new_category_id = serializer.validated_data['new_category']
|
|
try:
|
|
old_category = Category.objects.get(id=old_category_id)
|
|
except Category.DoesNotExist:
|
|
return Response(
|
|
{'success': False, 'detail': f'Category with id {old_category_id} not found'},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
try:
|
|
new_category = Category.objects.get(id=new_category_id)
|
|
except Category.DoesNotExist:
|
|
return Response(
|
|
{'success': False, 'detail': f'Category with id {new_category_id} not found'},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
c = Course.objects.filter(
|
|
category=old_category,
|
|
).update(
|
|
category=new_category
|
|
)
|
|
return Response({'success': True})
|
|
else:
|
|
return Response(
|
|
{'success': False},
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
)
|
|
|
|
|
|
class LessonViewSet(ExtendedModelViewSet):
|
|
queryset = Lesson.objects.select_related(
|
|
'course', 'cover'
|
|
).prefetch_related('content').all()
|
|
serializer_class = LessonCreateSerializer
|
|
serializer_class_map = {
|
|
'list': LessonSerializer,
|
|
'retrieve': LessonSerializer,
|
|
}
|
|
filter_fields = ('course',)
|
|
search_fields = ('title', 'short_description',)
|
|
ordering_fields = ('title', 'created_at', 'update_at',)
|
|
permission_classes = (IsAuthorObjectOrAdmin,)
|
|
permission_map = {
|
|
'create': IsAuthorOrAdmin,
|
|
'delete': IsAdmin,
|
|
}
|
|
|
|
|
|
class LiveLessonViewSet(ExtendedModelViewSet):
|
|
queryset = LiveLesson.objects.prefetch_related('content').all()
|
|
serializer_class = LiveLessonCreateSerializer
|
|
serializer_class_map = {
|
|
'list': LiveLessonSerializer,
|
|
'retrieve': LiveLessonSerializer,
|
|
}
|
|
search_fields = ('title', 'short_description',)
|
|
ordering_fields = ('title', 'created_at', 'update_at',)
|
|
permission_classes = (IsTeacherOrAdmin,)
|
|
permission_map = {
|
|
'delete': IsAdmin,
|
|
}
|
|
|
|
|
|
class ImageViewSet(ExtendedModelViewSet):
|
|
queryset = Image.objects.select_related(
|
|
'course', 'lesson', 'img',
|
|
).all()
|
|
serializer_class = ImageCreateSerializer
|
|
serializer_class_map = {
|
|
'list': ImageSerializer,
|
|
'retrieve': ImageSerializer,
|
|
}
|
|
search_fields = ('title',)
|
|
ordering_fields = ('title', 'created_at', 'update_at', 'position',)
|
|
# permission_classes = (IsAuthorOrAdmin,)
|
|
# permission_map = {
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
|
|
class TextViewSet(ExtendedModelViewSet):
|
|
queryset = Text.objects.select_related(
|
|
'course', 'lesson'
|
|
).all()
|
|
serializer_class = TextCreateSerializer
|
|
serializer_class_map = {
|
|
'list': TextSerializer,
|
|
'retrieve': TextSerializer,
|
|
}
|
|
search_fields = ('title',)
|
|
ordering_fields = ('title', 'created_at', 'update_at', 'position',)
|
|
# permission_classes = (IsAuthorOrAdmin,)
|
|
# permission_map = {
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
|
|
class ImageTextViewSet(ExtendedModelViewSet):
|
|
queryset = ImageText.objects.select_related(
|
|
'course', 'lesson', 'img'
|
|
).all()
|
|
serializer_class = ImageTextCreateSerializer
|
|
serializer_class_map = {
|
|
'list': ImageTextSerializer,
|
|
'retrieve': ImageTextSerializer,
|
|
}
|
|
search_fields = ('title',)
|
|
ordering_fields = ('title', 'created_at', 'update_at', 'position',)
|
|
# permission_classes = (IsAuthorOrAdmin,)
|
|
# permission_map = {
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
|
|
class VideoViewSet(ExtendedModelViewSet):
|
|
queryset = Video.objects.select_related(
|
|
'course', 'lesson'
|
|
).all()
|
|
serializer_class = VideoCreateSerializer
|
|
serializer_class_map = {
|
|
'list': VideoSerializer,
|
|
'retrieve': VideoSerializer,
|
|
}
|
|
search_fields = ('title',)
|
|
ordering_fields = ('title', 'created_at', 'update_at', 'position',)
|
|
# permission_classes = (IsAuthorOrAdmin,)
|
|
# permission_map = {
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
|
|
class GalleryViewSet(ExtendedModelViewSet):
|
|
queryset = Gallery.objects.all()
|
|
serializer_class = GallerySerializer
|
|
search_fields = ('title',)
|
|
ordering_fields = ('title', 'created_at', 'update_at',)
|
|
# permission_classes = (IsAuthorOrAdmin,)
|
|
# permission_map = {
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
|
|
class GalleryImageViewSet(ExtendedModelViewSet):
|
|
queryset = GalleryImage.objects.select_related(
|
|
'gallery', 'img',
|
|
).all()
|
|
serializer_class = GalleryImageCreateSerializer
|
|
search_fields = ('gallery__title',)
|
|
serializer_class_map = {
|
|
'list': GalleryImageSerializer,
|
|
'retrieve': GalleryImageSerializer,
|
|
}
|
|
# permission_classes = (IsAuthorOrAdmin,)
|
|
# permission_map = {
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
|
|
class UserViewSet(ExtendedModelViewSet):
|
|
queryset = User.objects.all()
|
|
serializer_class = UserSerializer
|
|
serializer_class_map = {
|
|
'upload_photo': UserPhotoSerializer,
|
|
}
|
|
filter_fields = ('is_staff', 'is_active', 'role',
|
|
'gender', 'is_email_proved', 'fb_id',)
|
|
search_fields = ('email', 'first_name', 'last_name',
|
|
'country', 'city', 'fb_id',)
|
|
ordering_fields = ('email', 'first_name', 'last_name',
|
|
'country', 'city', 'date_joined',)
|
|
|
|
# permission_classes = (IsAdminOrIsSelf,)
|
|
# permission_map = {
|
|
# 'delete': IsAdmin,
|
|
# }
|
|
|
|
def list(self, request, *args, **kwargs):
|
|
queryset = self.filter_queryset(self.get_queryset())
|
|
|
|
if request.query_params.get('page'):
|
|
page = self.paginate_queryset(queryset)
|
|
if page is not None:
|
|
serializer = self.get_serializer(page, many=True)
|
|
return self.get_paginated_response(serializer.data)
|
|
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@list_route(methods=['get'])
|
|
def me(self, request):
|
|
serializer = self.get_serializer_class()
|
|
serialized_data = serializer(instance=request.user)
|
|
return Response(serialized_data.data)
|
|
|
|
@detail_route(methods=['post'], url_path='upload-photo')
|
|
def upload_photo(self, request, pk=None):
|
|
user = self.get_object()
|
|
serializer = self.get_serializer()
|
|
serialized_data = serializer(data=request.data)
|
|
if serialized_data.is_valid():
|
|
user.photo = serialized_data['photo']
|
|
user.save()
|
|
return Response({'success': True})
|
|
else:
|
|
return Response({'success': False}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
class UserGalleryViewSet(mixins.UpdateModelMixin, viewsets.GenericViewSet):
|
|
queryset = User.objects.all()
|
|
serializer_class = UserGalleryUpdateSerializer
|
|
# FIXME
|
|
authentication_classes = []
|
|
|
|
|
|
class SchoolScheduleViewSet(ExtendedModelViewSet):
|
|
queryset = SchoolSchedule.objects.all()
|
|
serializer_class = SchoolScheduleSerializer
|
|
permission_classes = (IsTeacherOrAdmin,)
|
|
|
|
|
|
class ConfigViewSet(generics.RetrieveUpdateAPIView):
|
|
queryset = Config.objects.all()
|
|
serializer_class = ConfigSerializer
|
|
permission_classes = (IsAdmin,)
|
|
|
|
def perform_update(self, serializer):
|
|
files = dict()
|
|
for k, v in self.request.FILES.items():
|
|
if v:
|
|
files[k] = v
|
|
serializer.save(**files)
|
|
|
|
def get_object(self):
|
|
return Config.load()
|
|
|
|
|
|
class CommentViewSet(ExtendedModelViewSet):
|
|
queryset = Comment.objects.all()
|
|
serializer_class = CommentSerializer
|
|
permission_classes = (IsAuthorObjectOrAdmin,)
|
|
|
|
def get_queryset(self):
|
|
queryset = self.queryset
|
|
is_deactivated = self.request.query_params.get('is_deactivated', '0')
|
|
if is_deactivated == '0':
|
|
queryset = queryset.filter(level=0)
|
|
elif is_deactivated == '1':
|
|
queryset = queryset.filter(deactivated_at__isnull=True)
|
|
elif is_deactivated == '2':
|
|
queryset = queryset.filter(deactivated_at__isnull=False)
|
|
|
|
return queryset
|
|
|
|
|
|
class ObjectCommentsViewSet(ExtendedModelViewSet):
|
|
queryset = Comment.objects.all()
|
|
serializer_class = CommentCreateSerializer
|
|
ordering_fields = ('update_at', )
|
|
|
|
def get_queryset(self):
|
|
queryset = self.queryset
|
|
obj_type = self.request.query_params.get('obj_type')
|
|
obj_id = self.request.query_params.get('obj_id')
|
|
is_deactivated = self.request.query_params.get('is_deactivated')
|
|
if obj_type == Comment.OBJ_TYPE_COURSE:
|
|
queryset = CourseComment.objects.filter(course=obj_id)
|
|
elif obj_type == Comment.OBJ_TYPE_LESSON:
|
|
queryset = LessonComment.objects.filter(lesson=obj_id)
|
|
elif obj_type == Comment.OBJ_TYPE_LIVE_LESSON:
|
|
queryset = LiveLessonComment.objects.filter(live_lesson=obj_id)
|
|
if is_deactivated == '0':
|
|
queryset = queryset.filter(level=0)
|
|
elif is_deactivated == '1':
|
|
queryset = queryset.filter(deactivated_at__isnull=True)
|
|
elif is_deactivated == '2':
|
|
queryset = queryset.filter(deactivated_at__isnull=False)
|
|
return queryset
|
|
|
|
def get_serializer_class(self):
|
|
if self.request.method == 'POST':
|
|
return CommentCreateSerializer
|
|
obj_type = self.request.query_params.get('obj_type')
|
|
serializer_class = CommentSerializer
|
|
if obj_type == Comment.OBJ_TYPE_COURSE:
|
|
serializer_class = CourseCommentSerializer
|
|
elif obj_type == Comment.OBJ_TYPE_LESSON:
|
|
serializer_class = LessonCommentSerializer
|
|
elif obj_type == Comment.OBJ_TYPE_LIVE_LESSON:
|
|
serializer_class = LiveLessonCommentSerializer
|
|
return serializer_class
|
|
|
|
def perform_create(self, serializer):
|
|
obj_type = self.request.data.get('obj_type')
|
|
obj_id = self.request.data.get('obj_id')
|
|
serializer.save()
|
|
try:
|
|
pusher().trigger(f'comments_{obj_type}_{obj_id}', 'add', serializer.data)
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
@permission_classes((IsAuthorObjectOrAdmin,))
|
|
def perform_destroy(self, instance):
|
|
obj_type = None
|
|
obj_id = None
|
|
if isinstance(instance, LessonComment):
|
|
obj_type = Comment.OBJ_TYPE_LESSON
|
|
obj_id = instance.lesson_id
|
|
elif isinstance(instance, CourseComment):
|
|
obj_type = Comment.OBJ_TYPE_COURSE
|
|
obj_id = instance.course_id
|
|
elif isinstance(instance, LiveLessonComment):
|
|
obj_type = Comment.OBJ_TYPE_LIVE_LESSON
|
|
obj_id = instance.live_lesson_id
|
|
serializer = self.get_serializer(instance)
|
|
try:
|
|
pusher().trigger(f'comments_{obj_type}_{obj_id}', 'delete', serializer.data)
|
|
except Exception as e:
|
|
print(e)
|
|
instance.delete()
|
|
|
|
@authentication_classes([])
|
|
def list(self, request, *args, **kwargs):
|
|
queryset = self.filter_queryset(self.get_queryset()).filter(parent__isnull=True)
|
|
serializer = self.get_serializer(queryset, many=True)
|
|
return Response(serializer.data)
|
|
|
|
|
|
class AuthorRequestViewSet(ExtendedModelViewSet):
|
|
queryset = AuthorRequest.objects.all()
|
|
serializer_class = AuthorRequestSerializer
|
|
permission_classes = (IsAdmin,)
|
|
filter_fields = ('status',)
|
|
|
|
|
|
class PaymentViewSet(viewsets.ModelViewSet):
|
|
queryset = Payment.objects.all()
|
|
serializer_class = PaymentSerializer
|
|
permission_classes = (IsAdmin,)
|
|
filter_fields = ('status', 'user',)
|
|
ordering_fields = (
|
|
'id', 'user__email',
|
|
'user__first_name', 'user__last_name',
|
|
'amount', 'created_at',
|
|
)
|
|
search_fields = ('user__email', 'user__first_name', 'user__last_name',)
|
|
|
|
def get_serializer(self, instance, *args, **kwargs):
|
|
serializer_class = self.get_serializer_class()
|
|
if 'update' in self.action:
|
|
if isinstance(instance, CoursePayment):
|
|
serializer_class = CoursePaymentCreateSerializer
|
|
elif isinstance(instance, SchoolPayment):
|
|
serializer_class = SchoolPaymentCreateSerializer
|
|
kwargs['context'] = self.get_serializer_context()
|
|
return serializer_class(instance, *args, **kwargs)
|
|
|
|
def get_queryset(self):
|
|
queryset = self.queryset
|
|
course = self.request.query_params.get('course')
|
|
weekdays = self.request.query_params.getlist('weekdays[]')
|
|
if course:
|
|
queryset = CoursePayment.objects.filter(course=course)
|
|
if weekdays:
|
|
queryset = SchoolPayment.objects.filter(weekdays__overlap=weekdays)
|
|
|
|
return queryset.filter(status__isnull=False).order_by('-created_at')
|
|
|
|
@action(methods=['get'], detail=False, url_path='calc-amount', authentication_classes=[], permission_classes=[])
|
|
def calc_amount(self, request, pk=None):
|
|
user = request.query_params.get('user')
|
|
course = request.query_params.get('course')
|
|
weekdays = request.query_params.getlist('weekdays[]')
|
|
date_start = request.query_params.get('date_start')
|
|
user = user and User.objects.get(pk=user)
|
|
course = course and Course.objects.get(pk=course)
|
|
date_start = date_start and datetime.strptime(date_start, '%Y-%m-%d')
|
|
|
|
return Response(Payment.calc_amount(user=user, course=course, date_start=date_start, weekdays=weekdays))
|
|
|
|
|
|
class ContestViewSet(ExtendedModelViewSet):
|
|
queryset = Contest.objects.all()
|
|
serializer_class = ContestCreateSerializer
|
|
serializer_class_map = {
|
|
'list': ContestSerializer,
|
|
'retrieve': ContestSerializer,
|
|
}
|
|
filter_fields = ('active',)
|
|
search_fields = ('description', 'title', 'slug',)
|
|
ordering_fields = ('id', 'title', 'active', 'date_start', 'date_end',)
|
|
permission_classes = (IsAdmin,)
|
|
|
|
|
|
class ContestWorkViewSet(ExtendedModelViewSet):
|
|
queryset = ContestWork.objects.all()
|
|
serializer_class = ContestWorkCreateSerializer
|
|
serializer_class_map = {
|
|
'list': ContestWorkSerializer,
|
|
'retrieve': ContestWorkSerializer,
|
|
}
|
|
filter_fields = ('contest',)
|
|
# FIXME
|
|
authentication_classes = []
|
|
|
|
def create(self, request, *args, **kwargs):
|
|
# FIXME
|
|
user = User.objects.get(pk=request.data.get('user'))
|
|
if ContestWork.objects.filter(user=user).exists():
|
|
return Response(status=status.HTTP_400_BAD_REQUEST)
|
|
return super().create(request, *args, **kwargs)
|
|
|
|
|
|
class CaptureEmail(views.APIView):
|
|
authentication_classes = ()
|
|
|
|
def post(self, request):
|
|
list_id = None
|
|
list_name = 'captured-emails'
|
|
recipient_id = None
|
|
email = request.data.get('email')
|
|
sg = get_sendgrid_client()
|
|
|
|
# берем все списки
|
|
response = sg.client.contactdb.lists.get()
|
|
if response.status_code != 200:
|
|
return Response({'error': 'Cannot get list of lists'}, status=status.HTTP_400_BAD_REQUEST)
|
|
# ищем нужный список
|
|
for sg_list in response.to_dict.get('lists'):
|
|
if sg_list.get('name') == list_name:
|
|
list_id = sg_list.get('id')
|
|
break
|
|
# не нашли - создаем
|
|
if not list_id:
|
|
response = sg.client.contactdb.lists.post(request_body={'name': list_name})
|
|
if response.status_code != 201:
|
|
return Response({'error': 'List was not created'}, status=status.HTTP_400_BAD_REQUEST)
|
|
list_id = response.to_dict.get('id')
|
|
# добавляем получателя
|
|
response = sg.client.contactdb.recipients.patch(request_body=[{
|
|
'email': email,
|
|
}])
|
|
if response.status_code != 201:
|
|
return Response({'error': 'Cannot update recipients'}, status=status.HTTP_400_BAD_REQUEST)
|
|
recipient_id = response.to_dict.get('persisted_recipients')[0]
|
|
# добавляем получателя в отдельный список
|
|
response = sg.client.contactdb.lists._(list_id).recipients._(recipient_id).post()
|
|
if response.status_code != 201:
|
|
return Response({'error': 'Cannot add recipient to list'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
return Response({'status': 'ok'})
|
|
|
|
|