"""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, RemoveGuardianCodeSerializer) 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.guardian_code_status = str(NUMBER['two']) 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 list(self, request, *args, **kwargs): """profile view""" try: update_positions_based_on_points() queryset = JuniorTask.objects.filter(junior__auth__email=self.request.user).last() # 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']), current_card_page=NUMBER['zero'], current_que_page=NUMBER['zero']) 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') current_page = self.request.GET.get('current_page') 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) JuniorArticle.objects.filter(junior__auth=self.request.user, article=queryset.article).update( current_que_page=int(current_page) + NUMBER['one']) 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') current_page = self.request.data.get('current_page') JuniorArticleCard.objects.filter(junior=junior_instance, article__id=article, article_card__id=article_card).update(is_read=True) JuniorArticle.objects.filter(junior=junior_instance, article__id=article).update(current_card_page=int(current_page)+NUMBER['one']) 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) class RemoveGuardianCodeAPIView(views.APIView): """Update junior task API""" serializer_class = RemoveGuardianCodeSerializer permission_classes = [IsAuthenticated] def put(self, request, format=None): try: junior_queryset = Junior.objects.filter(auth=self.request.user).last() if junior_queryset: # use RemoveGuardianCodeSerializer serializer serializer = RemoveGuardianCodeSerializer(junior_queryset, data=request.data, partial=True) if serializer.is_valid(): # save serializer serializer.save() return custom_response(SUCCESS_CODE['3044'], 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['2047'], response_status=status.HTTP_400_BAD_REQUEST) except Exception as e: return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)