From a80f603614813007a362cee43ca08c6bf128658d Mon Sep 17 00:00:00 2001 From: jain Date: Thu, 6 Jul 2023 07:57:53 +0530 Subject: [PATCH] jira-15 top junior API and default images field --- base/constants.py | 6 +- guardian/admin.py | 2 +- ...t_image_juniortask_is_approved_and_more.py | 28 ++++++ guardian/models.py | 2 + guardian/serializers.py | 70 +++++++++++++++ guardian/urls.py | 7 +- guardian/utils.py | 1 + guardian/views.py | 90 ++++++++++++++++++- junior/serializers.py | 43 ++++++++- zod_bank/settings.py | 3 +- 10 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 guardian/migrations/0011_juniortask_default_image_juniortask_is_approved_and_more.py diff --git a/base/constants.py b/base/constants.py index 4e7bdcd..f455316 100644 --- a/base/constants.py +++ b/base/constants.py @@ -43,7 +43,11 @@ TASK_STATUS = ( ('5', 'completed') ) -PENDING = 'pending' +PENDING = 1 +IN_PROGRESS = 2 +REJECTED = 3 +REQUESTED = 4 +COMPLETED = 5 TASK_POINTS = 5 # duplicate name used defined in constant PROJECT_NAME PROJECT_NAME = 'Zod Bank' diff --git a/guardian/admin.py b/guardian/admin.py index 6ece960..45f5c95 100644 --- a/guardian/admin.py +++ b/guardian/admin.py @@ -16,7 +16,7 @@ class GuardianAdmin(admin.ModelAdmin): @admin.register(JuniorTask) class TaskAdmin(admin.ModelAdmin): """Junior Admin""" - list_display = ['task_name', 'task_status'] + list_display = ['task_name', 'task_status', 'junior', 'points'] def __str__(self): """Return email id""" diff --git a/guardian/migrations/0011_juniortask_default_image_juniortask_is_approved_and_more.py b/guardian/migrations/0011_juniortask_default_image_juniortask_is_approved_and_more.py new file mode 100644 index 0000000..7d10d3c --- /dev/null +++ b/guardian/migrations/0011_juniortask_default_image_juniortask_is_approved_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.2 on 2023-07-05 11:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('guardian', '0010_alter_juniortask_task_status'), + ] + + operations = [ + migrations.AddField( + model_name='juniortask', + name='default_image', + field=models.ImageField(blank=True, default=None, null=True, upload_to=''), + ), + migrations.AddField( + model_name='juniortask', + name='is_approved', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='juniortask', + name='task_status', + field=models.CharField(choices=[('1', 'pending'), ('2', 'in-progress'), ('3', 'rejected'), ('4', 'requested'), ('5', 'completed')], default=1, max_length=15), + ), + ] diff --git a/guardian/models.py b/guardian/models.py index 3752b02..c2ac60b 100644 --- a/guardian/models.py +++ b/guardian/models.py @@ -50,10 +50,12 @@ class JuniorTask(models.Model): task_description = models.CharField(max_length=500) points = models.IntegerField(default=TASK_POINTS) due_date = models.DateField(auto_now_add=False, null=True, blank=True) + default_image = models.ImageField(null=True, blank=True, default=None) image = models.URLField(null=True, blank=True, default=None) junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='junior', verbose_name='Junior') task_status = models.CharField(choices=TASK_STATUS, max_length=15, default=PENDING) is_active = models.BooleanField(default=True) + is_approved = models.BooleanField(default=False) """Profile created and updated time""" created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) diff --git a/guardian/serializers.py b/guardian/serializers.py index be0272d..fb091fc 100644 --- a/guardian/serializers.py +++ b/guardian/serializers.py @@ -129,7 +129,9 @@ class CreateGuardianSerializer(serializers.ModelSerializer): if image: filename = f"images/{image.name}" image_url = upload_image_to_alibaba(image, filename) + print("image_url=====>",image_url) guardian.image = image_url + print("guardian.image=====>", guardian.image) guardian.save() return guardian @@ -192,3 +194,71 @@ class TaskDetailsSerializer(serializers.ModelSerializer): model = JuniorTask fields = ['id', 'guardian', 'task_name', 'task_description', 'points', 'due_date', 'image','junior', 'task_status', 'is_active'] + + + + + +class TopJuniorSerializer(serializers.ModelSerializer): + total_points = serializers.SerializerMethodField() + + email = serializers.SerializerMethodField('get_auth') + first_name = serializers.SerializerMethodField('get_first_name') + last_name = serializers.SerializerMethodField('get_last_name') + + def get_auth(self, obj): + return obj.auth.username + + def get_first_name(self, obj): + return obj.auth.first_name + + def get_last_name(self, obj): + return obj.auth.last_name + + class Meta: + model = Junior + fields = ['id', 'email', 'first_name', 'last_name', 'phone', 'country_code', 'country_name', 'gender', 'dob', 'image', 'junior_code', 'guardian_code', 'referral_code', 'referral_code_used', 'is_active', 'is_complete_profile', 'passcode', 'is_verified', 'created_at', 'updated_at', 'total_points'] + + def get_total_points(self, obj): + junior_ids_with_total_points = self.context.get('junior_ids_with_total_points') + if junior_ids_with_total_points: + junior_id = obj.id + for item in junior_ids_with_total_points: + if item['junior'] == junior_id: + return item['total_points'] + return 0 + +# +# class TopJuniorSerializer(serializers.ModelSerializer): +# total_points = serializers.SerializerMethodField() +# +# email = serializers.SerializerMethodField('get_auth') +# first_name = serializers.SerializerMethodField('get_first_name') +# last_name = serializers.SerializerMethodField('get_last_name') +# +# +# def get_auth(self, obj): +# return obj.auth.username +# +# def get_first_name(self, obj): +# return obj.auth.first_name +# +# def get_last_name(self, obj): +# print("onbj==>",obj) +# return obj.auth.last_name +# +# class Meta: +# model = Junior +# fields = ['id', 'email', 'first_name', 'last_name', 'phone', 'country_code', 'country_name', 'gender', 'dob', 'image', 'junior_code', 'guardian_code', 'referral_code', 'referral_code_used', 'is_active', 'is_complete_profile', 'passcode', 'is_verified', 'created_at', 'updated_at', 'total_points'] +# +# def get_total_points(self, obj): +# total_highest_points = self.context.get('total_highest_points') +# if total_highest_points: +# print("total_highest_points==>",total_highest_points) +# junior_id = obj.id +# print("junior_id==>", junior_id) +# total_points = next((item['total_points'] for item in total_highest_points if item['junior'] == junior_id), 0) +# print("total_points==>", total_points) +# return total_points +# return 0 +# diff --git a/guardian/urls.py b/guardian/urls.py index 6acd172..b69b041 100644 --- a/guardian/urls.py +++ b/guardian/urls.py @@ -1,7 +1,8 @@ """ Urls files""" """Django import""" from django.urls import path, include -from .views import SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView +from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView, + SearchTaskListAPIView, TopJuniorListAPIView) """Third party import""" from rest_framework import routers @@ -19,6 +20,10 @@ router.register('create-task', CreateTaskAPIView, basename='create-task') router.register('all-task-list', AllTaskListAPIView, basename='all-task-list') """Task list bases on the status API""" router.register('task-list', TaskListAPIView, basename='task-list') +"""Leaderboard API""" +router.register('top-junior', TopJuniorListAPIView, basename='top-junior') +"""Search Task list on the bases of status, due date, and task title API""" +router.register('filter-task', SearchTaskListAPIView, basename='filter-task') """Define Url pattern""" urlpatterns = [ path('api/v1/', include(router.urls)), diff --git a/guardian/utils.py b/guardian/utils.py index 0e46c6c..a4e1ffc 100644 --- a/guardian/utils.py +++ b/guardian/utils.py @@ -11,3 +11,4 @@ def upload_image_to_alibaba(image, filename): # Upload the temporary file to Alibaba OSS bucket.put_object_from_file(filename, temp_file.name) return f"https://{settings.ALIYUN_OSS_BUCKET_NAME}.{settings.ALIYUN_OSS_ENDPOINT}/{filename}" + diff --git a/guardian/views.py b/guardian/views.py index 22ffaa0..9a4ab78 100644 --- a/guardian/views.py +++ b/guardian/views.py @@ -2,16 +2,20 @@ """Third party Django app""" from rest_framework.permissions import IsAuthenticated from rest_framework import viewsets, status +from django.db.models import Max """Import Django app""" -from .serializers import UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer +from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer, + TopJuniorSerializer) from .models import Guardian, JuniorTask from junior.models import Junior +from junior.serializers import JuniorDetailSerializer from account.models import UserEmailOtp from .tasks import generate_otp from account.utils import send_otp_email from account.utils import custom_response, custom_error_response from base.messages import ERROR_CODE, SUCCESS_CODE from .utils import upload_image_to_alibaba +from django.db.models import Sum # Create your views here. class SignupViewset(viewsets.ModelViewSet): """Signup view set""" @@ -73,7 +77,12 @@ class TaskListAPIView(viewsets.ModelViewSet): def list(self, request, *args, **kwargs): """Create guardian profile""" print("request.GET.get(status)==>",self.request.GET.get('status')) - queryset = JuniorTask.objects.filter(guardian__user=request.user, task_status=self.request.GET.get('status')) + status_value = self.request.GET.get('status') + if status_value == 0: + queryset = JuniorTask.objects.filter(guardian__user=request.user) + else: + queryset = JuniorTask.objects.filter(guardian__user=request.user, + task_status=status_value) print("queryset==>",queryset) serializer = TaskDetailsSerializer(queryset, many=True) print("serializer.data===>",serializer.data) @@ -97,3 +106,80 @@ class CreateTaskAPIView(viewsets.ModelViewSet): serializer.save() return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) + + +class SearchTaskListAPIView(viewsets.ModelViewSet): + """Update guardian profile""" + serializer_class = TaskDetailsSerializer + permission_classes = [IsAuthenticated] + + def list(self, request, *args, **kwargs): + """Create guardian profile""" + due_date = self.request.GET.get('due_date') + print("request.GET.get(status)==>",self.request.GET.get('status')) + if self.request.GET.get('status'): + queryset = JuniorTask.objects.filter(guardian__user=request.user, + task_status=self.request.GET.get('status')).order_by('due_date') + if due_date: + queryset = JuniorTask.objects.filter(guardian__user=request.user, + due_date=due_date).order_by('due_date').order_by('created_at') + + print("queryset==>",queryset) + serializer = TaskDetailsSerializer(queryset, many=True) + # print("serializer.data===>",serializer.data) + return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) + + +class TopJuniorListAPIView(viewsets.ModelViewSet): + """Top juniors list""" + serializer_class = TopJuniorSerializer + # permission_classes = [IsAuthenticated] + + def list(self, request, *args, **kwargs): + """fetch junior list those complete their task""" + junior_ids_with_total_points = JuniorTask.objects.filter(task_status=1) \ + .values('junior') \ + .annotate(total_points=Sum('points')) \ + .order_by('-total_points') + + junior_ids = [item['junior'] for item in junior_ids_with_total_points] + + juniors = Junior.objects.filter(id__in=junior_ids) \ + .annotate(max_points=Max('junior_task__points')) \ + .order_by('-max_points', 'id') + + serializer = self.get_serializer(juniors, many=True, context={'junior_ids_with_total_points': junior_ids_with_total_points}) + return custom_response(serializer.data, response_status=status.HTTP_200_OK) + +# +# class TopJuniorListAPIView(viewsets.ModelViewSet): +# """Top juniors list""" +# serializer_class = TopJuniorSerializer +# # permission_classes = [IsAuthenticated] +# +# def list(self, request, *args, **kwargs): +# """fetch junior list those complete their task""" +# total_highest_points = list(JuniorTask.objects.filter(task_status=1) +# .values('junior') +# .annotate(total_points=Sum('points')) +# .order_by('-total_points')) +# print("total_highest_points===>",total_highest_points,'===>',type(total_highest_points)) +# junior_ids = [item['junior'] for item in total_highest_points] +# print("junior_ids====>", junior_ids) +# juniors = Junior.objects.filter(id__in=junior_ids) +# # a = [] +# # for i in junior_ids: +# # juniors = Junior.objects.filter(id=i) +# # a.append(juniors) +# print("juniors====>", juniors) +# # print('a===>',a,'==>',type(a)) +# serializer = self.get_serializer(juniors, context={'total_highest_points': total_highest_points}, many=True) +# print("serializer====>",type(serializer.data)) +# # Find the junior with the highest points +# # highest_points_junior = max(serializer.data, key=lambda x: x['total_points']) +# +# return custom_response(serializer.data, response_status=status.HTTP_200_OK) +# # serializer = self.get_serializer(total_highest_points, many=True) +# # return custom_response(None, serializer.data,response_status=status.HTTP_200_OK) + + diff --git a/junior/serializers.py b/junior/serializers.py index b8c6864..8e871cd 100644 --- a/junior/serializers.py +++ b/junior/serializers.py @@ -8,7 +8,8 @@ import random from junior.models import Junior from guardian.utils import upload_image_to_alibaba from base.messages import ERROR_CODE, SUCCESS_CODE -from guardian.models import Guardian +from guardian.models import Guardian, JuniorTask +from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED class ListCharField(serializers.ListField): """Serializer for Array field""" @@ -147,7 +148,13 @@ class JuniorDetailListSerializer(serializers.ModelSerializer): email = serializers.SerializerMethodField('get_auth') first_name = serializers.SerializerMethodField('get_first_name') last_name = serializers.SerializerMethodField('get_last_name') - + assigned_task = serializers.SerializerMethodField('get_assigned_task') + points = serializers.SerializerMethodField('get_points') + in_progress_task = serializers.SerializerMethodField('get_in_progress_task') + completed_task = serializers.SerializerMethodField('get_completed_task') + requested_task = serializers.SerializerMethodField('get_requested_task') + rejected_task = serializers.SerializerMethodField('get_rejected_task') + pending_task = serializers.SerializerMethodField('get_pending_task') def get_auth(self, obj): @@ -159,9 +166,39 @@ class JuniorDetailListSerializer(serializers.ModelSerializer): def get_last_name(self, obj): return obj.auth.last_name + def get_assigned_task(self, obj): + print("obj===>",obj,'type==>',type(obj)) + data = JuniorTask.objects.filter(junior=obj).count() + return data + + def get_points(self, obj): + data = sum(JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).values_list('points', flat=True)) + return data + + def get_in_progress_task(self, obj): + data = JuniorTask.objects.filter(junior=obj, task_status=IN_PROGRESS).count() + return data + + def get_completed_task(self, obj): + data = JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).count() + return data + + + def get_requested_task(self, obj): + data = JuniorTask.objects.filter(junior=obj, task_status=REQUESTED).count() + return data + + def get_rejected_task(self, obj): + data = JuniorTask.objects.filter(junior=obj, task_status=REJECTED).count() + return data + + def get_pending_task(self, obj): + data = JuniorTask.objects.filter(junior=obj, task_status=PENDING).count() + return data class Meta(object): """Meta info""" model = Junior fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', 'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image', - 'updated_at'] \ No newline at end of file + 'updated_at', 'assigned_task','points', 'pending_task', 'in_progress_task', 'completed_task', + 'requested_task', 'rejected_task'] diff --git a/zod_bank/settings.py b/zod_bank/settings.py index 7a05e1a..60c3e70 100644 --- a/zod_bank/settings.py +++ b/zod_bank/settings.py @@ -190,7 +190,8 @@ EMAIL_PORT="587" EMAIL_USE_TLS="True" EMAIL_HOST_USER="apikey" # Replace with your Gmail email address EMAIL_HOST_PASSWORD="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" -EMAIL_FROM_ADDRESS="zodbank@yopmail.com" +EMAIL_FROM_ADDRESS="support@zodbank.com" +# EMAIL_FROM_ADDRESS="zodbank@yopmail.com" ALIYUN_OSS_ACCESS_KEY_ID = os.getenv('ALIYUN_OSS_ACCESS_KEY_ID') ALIYUN_OSS_ACCESS_KEY_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET')