From 69ce6857e8bd95ee83b3525d1ac27c5d5ab1779c Mon Sep 17 00:00:00 2001 From: jain Date: Wed, 9 Aug 2023 16:36:33 +0530 Subject: [PATCH 1/3] financial learning section api --- base/constants.py | 6 ++ base/messages.py | 8 +- guardian/serializers.py | 2 - junior/admin.py | 22 +++++- junior/migrations/0022_juniorarticle.py | 27 +++++++ junior/migrations/0023_juniorarticlecard.py | 27 +++++++ junior/models.py | 39 +++++++++- junior/serializers.py | 2 +- junior/urls.py | 7 +- junior/views.py | 84 ++++++++++++++++++++- 10 files changed, 211 insertions(+), 13 deletions(-) create mode 100644 junior/migrations/0022_juniorarticle.py create mode 100644 junior/migrations/0023_juniorarticlecard.py diff --git a/base/constants.py b/base/constants.py index 7efdb8b..36079b9 100644 --- a/base/constants.py +++ b/base/constants.py @@ -76,6 +76,12 @@ GUARDIAN_CODE_STATUS = ( ('2', 'exist guardian code'), ('3', 'request for guardian code') ) +# article status +ARTICLE_STATUS = ( + ('1', 'read'), + ('2', 'in_progress'), + ('3', 'completed') +) # relationship RELATIONSHIP = ( ('1', 'parent'), diff --git a/base/messages.py b/base/messages.py index 05b4ec3..1e3e146 100644 --- a/base/messages.py +++ b/base/messages.py @@ -150,7 +150,13 @@ SUCCESS_CODE = { "3038": "Status has been changed successfully.", # notification read "3039": "Notification read successfully", - "3040": "Start article successfully" + "3040": "Start article successfully", + # complete article + "3041": "Article completed successfully", + # submit assessment successfully + "3042": "Assessment completed successfully", + "3043": "Read article card successfully" + } """status code error""" STATUS_CODE_ERROR = { diff --git a/guardian/serializers.py b/guardian/serializers.py index 0a8b625..12d5383 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -387,8 +387,6 @@ class ApproveTaskSerializer(serializers.ModelSerializer): # reject the task instance.task_status = str(NUMBER['three']) instance.is_approved = False - # update total task point - junior_data.total_points = junior_data.total_points - instance.points # update reject time of task # instance.rejected_on = real_time() instance.rejected_on = timezone.now().astimezone(pytz.utc) diff --git a/junior/admin.py b/junior/admin.py index 5fdfcce..6c6cdf9 100644 --- a/junior/admin.py +++ b/junior/admin.py @@ -2,8 +2,26 @@ """Third party Django app""" from django.contrib import admin """Import Django app""" -from .models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints +from .models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle, + JuniorArticleCard) # Register your models here. +@admin.register(JuniorArticle) +class JuniorArticleAdmin(admin.ModelAdmin): + """Junior Admin""" + list_display = ['junior', 'article', 'status', 'is_completed'] + + def __str__(self): + """Return email id""" + return self.junior__auth__email + +@admin.register(JuniorArticleCard) +class JuniorArticleCardAdmin(admin.ModelAdmin): + """Junior Admin""" + list_display = ['junior', 'article', 'article_card', 'is_read'] + + def __str__(self): + """Return email id""" + return self.junior__auth__email @admin.register(Junior) class JuniorAdmin(admin.ModelAdmin): """Junior Admin""" @@ -30,4 +48,4 @@ class JuniorGuardianRelationshipAdmin(admin.ModelAdmin): @admin.register(JuniorArticlePoints) class JuniorArticlePointsAdmin(admin.ModelAdmin): """Junior Admin""" - list_display = ['junior', 'article', 'question', 'submitted_answer'] + list_display = ['junior', 'article', 'question', 'submitted_answer', 'is_answer_correct'] diff --git a/junior/migrations/0022_juniorarticle.py b/junior/migrations/0022_juniorarticle.py new file mode 100644 index 0000000..9dd794e --- /dev/null +++ b/junior/migrations/0022_juniorarticle.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.2 on 2023-08-09 09:34 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('web_admin', '0004_alter_surveyoption_survey'), + ('junior', '0021_alter_juniorarticlepoints_submitted_answer'), + ] + + operations = [ + migrations.CreateModel( + name='JuniorArticle', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_completed', models.BooleanField(default=False)), + ('status', models.CharField(blank=True, choices=[('1', 'read'), ('2', 'in_progress'), ('3', 'completed')], default='1', max_length=10, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='junior_articles_details', to='web_admin.article')), + ('junior', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='juniors_article', to='junior.junior', verbose_name='Junior')), + ], + ), + ] diff --git a/junior/migrations/0023_juniorarticlecard.py b/junior/migrations/0023_juniorarticlecard.py new file mode 100644 index 0000000..9b8a1af --- /dev/null +++ b/junior/migrations/0023_juniorarticlecard.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.2 on 2023-08-09 10:47 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('web_admin', '0004_alter_surveyoption_survey'), + ('junior', '0022_juniorarticle'), + ] + + operations = [ + migrations.CreateModel( + name='JuniorArticleCard', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_read', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='junior_articles_detail', to='web_admin.article')), + ('article_card', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='junior_article_card', to='web_admin.articlecard')), + ('junior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='juniors_article_card', to='junior.junior', verbose_name='Junior')), + ], + ), + ] diff --git a/junior/models.py b/junior/models.py index 3d2aaa4..180b425 100644 --- a/junior/models.py +++ b/junior/models.py @@ -6,11 +6,11 @@ from django.contrib.auth import get_user_model """Import ArrayField""" from django.contrib.postgres.fields import ArrayField """Import django app""" -from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP, GUARDIAN_CODE_STATUS +from base.constants import GENDERS, SIGNUP_METHODS, RELATIONSHIP, GUARDIAN_CODE_STATUS, ARTICLE_STATUS # Import guardian's model from guardian.models import Guardian # Import web admin's model -from web_admin.models import SurveyOption, ArticleSurvey, Article +from web_admin.models import SurveyOption, ArticleSurvey, Article, ArticleCard """Define User model""" User = get_user_model() # Create your models here. @@ -161,3 +161,38 @@ class JuniorArticlePoints(models.Model): def __str__(self): """Return title""" return f'{self.id} | {self.question}' + +class JuniorArticle(models.Model): + """ + Survey Options model + """ + # associated junior with the task + junior = models.OneToOneField(Junior, on_delete=models.CASCADE, related_name='juniors_article', verbose_name='Junior') + article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='junior_articles_details') + # article completed""" + is_completed = models.BooleanField(default=False) + status = models.CharField(max_length=10, choices=ARTICLE_STATUS, null=True, blank=True, default='1') + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + """Return title""" + return f'{self.id} | {self.article}' + +class JuniorArticleCard(models.Model): + """ + Survey Options model + """ + # associated junior with the task + junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='juniors_article_card', verbose_name='Junior') + article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='junior_articles_detail') + article_card = models.ForeignKey(ArticleCard, on_delete=models.CASCADE, related_name='junior_article_card') + + # article card read""" + is_read = models.BooleanField(default=False) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + """Return title""" + return f'{self.id} | {self.article}' diff --git a/junior/serializers.py b/junior/serializers.py index bfd79d1..079031a 100644 --- a/junior/serializers.py +++ b/junior/serializers.py @@ -12,7 +12,7 @@ from rest_framework_simplejwt.tokens import RefreshToken # local imports from account.utils import send_otp_email, generate_code -from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship +from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints from guardian.tasks import generate_otp from base.messages import ERROR_CODE, SUCCESS_CODE from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD, EXPIRED, diff --git a/junior/urls.py b/junior/urls.py index 76e5b47..e494a3d 100644 --- a/junior/urls.py +++ b/junior/urls.py @@ -5,7 +5,8 @@ from .views import (UpdateJuniorProfile, ValidateGuardianCode, JuniorListAPIView InvitedJuniorAPIView, FilterJuniorAPIView, RemoveJuniorAPIView, JuniorTaskListAPIView, CompleteJuniorTaskAPIView, JuniorPointsListAPIView, ValidateReferralCode, InviteGuardianAPIView, StartTaskAPIView, ReAssignJuniorTaskAPIView, StartArticleAPIView, - StartAssessmentAPIView, CheckAnswerAPIView) + StartAssessmentAPIView, CheckAnswerAPIView, CompleteArticleAPIView, ReadArticleCardAPIView, + CreateArticleCardAPIView) """Third party import""" from rest_framework import routers @@ -48,6 +49,8 @@ router.register('start-article', StartArticleAPIView, basename='start-article') router.register('start-assessment', StartAssessmentAPIView, basename='start-assessment') # check answer api""" router.register('check-answer', CheckAnswerAPIView, basename='check-answer') +# start article""" +router.register('create-article-card', CreateArticleCardAPIView, basename='create-article-card') # Define url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), @@ -55,4 +58,6 @@ urlpatterns = [ path('api/v1/complete-task/', CompleteJuniorTaskAPIView.as_view()), path('api/v1/start-task/', StartTaskAPIView.as_view()), path('api/v1/reassign-task/', ReAssignJuniorTaskAPIView.as_view()), + path('api/v1/complete-article/', CompleteArticleAPIView.as_view()), + path('api/v1/read-article-card/', ReadArticleCardAPIView.as_view()), ] diff --git a/junior/views.py b/junior/views.py index 9a7ce35..5926c47 100644 --- a/junior/views.py +++ b/junior/views.py @@ -28,20 +28,23 @@ import requests # Import upload_image_to_alibaba # Import custom_response, custom_error_response # Import constants -from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints +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) + 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 +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 +from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer, StartAssessmentSerializer) """ Define APIs """ @@ -479,6 +482,8 @@ class StartArticleAPIView(viewsets.ModelViewSet): 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: @@ -545,3 +550,74 @@ class CheckAnswerAPIView(viewsets.ModelViewSet): 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) From 9c75cb1615729c468b6bfddb92ffbaf79b821d86 Mon Sep 17 00:00:00 2001 From: abutalib-kiwi Date: Wed, 9 Aug 2023 16:57:19 +0530 Subject: [PATCH 2/3] analytics section api, users counts, new signup count, task report --- account/serializers.py | 5 +- account/views.py | 5 +- web_admin/serializers/analytics_serializer.py | 3 + web_admin/serializers/auth_serializer.py | 4 +- web_admin/urls.py | 4 + web_admin/views/analytics.py | 98 +++++++++++++++++++ web_admin/views/user_management.py | 13 ++- 7 files changed, 117 insertions(+), 15 deletions(-) create mode 100644 web_admin/serializers/analytics_serializer.py create mode 100644 web_admin/views/analytics.py diff --git a/account/serializers.py b/account/serializers.py index 5686931..4065b5c 100644 --- a/account/serializers.py +++ b/account/serializers.py @@ -154,10 +154,9 @@ class AdminLoginSerializer(serializers.ModelSerializer): user = User.objects.filter(email__iexact=attrs['email'], is_superuser=True ).only('id', 'first_name', 'last_name', 'email', 'is_superuser').first() - if not user: - raise serializers.ValidationError({'details': ERROR_CODE['2002']}) - elif not user.check_password(attrs['password']): + if not user or not user.check_password(attrs['password']): raise serializers.ValidationError({'details': ERROR_CODE['2002']}) + self.context.update({'user': user}) return attrs diff --git a/account/views.py b/account/views.py index 80530ad..c814100 100644 --- a/account/views.py +++ b/account/views.py @@ -334,10 +334,9 @@ class UserLogin(viewsets.ViewSet): user = User.objects.filter(email__iexact=email, is_superuser=True ).only('id', 'first_name', 'last_name', 'email', 'is_superuser').first() - if not user: - return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_400_BAD_REQUEST) - elif not user.check_password(password): + if not user or not user.check_password(password): return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_400_BAD_REQUEST) + serializer = SuperUserSerializer(user) return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK) diff --git a/web_admin/serializers/analytics_serializer.py b/web_admin/serializers/analytics_serializer.py new file mode 100644 index 0000000..5b653a6 --- /dev/null +++ b/web_admin/serializers/analytics_serializer.py @@ -0,0 +1,3 @@ +""" +web_admin analytics serializer file +""" diff --git a/web_admin/serializers/auth_serializer.py b/web_admin/serializers/auth_serializer.py index 9f603ce..712e284 100644 --- a/web_admin/serializers/auth_serializer.py +++ b/web_admin/serializers/auth_serializer.py @@ -87,9 +87,9 @@ class AdminVerifyOTPSerializer(serializers.Serializer): # fetch email otp object of the user user_otp_details = UserEmailOtp.objects.filter(email=email, otp=otp).last() if not user_otp_details: - raise serializers.ValidationError({'details': ERROR_CODE['2064']}) + raise serializers.ValidationError({'details': ERROR_CODE['2008']}) if user_otp_details.user_type != dict(USER_TYPE).get('3'): - raise serializers.ValidationError({'details': ERROR_CODE['2063']}) + raise serializers.ValidationError({'details': ERROR_CODE['2008']}) if user_otp_details.expired_at.replace(tzinfo=None) < datetime.utcnow(): raise serializers.ValidationError({'details': ERROR_CODE['2029']}) user_otp_details.is_verified = True diff --git a/web_admin/urls.py b/web_admin/urls.py index 065d30d..d586e50 100644 --- a/web_admin/urls.py +++ b/web_admin/urls.py @@ -6,6 +6,7 @@ from django.urls import path, include from rest_framework import routers # local imports +from web_admin.views.analytics import AnalyticsViewSet from web_admin.views.article import ArticleViewSet, DefaultArticleCardImagesViewSet, ArticleListViewSet from web_admin.views.auth import ForgotAndResetPasswordViewSet from web_admin.views.user_management import UserManagementViewSet @@ -17,6 +18,9 @@ router.register('article', ArticleViewSet, basename='article') router.register('default-card-images', DefaultArticleCardImagesViewSet, basename='default-card-images') router.register('user-management', UserManagementViewSet, basename='user') router.register('article-list', ArticleListViewSet, basename='article-list') +router.register('analytics', AnalyticsViewSet, basename='user-analytics') +# router.register('task-analytics', TaskAnalyticsViewSet, basename='task-analytics') + # forgot and reset password api for admin router.register('admin', ForgotAndResetPasswordViewSet, basename='admin') diff --git a/web_admin/views/analytics.py b/web_admin/views/analytics.py new file mode 100644 index 0000000..f769c18 --- /dev/null +++ b/web_admin/views/analytics.py @@ -0,0 +1,98 @@ +""" +web_admin analytics view file +""" +import datetime + +from rest_framework.viewsets import GenericViewSet +from rest_framework.decorators import action +from django.contrib.auth import get_user_model +from django.db.models import Q +from django.db.models import Count +from django.db.models.functions import TruncDate + +from account.utils import custom_response +from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, EXPIRED +from guardian.models import JuniorTask + +USER = get_user_model() + + +class AnalyticsViewSet(GenericViewSet): + """ + analytics api view + """ + serializer_class = None + + def get_queryset(self): + user_qs = USER.objects.filter( + (Q(junior_profile__is_verified=True) | Q(guardian_profile__is_verified=True)), + is_superuser=False + ).prefetch_related('guardian_profile', + 'junior_profile' + ).exclude(junior_profile__isnull=True, + guardian_profile__isnull=True).order_by('date_joined') + return user_qs + + @action(methods=['get'], url_name='users-count', url_path='users-count', detail=False) + def total_users_count(self, request, *args, **kwargs): + """ + api method to get total users, guardians and juniors + :param request: query params {start_date and end_date}, date format (yyyy-mm-dd) + :return: + """ + + end_date = datetime.date.today() + start_date = end_date - datetime.timedelta(days=6) + + if request.query_params.get('start_date') and request.query_params.get('end_date'): + start_date = datetime.datetime.strptime(request.query_params.get('start_date'), '%Y-%m-%d') + end_date = datetime.datetime.strptime(request.query_params.get('end_date'), '%Y-%m-%d') + + user_qs = self.get_queryset() + queryset = user_qs.filter(date_joined__range=(start_date, (end_date + datetime.timedelta(days=1)))) + + data = {'total_users': queryset.count(), + 'total_guardians': queryset.filter(junior_profile__isnull=True).count(), + 'total_juniors': queryset.filter(guardian_profile__isnull=True).count()} + + return custom_response(None, data) + + @action(methods=['get'], url_name='new-signups', url_path='new-signups', detail=False) + def new_signups(self, request, *args, **kwargs): + + end_date = datetime.date.today() + start_date = end_date - datetime.timedelta(days=6) + + if request.query_params.get('start_date') and request.query_params.get('end_date'): + start_date = datetime.datetime.strptime(request.query_params.get('start_date'), '%Y-%m-%d') + end_date = datetime.datetime.strptime(request.query_params.get('end_date'), '%Y-%m-%d') + + user_qs = self.get_queryset() + signup_data = user_qs.filter(date_joined__range=[start_date, (end_date + datetime.timedelta(days=1))] + ).annotate(date=TruncDate('date_joined') + ).values('date').annotate(signups=Count('id')).order_by('date') + + return custom_response(None, signup_data) + + @action(methods=['get'], url_name='assign-tasks', url_path='assign-tasks', detail=False) + def assign_tasks_report(self, request, *args, **kwargs): + + end_date = datetime.date.today() + start_date = end_date - datetime.timedelta(days=6) + + if request.query_params.get('start_date') and request.query_params.get('end_date'): + start_date = datetime.datetime.strptime(request.query_params.get('start_date'), '%Y-%m-%d') + end_date = datetime.datetime.strptime(request.query_params.get('end_date'), '%Y-%m-%d') + + assign_tasks = JuniorTask.objects.filter( + created_at__range=[start_date, (end_date + datetime.timedelta(days=1))] + ).exclude(task_status__in=[PENDING, EXPIRED]) + + data = { + 'task_completed': assign_tasks.filter(task_status=COMPLETED).count(), + 'task_in_progress': assign_tasks.filter(task_status=IN_PROGRESS).count(), + 'task_requested': assign_tasks.filter(task_status=REQUESTED).count(), + 'task_rejected': assign_tasks.filter(task_status=REJECTED).count(), + } + + return custom_response(None, data) diff --git a/web_admin/views/user_management.py b/web_admin/views/user_management.py index 3bd8f64..c16b62a 100644 --- a/web_admin/views/user_management.py +++ b/web_admin/views/user_management.py @@ -29,11 +29,12 @@ class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin, """ serializer_class = UserManagementListSerializer permission_classes = [IsAuthenticated, AdminPermission] - queryset = USER.objects.filter(is_superuser=False - ).prefetch_related('guardian_profile', - 'junior_profile' - ).exclude(junior_profile__isnull=True, - guardian_profile__isnull=True).order_by('date_joined') + queryset = USER.objects.filter( + (Q(junior_profile__is_verified=True) | Q(guardian_profile__is_verified=True)), + is_superuser=False).prefetch_related('guardian_profile', + 'junior_profile' + ).exclude(junior_profile__isnull=True, + guardian_profile__isnull=True).order_by('date_joined') filter_backends = (SearchFilter,) search_fields = ['first_name', 'last_name'] http_method_names = ['get', 'post', 'patch'] @@ -55,8 +56,6 @@ class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin, :return: """ queryset = self.get_queryset() - queryset = queryset.filter( - (Q(junior_profile__is_verified=True) | Q(guardian_profile__is_verified=True))) paginator = self.pagination_class() paginated_queryset = paginator.paginate_queryset(queryset, request) serializer = self.serializer_class(paginated_queryset, many=True) From 32eaa6c3f2a90d48c971f13532c553d497487bf2 Mon Sep 17 00:00:00 2001 From: jain Date: Wed, 9 Aug 2023 17:18:07 +0530 Subject: [PATCH 3/3] guardian code update --- junior/serializers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junior/serializers.py b/junior/serializers.py index 079031a..3575ccf 100644 --- a/junior/serializers.py +++ b/junior/serializers.py @@ -96,6 +96,9 @@ class CreateJuniorSerializer(serializers.ModelSerializer): guardian_data = Guardian.objects.filter(guardian_code=guardian_code[0]).last() if guardian_data: JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior) + junior.guardian_code_status = str(NUMBER['three']) + junior_approval_mail(user.email, user.first_name) + send_notification.delay(APPROVED_JUNIOR, None, guardian_data.user.id, {}) junior.dob = validated_data.get('dob', junior.dob) junior.passcode = validated_data.get('passcode', junior.passcode) junior.country_name = validated_data.get('country_name', junior.country_name)