"""Junior view file""" import os from rest_framework import viewsets, status, generics,views from rest_framework.permissions import IsAuthenticated from rest_framework.pagination import PageNumberPagination from django.contrib.auth.models import User from rest_framework.filters import SearchFilter from django.db.models import F import datetime import requests """Django app import""" # Import guardian's model, # Import junior's model, # Import account's model, # Import constant from # base package, # Import messages from # base package, # Import some functions # from utils file # Import account's serializer # Import account's task # import junior serializer # Import update_positions_based_on_points # Import upload_image_to_alibaba # Import custom_response, custom_error_response # Import constants from django.db.models import Sum from junior.models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle, JuniorArticleCard) from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer, RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer, AddGuardianSerializer, StartTaskSerializer, ReAssignTaskSerializer ) from guardian.models import Guardian, JuniorTask from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import NUMBER, ARTICLE_STATUS from account.utils import custom_response, custom_error_response from guardian.utils import upload_image_to_alibaba from .utils import update_positions_based_on_points from notifications.utils import send_notification from notifications.constants import REMOVE_JUNIOR from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer, StartAssessmentSerializer) """ Define APIs """ # Define validate guardian code API, # update junior profile, # list of all assosicated junior # Add junior API # invite junior API # search junior API # remove junior API, # approve junior API # create referral code # validation API # invite guardian API # by junior # Start task # by junior API # Create your views here. class UpdateJuniorProfile(viewsets.ViewSet): """Update junior profile""" serializer_class = CreateJuniorSerializer permission_classes = [IsAuthenticated] def create(self, request, *args, **kwargs): """Use CreateJuniorSerializer""" try: request_data = request.data image = request.data.get('image') image_url = '' if image: # check image size if image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) # convert into file filename = f"images/{image.name}" # upload image on ali baba image_url = upload_image_to_alibaba(image, filename) request_data = {"image": image_url} serializer = CreateJuniorSerializer(context={"user":request.user, "image":image_url, "first_name": request.data.get('first_name'), "last_name": request.data.get('last_name') }, data=request_data) if serializer.is_valid(): """save serializer""" serializer.save() return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class ValidateGuardianCode(viewsets.ViewSet): """Check guardian code exist or not""" permission_classes = [IsAuthenticated] def list(self, request, *args, **kwargs): """check guardian code""" try: guardian_code = self.request.GET.get('guardian_code').split(',') for code in guardian_code: # fetch guardian object guardian_data = Guardian.objects.filter(guardian_code=code).exists() if guardian_data: # successfully check guardian code return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK) else: return custom_error_response(ERROR_CODE["2022"], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class JuniorListAPIView(viewsets.ModelViewSet): """Junior list of assosicated guardian""" serializer_class = JuniorDetailListSerializer queryset = Junior.objects.all() permission_classes = [IsAuthenticated] filter_backends = (SearchFilter,) search_fields = ['auth__first_name', 'auth__last_name'] http_method_names = ('get',) def get_queryset(self): queryset = self.filter_queryset(self.queryset) return queryset def list(self, request, *args, **kwargs): """ junior list""" try: update_positions_based_on_points() guardian_data = Guardian.objects.filter(user__email=request.user).last() # fetch junior object if guardian_data: queryset = self.get_queryset() queryset = queryset.filter(guardian_code__icontains=str(guardian_data.guardian_code)) # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(ERROR_CODE['2045'], response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class AddJuniorAPIView(viewsets.ModelViewSet): """Add Junior by guardian""" serializer_class = AddJuniorSerializer permission_classes = [IsAuthenticated] http_method_names = ('post',) def create(self, request, *args, **kwargs): """ junior list""" try: info_data = {'user': request.user, 'relationship': str(request.data['relationship']), 'email': request.data['email'], 'first_name': request.data['first_name'], 'last_name': request.data['last_name'], 'image':None} profile_image = request.data.get('image') if profile_image: # check image size if profile_image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) # convert into file filename = f"images/{profile_image.name}" # upload image on ali baba image_url = upload_image_to_alibaba(profile_image, filename) info_data.update({"image": image_url}) if user := User.objects.filter(username=request.data['email']).first(): self.associate_guardian(user) return custom_response(SUCCESS_CODE['3021'], response_status=status.HTTP_200_OK) # use AddJuniorSerializer serializer serializer = AddJuniorSerializer(data=request.data, context=info_data) if serializer.is_valid(): # save serializer serializer.save() return custom_response(SUCCESS_CODE['3021'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) def associate_guardian(self, user): junior = Junior.objects.filter(auth=user).first() guardian = Guardian.objects.filter(user=self.request.user).first() junior.guardian_code = [guardian.guardian_code] junior.save() JuniorGuardianRelationship.objects.get_or_create(guardian=guardian, junior=junior, relationship=str(self.request.data['relationship'])) return True class InvitedJuniorAPIView(viewsets.ModelViewSet): """Junior list of assosicated guardian""" serializer_class = JuniorDetailListSerializer permission_classes = [IsAuthenticated] pagination_class = PageNumberPagination http_method_names = ('get',) def get_queryset(self): """Get the queryset for the view""" guardian = Guardian.objects.filter(user__email=self.request.user).last() junior_queryset = Junior.objects.filter(guardian_code__icontains=str(guardian.guardian_code), is_invited=True) return junior_queryset def list(self, request, *args, **kwargs): """ junior list""" try: queryset = self.get_queryset() paginator = self.pagination_class() # pagination paginated_queryset = paginator.paginate_queryset(queryset, request) # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class FilterJuniorAPIView(viewsets.ModelViewSet): """Update guardian profile""" serializer_class = JuniorDetailListSerializer permission_classes = [IsAuthenticated] pagination_class = PageNumberPagination http_method_names = ('get',) def get_queryset(self): """Get the queryset for the view""" title = self.request.GET.get('title') guardian_data = Guardian.objects.filter(user__email=self.request.user).last() # fetch junior query queryset = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code), is_invited=True, auth__first_name=title) return queryset def list(self, request, *args, **kwargs): """Create guardian profile""" try: queryset = self.get_queryset() paginator = self.pagination_class() # use Pagination paginated_queryset = paginator.paginate_queryset(queryset, request) # use JuniorDetailListSerializer serializer serializer = JuniorDetailListSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class RemoveJuniorAPIView(views.APIView): """Remove junior API""" serializer_class = RemoveJuniorSerializer model = Junior permission_classes = [IsAuthenticated] def put(self, request, format=None): try: junior_id = self.request.GET.get('id') guardian = Guardian.objects.filter(user__email=self.request.user).last() # fetch junior query junior_queryset = Junior.objects.filter(id=junior_id, guardian_code__icontains=str(guardian.guardian_code)).last() if junior_queryset: # use RemoveJuniorSerializer serializer serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True) if serializer.is_valid(): # save serializer serializer.save() send_notification.delay(REMOVE_JUNIOR, None, junior_queryset.auth.id, {}) return custom_response(SUCCESS_CODE['3022'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) else: return custom_error_response(ERROR_CODE['2034'], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class JuniorTaskListAPIView(viewsets.ModelViewSet): """Update guardian profile""" serializer_class = TaskDetailsjuniorSerializer permission_classes = [IsAuthenticated] pagination_class = PageNumberPagination http_method_names = ('get',) def list(self, request, *args, **kwargs): """Create guardian profile""" try: status_value = self.request.GET.get('status') search = self.request.GET.get('search') if search and str(status_value) == '0': # search with title and for all task list queryset = JuniorTask.objects.filter(junior__auth=request.user, task_name__icontains=search).order_by('due_date', 'created_at') elif search and str(status_value) != '0': # search with title and fetch task list with status wise queryset = JuniorTask.objects.filter(junior__auth=request.user, task_name__icontains=search, task_status=status_value).order_by('due_date', 'created_at') if search is None and str(status_value) == '0': # fetch all task list queryset = JuniorTask.objects.filter(junior__auth=request.user).order_by('due_date', 'created_at') elif search is None and str(status_value) != '0': # fetch task list with status wise queryset = JuniorTask.objects.filter(junior__auth=request.user, task_status=status_value).order_by('due_date','created_at') paginator = self.pagination_class() # use Pagination paginated_queryset = paginator.paginate_queryset(queryset, request) # use TaskDetailsSerializer serializer serializer = TaskDetailsjuniorSerializer(paginated_queryset, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class CompleteJuniorTaskAPIView(views.APIView): """Update junior task API""" serializer_class = CompleteTaskSerializer model = JuniorTask permission_classes = [IsAuthenticated] def put(self, request, format=None): try: task_id = self.request.data.get('task_id') image = request.data['image'] if image and image.size == NUMBER['zero']: return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST) # create file filename = f"images/{image.name}" # upload image filename = f"images/{image.name}" image_url = upload_image_to_alibaba(image, filename) # fetch junior query task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user).last() if task_queryset: # use CompleteTaskSerializer serializer if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]: """Already request send """ return custom_error_response(ERROR_CODE['2049'], response_status=status.HTTP_400_BAD_REQUEST) serializer = CompleteTaskSerializer(task_queryset, data={'image': image_url}, partial=True) if serializer.is_valid(): # save serializer serializer.save() return custom_response(SUCCESS_CODE['3032'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) else: return custom_error_response(ERROR_CODE['2044'], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class JuniorPointsListAPIView(viewsets.ModelViewSet): """Junior Points viewset""" serializer_class = JuniorPointsSerializer permission_classes = [IsAuthenticated] http_method_names = ('get',) def get_queryset(self): """get queryset""" update_positions_based_on_points() return JuniorTask.objects.filter(junior__auth__email=self.request.user).last() def list(self, request, *args, **kwargs): """profile view""" try: queryset = self.get_queryset() # update position of junior serializer = JuniorPointsSerializer(queryset) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class ValidateReferralCode(viewsets.ViewSet): """Check guardian code exist or not""" permission_classes = [IsAuthenticated] http_method_names = ('get',) def get_queryset(self): """Get queryset based on referral_code.""" referral_code = self.request.GET.get('referral_code') if referral_code: # search referral code in guardian model guardian_queryset = Guardian.objects.filter(referral_code=referral_code).last() if guardian_queryset: return guardian_queryset else: # search referral code in junior model junior_queryset = Junior.objects.filter(referral_code=referral_code).last() if junior_queryset: return junior_queryset return None def list(self, request, *args, **kwargs): """check guardian code""" try: if self.get_queryset(): return custom_response(SUCCESS_CODE['3033'], response_status=status.HTTP_200_OK) return custom_error_response(ERROR_CODE["2019"], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class InviteGuardianAPIView(viewsets.ModelViewSet): """Invite guardian by junior""" serializer_class = AddGuardianSerializer permission_classes = [IsAuthenticated] http_method_names = ('post',) def create(self, request, *args, **kwargs): """ junior list""" try: if request.data['email'] == '': return custom_error_response(ERROR_CODE['2062'], response_status=status.HTTP_400_BAD_REQUEST) info = {'user': request.user, 'email': request.data['email'], 'first_name': request.data['first_name'], 'last_name': request.data['last_name'], 'relationship': str(request.data['relationship'])} # use AddJuniorSerializer serializer serializer = AddGuardianSerializer(data=request.data, context=info) if serializer.is_valid(): # save serializer serializer.save() return custom_response(SUCCESS_CODE['3034'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class StartTaskAPIView(views.APIView): """Update junior task API""" serializer_class = StartTaskSerializer model = JuniorTask permission_classes = [IsAuthenticated] def put(self, request, format=None): try: task_id = self.request.data.get('task_id') task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user).last() if task_queryset and task_queryset.task_status == str(NUMBER['one']): # use StartTaskSerializer serializer serializer = StartTaskSerializer(task_queryset, data=request.data, partial=True) if serializer.is_valid(): # save serializer serializer.save() return custom_response(SUCCESS_CODE['3035'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) else: # task in another state return custom_error_response(ERROR_CODE['2060'], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class ReAssignJuniorTaskAPIView(views.APIView): """Update junior task API""" serializer_class = ReAssignTaskSerializer model = JuniorTask permission_classes = [IsAuthenticated] def put(self, request, format=None): try: task_id = self.request.data.get('task_id') task_queryset = JuniorTask.objects.filter(id=task_id, guardian__user__email=self.request.user).last() if task_queryset and task_queryset.task_status == str(NUMBER['six']): # use StartTaskSerializer serializer serializer = ReAssignTaskSerializer(task_queryset, data=request.data, partial=True) if serializer.is_valid(): # save serializer serializer.save() return custom_response(SUCCESS_CODE['3036'], response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) else: # task in another state return custom_error_response(ERROR_CODE['2066'], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class StartArticleAPIView(viewsets.ModelViewSet): """Start article""" permission_classes = [IsAuthenticated] http_method_names = ('post',) def create(self, request, *args, **kwargs): """ junior list""" try: junior_instance = Junior.objects.filter(auth=self.request.user).last() article_id = request.data.get('article_id') article_data = Article.objects.filter(id=article_id).last() if not JuniorArticle.objects.filter(junior=junior_instance, article=article_data).last(): JuniorArticle.objects.create(junior=junior_instance, article=article_data, status=str(NUMBER['two'])) if article_data: question_query = ArticleSurvey.objects.filter(article=article_id) for question in question_query: if not JuniorArticlePoints.objects.filter(junior=junior_instance, article=article_data, question=question): JuniorArticlePoints.objects.create(junior=junior_instance, article=article_data, question=question) return custom_response(SUCCESS_CODE['3040'], response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class StartAssessmentAPIView(viewsets.ModelViewSet): """Junior Points viewset""" serializer_class = StartAssessmentSerializer permission_classes = [IsAuthenticated] http_method_names = ('get',) def get_queryset(self): article_id = self.request.GET.get('article_id') # if referral_code: article = Article.objects.filter(id=article_id, is_deleted=False).prefetch_related( 'article_cards', 'article_survey', 'article_survey__options' ).order_by('-created_at') return article def list(self, request, *args, **kwargs): """profile view""" try: queryset = self.get_queryset() paginator = self.pagination_class() paginated_queryset = paginator.paginate_queryset(queryset, request) serializer = self.serializer_class(paginated_queryset, context={"user":request.user}, many=True) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class CheckAnswerAPIView(viewsets.ModelViewSet): """Junior Points viewset""" permission_classes = [IsAuthenticated] http_method_names = ('get',) def get_queryset(self): question_id = self.request.GET.get('question_id') article = ArticleSurvey.objects.filter(id=question_id).last() return article def list(self, request, *args, **kwargs): """profile view""" try: answer_id = self.request.GET.get('answer_id') queryset = self.get_queryset() submit_ans = SurveyOption.objects.filter(id=answer_id, is_answer=True).last() junior_article_points = JuniorArticlePoints.objects.filter(junior__auth=self.request.user, question=queryset) if submit_ans: junior_article_points.update(submitted_answer=submit_ans, is_attempt=True, is_answer_correct=True) JuniorPoints.objects.filter(junior__auth=self.request.user).update(total_points= F('total_points')+ queryset.points) else: junior_article_points.update(submitted_answer=submit_ans, is_attempt=True, earn_points=0, is_answer_correct=False) return custom_response(None, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class CompleteArticleAPIView(views.APIView): """Remove junior API""" permission_classes = [IsAuthenticated] http_method_names = ('put', 'get',) def put(self, request, format=None): try: article_id = self.request.data.get('article_id') JuniorArticle.objects.filter(junior__auth=request.user, article__id=article_id).update( is_completed=True, status=str(NUMBER['three']) ) return custom_response(SUCCESS_CODE['3041'], response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) def get(self, request, *args, **kwargs): """ junior list""" try: article_id = self.request.GET.get('article_id') total_earn_points = JuniorArticlePoints.objects.filter(junior__auth=request.user, article__id=article_id, is_answer_correct=True).aggregate( total_earn_points=Sum('earn_points'))['total_earn_points'] data = {"total_earn_points":total_earn_points} return custom_response(SUCCESS_CODE['3042'], data, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class ReadArticleCardAPIView(views.APIView): """Remove junior API""" permission_classes = [IsAuthenticated] http_method_names = ('put',) def put(self, request, *args, **kwargs): """ junior list""" try: junior_instance = Junior.objects.filter(auth=self.request.user).last() article = self.request.data.get('article_id') article_card = self.request.data.get('article_card') JuniorArticleCard.objects.filter(junior=junior_instance, article__id=article, article_card__id=article_card).update(is_read=True) return custom_response(SUCCESS_CODE['3043'], response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST) class CreateArticleCardAPIView(viewsets.ModelViewSet): """Start article""" permission_classes = [IsAuthenticated] http_method_names = ('post',) def create(self, request, *args, **kwargs): """ junior list""" try: junior_instance = Junior.objects.filter(auth=self.request.user).last() article_id = request.data.get('article_id') article_data = Article.objects.filter(id=article_id).last() if article_data: article_cards = ArticleCard.objects.filter(article=article_id) for article_card in article_cards: if not JuniorArticleCard.objects.filter(junior=junior_instance, article=article_data, article_card=article_card): JuniorArticleCard.objects.create(junior=junior_instance, article=article_data, article_card=article_card) return custom_response(None, response_status=status.HTTP_200_OK) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)