Compare commits

..

27 Commits

Author SHA1 Message Date
04ed9c668c remove print statement for expiry date 2023-08-17 13:24:20 +05:30
36427b50c1 print statement for expiry date 2023-08-17 12:24:33 +05:30
5da07002e0 Merge pull request #217 from KiwiTechLLC/ZBKBCK-47
notification modification added more payload
2023-08-16 16:48:53 +05:30
3017b0ece0 changes in notification method 2023-08-16 16:40:34 +05:30
e73113fcca Merge branch 'dev' into ZBKBCK-47 2023-08-16 16:39:36 +05:30
c278670c39 Merge pull request #214 from KiwiTechLLC/sprint5
email verification and user notification bug
2023-08-16 16:28:58 +05:30
60af098e1e email verfication and user notification bug 2023-08-16 16:16:05 +05:30
d29a60558f Merge pull request #211 from KiwiTechLLC/sprint5
user type
2023-08-16 11:38:12 +05:30
451c3bdae7 user type 2023-08-16 11:37:21 +05:30
7c809776b6 guardian code status 2023-08-14 18:22:50 +05:30
e46d649fdc notification modification added more payload 2023-08-14 16:03:36 +05:30
adb827f5a0 Merge pull request #206 from KiwiTechLLC/sprint4
Sprint4
2023-08-14 15:26:27 +05:30
a02dfd4e31 login api with user type 2023-08-14 15:23:41 +05:30
d3b0be953e login api with user type 2023-08-14 15:16:16 +05:30
11b9f00285 Merge branch 'login_api_reduced_queries' of github.com:KiwiTechLLC/ZODBank-Backend into login_api_reduced_queries 2023-08-14 15:01:43 +05:30
08dc9f8538 Merge pull request #205 from KiwiTechLLC/sprint4
sonar fixes
2023-08-14 12:20:48 +05:30
6373d1e02c sonar fixes 2023-08-14 12:13:14 +05:30
a1d959299a Merge pull request #202 from KiwiTechLLC/sprint4
is complete key
2023-08-14 11:45:37 +05:30
070637bf1d is complete key 2023-08-14 11:43:59 +05:30
fd9a4902ae Merge pull request #199 from KiwiTechLLC/sprint4
guardian code chnages
2023-08-11 16:55:21 +05:30
082f93ff9d guardian code chnages 2023-08-11 16:54:27 +05:30
25eaee31a4 Merge pull request #198 from KiwiTechLLC/ZBKADM-71
added pagination in leaderboard admin
2023-08-11 16:02:13 +05:30
cae28e0b54 Merge pull request #197 from KiwiTechLLC/sprint4
is complete article key
2023-08-11 15:41:35 +05:30
54200dba52 is complete article key 2023-08-11 15:39:25 +05:30
846a9d42d4 Merge pull request #196 from KiwiTechLLC/ZBKADM-72-sonar-issues
sonar issues
2023-08-11 14:44:25 +05:30
69c19cf097 sonar issues 2023-08-11 14:40:49 +05:30
4f02cef0f9 Optimised login api 2023-08-10 18:43:03 +05:30
19 changed files with 258 additions and 147 deletions

View File

@ -152,7 +152,8 @@ class AdminLoginSerializer(serializers.ModelSerializer):
def validate(self, attrs): def validate(self, attrs):
user = User.objects.filter(email__iexact=attrs['email'], is_superuser=True user = User.objects.filter(email__iexact=attrs['email'], is_superuser=True
).only('id', 'first_name', 'last_name', 'email', 'is_superuser').first() ).only('id', 'first_name', 'last_name', 'email',
'username', 'is_active', 'is_superuser').first()
if not user or not user.check_password(attrs['password']): if not user or not user.check_password(attrs['password']):
raise serializers.ValidationError({'details': ERROR_CODE['2002']}) raise serializers.ValidationError({'details': ERROR_CODE['2002']})
@ -215,10 +216,17 @@ class GuardianSerializer(serializers.ModelSerializer):
def get_user_type(self, obj): def get_user_type(self, obj):
"""user type""" """user type"""
email_verified = UserEmailOtp.objects.filter(email=obj.user.username).last() if self.context.get('user_type', ''):
if email_verified and email_verified.user_type is not None: return self.context.get('user_type')
return email_verified.user_type # remove the below code once user_type can be passed
return str(NUMBER['two']) # from everywhere from where this serializer is being called
else:
email_verified = UserEmailOtp.objects.filter(
email=obj.user.username
).last()
if email_verified and email_verified.user_type is not None:
return email_verified.user_type
return str(NUMBER['two'])
def get_auth(self, obj): def get_auth(self, obj):
"""user email address""" """user email address"""

View File

@ -1,4 +1,6 @@
"""Account utils""" """Account utils"""
from celery import shared_task
"""Import django""" """Import django"""
from django.conf import settings from django.conf import settings
from rest_framework import viewsets, status from rest_framework import viewsets, status
@ -20,7 +22,7 @@ from rest_framework import serializers
# Import messages from base package""" # Import messages from base package"""
from junior.models import Junior from junior.models import Junior
from guardian.models import Guardian from guardian.models import Guardian
from account.models import UserDelete from account.models import UserDelete, UserDeviceDetails
from base.messages import ERROR_CODE from base.messages import ERROR_CODE
from django.utils import timezone from django.utils import timezone
from base.constants import NUMBER from base.constants import NUMBER
@ -44,7 +46,7 @@ from junior.models import JuniorPoints
# referral code, # referral code,
# Define function for generating # Define function for generating
# alphanumeric code # alphanumeric code
# otp expiry
def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num): def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num):
"""delete user account""" """delete user account"""
if user_type == '1' and user_type_data == '1': if user_type == '1' and user_type_data == '1':
@ -109,6 +111,7 @@ def guardian_account_update(user_tb):
for data in jun_data: for data in jun_data:
data.guardian_code.remove(guardian_data.guardian_code) data.guardian_code.remove(guardian_data.guardian_code)
data.save() data.save()
@shared_task()
def send_otp_email(recipient_email, otp): def send_otp_email(recipient_email, otp):
"""Send otp on email with template""" """Send otp on email with template"""
from_email = settings.EMAIL_FROM_ADDRESS from_email = settings.EMAIL_FROM_ADDRESS
@ -124,6 +127,20 @@ def send_otp_email(recipient_email, otp):
) )
return otp return otp
@shared_task
def user_device_details(user, device_id):
"""
Used to store the device id of the user
user: user object
device_id: string
return
"""
device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
if device_details:
device_details.device_id = device_id
device_details.save()
def send_support_email(name, sender, subject, message): def send_support_email(name, sender, subject, message):
"""Send otp on email with template""" """Send otp on email with template"""
to_email = [settings.EMAIL_FROM_ADDRESS] to_email = [settings.EMAIL_FROM_ADDRESS]
@ -234,3 +251,9 @@ def generate_code(value, user_id):
OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1) OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1)
def get_user_full_name(user_obj):
"""
to get user's full name
"""
return f"{user_obj.first_name} {user_obj.last_name}" if user_obj.last_name else user_obj.first_name

View File

@ -1,11 +1,12 @@
"""Account view """ """Account view """
import threading
from notifications.utils import remove_fcm_token from notifications.utils import remove_fcm_token
# django imports # django imports
from datetime import datetime, timedelta from datetime import datetime, timedelta
from rest_framework import viewsets, status, views from rest_framework import viewsets, status, views
from rest_framework.decorators import action from rest_framework.decorators import action
import random
import logging import logging
from django.utils import timezone from django.utils import timezone
import jwt import jwt
@ -35,10 +36,10 @@ from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSeriali
AdminLoginSerializer) AdminLoginSerializer)
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER, ZOD, JUN, GRD from base.constants import NUMBER, ZOD, JUN, GRD, USER_TYPE_FLAG
from guardian.tasks import generate_otp from guardian.tasks import generate_otp
from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response, from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response,
generate_code, OTP_EXPIRY) generate_code, OTP_EXPIRY, user_device_details)
from junior.serializers import JuniorProfileSerializer from junior.serializers import JuniorProfileSerializer
from guardian.serializers import GuardianProfileSerializer from guardian.serializers import GuardianProfileSerializer
@ -280,29 +281,48 @@ class UserPhoneVerification(viewsets.ModelViewSet):
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
class UserLogin(viewsets.ViewSet): class UserLogin(viewsets.ViewSet):
"""User login""" """User login"""
@action(methods=['post'], detail=False) @action(methods=['post'], detail=False)
def login(self, request): def login(self, request):
username = request.data.get('username') username = request.data.get('username')
password = request.data.get('password') password = request.data.get('password')
user_type = request.data.get('user_type')
device_id = request.META.get('HTTP_DEVICE_ID') device_id = request.META.get('HTTP_DEVICE_ID')
user = authenticate(request, username=username, password=password) user = authenticate(request, username=username, password=password)
try: try:
if user is not None: if user is not None:
login(request, user) login(request, user)
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last() if str(user_type) == USER_TYPE_FLAG["TWO"]:
if guardian_data: guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
serializer = GuardianSerializer(guardian_data).data if guardian_data:
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last() serializer = GuardianSerializer(
if junior_data: guardian_data, context={'user_type': user_type}
serializer = JuniorSerializer(junior_data).data ).data
device_details, created = UserDeviceDetails.objects.get_or_create(user=user) else:
if device_details: return custom_error_response(
device_details.device_id = device_id ERROR_CODE["2070"],
device_details.save() response_status=status.HTTP_401_UNAUTHORIZED
)
elif str(user_type) == USER_TYPE_FLAG["FIRST"]:
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
if junior_data:
serializer = JuniorSerializer(
junior_data, context={'user_type': user_type}
).data
else:
return custom_error_response(
ERROR_CODE["2071"],
response_status=status.HTTP_401_UNAUTHORIZED
)
else:
return custom_error_response(
ERROR_CODE["2069"],
response_status=status.HTTP_401_UNAUTHORIZED
)
# storing device id in using thread so the time would be reduced
threading.Thread(target=user_device_details, args=(user, device_id))
return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK) return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK)
else: else:
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED) return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
@ -312,9 +332,12 @@ class UserLogin(viewsets.ViewSet):
refresh = RefreshToken.for_user(user) refresh = RefreshToken.for_user(user)
access_token = str(refresh.access_token) access_token = str(refresh.access_token)
refresh_token = str(refresh) refresh_token = str(refresh)
data = {"auth_token":access_token, "refresh_token":refresh_token, "is_profile_complete": False, data = {
"user_type": email_verified.user_type, "auth_token":access_token,
} "refresh_token":refresh_token,
"is_profile_complete": False,
"user_type": user_type,
}
is_verified = False is_verified = False
if email_verified: if email_verified:
is_verified = email_verified.is_verified is_verified = email_verified.is_verified
@ -323,18 +346,26 @@ class UserLogin(viewsets.ViewSet):
email_verified.otp = otp email_verified.otp = otp
email_verified.save() email_verified.save()
data.update({"email_otp":otp}) data.update({"email_otp":otp})
send_otp_email(username, otp) send_otp_email.delay(username, otp)
return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified}, return custom_response(
response_status=status.HTTP_200_OK) ERROR_CODE['2024'],
{"email_otp": otp, "is_email_verified": is_verified},
response_status=status.HTTP_200_OK
)
data.update({"is_email_verified": is_verified}) data.update({"is_email_verified": is_verified})
return custom_response(SUCCESS_CODE['3003'], data, response_status=status.HTTP_200_OK) return custom_response(
SUCCESS_CODE['3003'],
data,
response_status=status.HTTP_200_OK
)
@action(methods=['post'], detail=False) @action(methods=['post'], detail=False)
def admin_login(self, request): def admin_login(self, request):
email = request.data.get('email') email = request.data.get('email')
password = request.data.get('password') password = request.data.get('password')
user = User.objects.filter(email__iexact=email, is_superuser=True user = User.objects.filter(email__iexact=email, is_superuser=True
).only('id', 'first_name', 'last_name', 'email', 'is_superuser').first() ).only('id', 'first_name', 'last_name', 'email',
'username', 'is_active', 'is_superuser').first()
if not user or 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) return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_400_BAD_REQUEST)
@ -370,12 +401,13 @@ class AdminLoginViewSet(viewsets.GenericViewSet):
class UserEmailVerification(viewsets.ModelViewSet): class UserEmailVerification(viewsets.ModelViewSet):
"""User Email verification""" """User Email verification"""
serializer_class = EmailVerificationSerializer serializer_class = EmailVerificationSerializer
http_method_names = ('post',)
def list(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
try: try:
user_obj = User.objects.filter(username=self.request.GET.get('email')).last() user_obj = User.objects.filter(username=self.request.data.get('email')).last()
email_data = UserEmailOtp.objects.filter(email=self.request.GET.get('email'), email_data = UserEmailOtp.objects.filter(email=self.request.data.get('email'),
otp=self.request.GET.get('otp')).last() otp=self.request.data.get('otp')).last()
if email_data: if email_data:
input_datetime_str = str(email_data.expired_at) input_datetime_str = str(email_data.expired_at)
input_format = "%Y-%m-%d %H:%M:%S.%f%z" input_format = "%Y-%m-%d %H:%M:%S.%f%z"
@ -389,12 +421,12 @@ class UserEmailVerification(viewsets.ModelViewSet):
email_data.is_verified = True email_data.is_verified = True
email_data.save() email_data.save()
if email_data.user_type == '1': if email_data.user_type == '1':
junior_data = Junior.objects.filter(auth__email=self.request.GET.get('email')).last() junior_data = Junior.objects.filter(auth__email=self.request.data.get('email')).last()
if junior_data: if junior_data:
junior_data.is_verified = True junior_data.is_verified = True
junior_data.save() junior_data.save()
else: else:
guardian_data = Guardian.objects.filter(user__email=self.request.GET.get('email')).last() guardian_data = Guardian.objects.filter(user__email=self.request.data.get('email')).last()
if guardian_data: if guardian_data:
guardian_data.is_verified = True guardian_data.is_verified = True
guardian_data.save() guardian_data.save()
@ -504,7 +536,7 @@ class UserNotificationAPIViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
"""profile view""" """profile view"""
queryset = self.queryset.filter(user=request.user) queryset = UserNotification.objects.filter(user=request.user)
serializer = UserNotificationSerializer(queryset, many=True) serializer = UserNotificationSerializer(queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)

View File

@ -50,6 +50,13 @@ USER_TYPE = (
('2', 'guardian'), ('2', 'guardian'),
('3', 'superuser') ('3', 'superuser')
) )
USER_TYPE_FLAG = {
"FIRST" : "1",
"TWO" : "2",
"THREE": "3"
}
"""gender""" """gender"""
GENDERS = ( GENDERS = (
('1', 'Male'), ('1', 'Male'),
@ -122,3 +129,5 @@ MAX_ARTICLE_SURVEY = 10
Already_register_user = "duplicate key value violates unique constraint" Already_register_user = "duplicate key value violates unique constraint"
ARTICLE_CARD_IMAGE_FOLDER = 'article-card-images' ARTICLE_CARD_IMAGE_FOLDER = 'article-card-images'
DATE_FORMAT = '%Y-%m-%d'

View File

@ -94,7 +94,10 @@ ERROR_CODE = {
"2065": "Passwords do not match. Please try again.", "2065": "Passwords do not match. Please try again.",
"2066": "Task does not exist or not in expired state", "2066": "Task does not exist or not in expired state",
"2067": "Action not allowed. User type missing.", "2067": "Action not allowed. User type missing.",
"2068": "No guardian associated with this junior" "2068": "No guardian associated with this junior",
"2069": "Invalid user type",
"2070": "You did not find as a guardian",
"2071": "You did not find as a junior"
} }
"""Success message code""" """Success message code"""

Binary file not shown.

View File

@ -29,7 +29,7 @@ from .utils import real_time, convert_timedelta_into_datetime, update_referral_p
# notification's constant # notification's constant
from notifications.constants import TASK_POINTS, TASK_REJECTED from notifications.constants import TASK_POINTS, TASK_REJECTED
# send notification function # send notification function
from notifications.utils import send_notification from notifications.utils import send_notification, send_notification_to_junior
# In this serializer file # In this serializer file
@ -383,7 +383,8 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
# update complete time of task # update complete time of task
# instance.completed_on = real_time() # instance.completed_on = real_time()
instance.completed_on = timezone.now().astimezone(pytz.utc) instance.completed_on = timezone.now().astimezone(pytz.utc)
send_notification.delay(TASK_POINTS, None, junior_details.auth.id, {}) send_notification_to_junior.delay(TASK_POINTS, None, junior_details.auth.id,
{'task_id': instance.id})
else: else:
# reject the task # reject the task
instance.task_status = str(NUMBER['three']) instance.task_status = str(NUMBER['three'])
@ -391,7 +392,8 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
# update reject time of task # update reject time of task
# instance.rejected_on = real_time() # instance.rejected_on = real_time()
instance.rejected_on = timezone.now().astimezone(pytz.utc) instance.rejected_on = timezone.now().astimezone(pytz.utc)
send_notification.delay(TASK_REJECTED, None, junior_details.auth.id, {}) send_notification_to_junior.delay(TASK_REJECTED, None, junior_details.auth.id,
{'task_id': instance.id})
instance.save() instance.save()
junior_data.save() junior_data.save()
return junior_details return junior_details

View File

@ -21,7 +21,9 @@ from zod_bank.celery import app
# notification's constant # notification's constant
from notifications.constants import REFERRAL_POINTS from notifications.constants import REFERRAL_POINTS
# send notification function # send notification function
from notifications.utils import send_notification from notifications.utils import send_notification, send_notification_to_junior
# Define upload image on # Define upload image on
# ali baba cloud # ali baba cloud
# firstly save image # firstly save image
@ -92,7 +94,7 @@ def update_referral_points(referral_code, referral_code_used):
junior_query.total_points = junior_query.total_points + NUMBER['five'] junior_query.total_points = junior_query.total_points + NUMBER['five']
junior_query.referral_points = junior_query.referral_points + NUMBER['five'] junior_query.referral_points = junior_query.referral_points + NUMBER['five']
junior_query.save() junior_query.save()
send_notification.delay(REFERRAL_POINTS, None, junior_queryset.auth.id, {}) send_notification_to_junior.delay(REFERRAL_POINTS, None, junior_queryset.auth.id, {})

View File

@ -38,8 +38,8 @@ from account.utils import custom_response, custom_error_response, OTP_EXPIRY, se
from base.messages import ERROR_CODE, SUCCESS_CODE from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER, GUARDIAN_CODE_STATUS from base.constants import NUMBER, GUARDIAN_CODE_STATUS
from .utils import upload_image_to_alibaba from .utils import upload_image_to_alibaba
from notifications.constants import REGISTRATION, TASK_CREATED, LEADERBOARD_RANKING from notifications.constants import REGISTRATION, TASK_ASSIGNED, LEADERBOARD_RANKING
from notifications.utils import send_notification from notifications.utils import send_notification_to_junior
""" Define APIs """ """ Define APIs """
# Define Signup API, # Define Signup API,
@ -72,8 +72,6 @@ class SignupViewset(viewsets.ModelViewSet):
user_type=str(request.data['user_type']), expired_at=expiry) user_type=str(request.data['user_type']), expired_at=expiry)
"""Send email to the register user""" """Send email to the register user"""
send_otp_email(request.data['email'], otp) send_otp_email(request.data['email'], otp)
# send push notification for registration
send_notification.delay(REGISTRATION, None, user.id, {})
return custom_response(SUCCESS_CODE['3001'], return custom_response(SUCCESS_CODE['3001'],
response_status=status.HTTP_200_OK) response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
@ -124,38 +122,6 @@ class AllTaskListAPIView(viewsets.ModelViewSet):
serializer = TaskDetailsSerializer(queryset, many=True) serializer = TaskDetailsSerializer(queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
# class TaskListAPIView(viewsets.ModelViewSet):
# """Update guardian profile"""
# serializer_class = TaskDetailsSerializer
# 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':
# queryset = JuniorTask.objects.filter(guardian__user=request.user,
# task_name__icontains=search).order_by('due_date', 'created_at')
# elif search and str(status_value) != '0':
# queryset = JuniorTask.objects.filter(guardian__user=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':
# queryset = JuniorTask.objects.filter(guardian__user=request.user).order_by('due_date', 'created_at')
# elif search is None and str(status_value) != '0':
# queryset = JuniorTask.objects.filter(guardian__user=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 = TaskDetailsSerializer(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 TaskListAPIView(viewsets.ModelViewSet): class TaskListAPIView(viewsets.ModelViewSet):
"""Update guardian profile""" """Update guardian profile"""
@ -218,9 +184,10 @@ class CreateTaskAPIView(viewsets.ModelViewSet):
serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data) serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data)
if serializer.is_valid(): if serializer.is_valid():
# save serializer # save serializer
serializer.save() task = serializer.save()
junior_id = Junior.objects.filter(id=junior).last() junior_id = Junior.objects.filter(id=junior).last()
send_notification.delay(TASK_CREATED, None, junior_id.auth.id, {}) send_notification_to_junior.delay(TASK_ASSIGNED, request.auth.payload['user_id'],
junior_id.auth.id, {'task_id': task.id})
return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK) 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) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e: except Exception as e:
@ -273,7 +240,7 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
# Update the position field for each JuniorPoints object # Update the position field for each JuniorPoints object
for index, junior in enumerate(junior_total_points): for index, junior in enumerate(junior_total_points):
junior.position = index + 1 junior.position = index + 1
send_notification.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {}) send_notification_to_junior.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {})
junior.save() junior.save()
serializer = self.get_serializer(junior_total_points[:NUMBER['fifteen']], many=True) serializer = self.get_serializer(junior_total_points[:NUMBER['fifteen']], many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK) return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)

View File

@ -21,7 +21,7 @@ from guardian.models import Guardian, JuniorTask
from account.models import UserEmailOtp, UserNotification from account.models import UserEmailOtp, UserNotification
from junior.utils import junior_notification_email, junior_approval_mail from junior.utils import junior_notification_email, junior_approval_mail
from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime
from notifications.utils import send_notification from notifications.utils import send_notification, send_notification_to_junior, send_notification_to_guardian
from notifications.constants import (INVITED_GUARDIAN, APPROVED_JUNIOR, SKIPPED_PROFILE_SETUP, TASK_ACTION, from notifications.constants import (INVITED_GUARDIAN, APPROVED_JUNIOR, SKIPPED_PROFILE_SETUP, TASK_ACTION,
TASK_SUBMITTED) TASK_SUBMITTED)
@ -98,7 +98,7 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior) JuniorGuardianRelationship.objects.get_or_create(guardian=guardian_data, junior=junior)
junior.guardian_code_status = str(NUMBER['three']) junior.guardian_code_status = str(NUMBER['three'])
junior_approval_mail(user.email, user.first_name) junior_approval_mail(user.email, user.first_name)
send_notification.delay(APPROVED_JUNIOR, None, guardian_data.user.id, {}) send_notification_to_guardian.delay(APPROVED_JUNIOR, junior.auth.id, guardian_data.user.id, {})
junior.dob = validated_data.get('dob', junior.dob) junior.dob = validated_data.get('dob', junior.dob)
junior.passcode = validated_data.get('passcode', junior.passcode) junior.passcode = validated_data.get('passcode', junior.passcode)
junior.country_name = validated_data.get('country_name', junior.country_name) junior.country_name = validated_data.get('country_name', junior.country_name)
@ -146,8 +146,8 @@ class JuniorDetailSerializer(serializers.ModelSerializer):
"""Meta info""" """Meta info"""
model = Junior model = Junior
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob', fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile',
'image', 'updated_at'] 'created_at', 'image', 'updated_at']
class JuniorDetailListSerializer(serializers.ModelSerializer): class JuniorDetailListSerializer(serializers.ModelSerializer):
"""junior serializer""" """junior serializer"""
@ -305,7 +305,7 @@ class AddJuniorSerializer(serializers.ModelSerializer):
"""Notification email""" """Notification email"""
junior_notification_email(email, full_name, email, password) junior_notification_email(email, full_name, email, password)
# push notification # push notification
send_notification.delay(SKIPPED_PROFILE_SETUP, None, junior_data.auth.id, {}) send_notification_to_junior.delay(SKIPPED_PROFILE_SETUP, None, junior_data.auth.id, {})
return junior_data return junior_data
@ -320,7 +320,7 @@ class RemoveJuniorSerializer(serializers.ModelSerializer):
if instance: if instance:
instance.is_invited = False instance.is_invited = False
instance.guardian_code = '{}' instance.guardian_code = '{}'
instance.guardian_code_status = str(NUMBER['1']) instance.guardian_code_status = str(NUMBER['one'])
instance.save() instance.save()
return instance return instance
@ -333,13 +333,14 @@ class CompleteTaskSerializer(serializers.ModelSerializer):
fields = ('id', 'image') fields = ('id', 'image')
def update(self, instance, validated_data): def update(self, instance, validated_data):
instance.image = validated_data.get('image', instance.image) instance.image = validated_data.get('image', instance.image)
# instance.requested_on = real_time()
instance.requested_on = timezone.now().astimezone(pytz.utc) instance.requested_on = timezone.now().astimezone(pytz.utc)
instance.task_status = str(NUMBER['four']) instance.task_status = str(NUMBER['four'])
instance.is_approved = False instance.is_approved = False
instance.save() instance.save()
send_notification.delay(TASK_SUBMITTED, None, instance.junior.auth.id, {}) send_notification_to_junior.delay(TASK_SUBMITTED, instance.guardian.user.id,
send_notification.delay(TASK_ACTION, None, instance.guardian.user.id, {}) instance.junior.auth.id, {'task_id': instance.id})
send_notification_to_guardian.delay(TASK_ACTION, instance.junior.auth.id,
instance.guardian.user.id, {'task_id': instance.id})
return instance return instance
class JuniorPointsSerializer(serializers.ModelSerializer): class JuniorPointsSerializer(serializers.ModelSerializer):
@ -449,8 +450,8 @@ class AddGuardianSerializer(serializers.ModelSerializer):
"""Notification email""" """Notification email"""
junior_notification_email(email, full_name, email, password) junior_notification_email(email, full_name, email, password)
junior_approval_mail(email, full_name) junior_approval_mail(email, full_name)
send_notification.delay(INVITED_GUARDIAN, None, junior_data.auth.id, {}) send_notification_to_junior.delay(INVITED_GUARDIAN, guardian_data.user.id, junior_data.auth.id, {})
send_notification.delay(APPROVED_JUNIOR, None, guardian_data.user.id, {}) send_notification_to_guardian.delay(APPROVED_JUNIOR, junior_data.auth.id, guardian_data.user.id, {})
return guardian_data return guardian_data
class StartTaskSerializer(serializers.ModelSerializer): class StartTaskSerializer(serializers.ModelSerializer):
@ -503,6 +504,7 @@ class RemoveGuardianCodeSerializer(serializers.ModelSerializer):
model = Junior model = Junior
fields = ('id', ) fields = ('id', )
def update(self, instance, validated_data): def update(self, instance, validated_data):
instance.guardian_code = None
instance.guardian_code_status = str(NUMBER['one']) instance.guardian_code_status = str(NUMBER['one'])
instance.save() instance.save()
return instance return instance

View File

@ -42,7 +42,7 @@ from base.constants import NUMBER, ARTICLE_STATUS
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
from guardian.utils import upload_image_to_alibaba from guardian.utils import upload_image_to_alibaba
from .utils import update_positions_based_on_points from .utils import update_positions_based_on_points
from notifications.utils import send_notification from notifications.utils import send_notification, send_notification_to_junior
from notifications.constants import REMOVE_JUNIOR from notifications.constants import REMOVE_JUNIOR
from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer, from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer,
@ -269,7 +269,7 @@ class RemoveJuniorAPIView(views.APIView):
if serializer.is_valid(): if serializer.is_valid():
# save serializer # save serializer
serializer.save() serializer.save()
send_notification.delay(REMOVE_JUNIOR, None, junior_queryset.auth.id, {}) send_notification_to_junior.delay(REMOVE_JUNIOR, None, junior_queryset.auth.id, {})
return custom_response(SUCCESS_CODE['3022'], serializer.data, response_status=status.HTTP_200_OK) 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) return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
else: else:
@ -334,7 +334,8 @@ class CompleteJuniorTaskAPIView(views.APIView):
image_url = upload_image_to_alibaba(image, filename) image_url = upload_image_to_alibaba(image, filename)
# fetch junior query # fetch junior query
task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user).last() task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user
).select_related('guardian', 'junior').last()
if task_queryset: if task_queryset:
# use CompleteTaskSerializer serializer # use CompleteTaskSerializer serializer
if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]: if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]:

View File

@ -3,7 +3,7 @@ notification constants file
""" """
from base.constants import NUMBER from base.constants import NUMBER
REGISTRATION = NUMBER['one'] REGISTRATION = NUMBER['one']
TASK_CREATED = NUMBER['two'] TASK_ASSIGNED = NUMBER['two']
INVITED_GUARDIAN = NUMBER['three'] INVITED_GUARDIAN = NUMBER['three']
APPROVED_JUNIOR = NUMBER['four'] APPROVED_JUNIOR = NUMBER['four']
REFERRAL_POINTS = NUMBER['five'] REFERRAL_POINTS = NUMBER['five']
@ -21,17 +21,17 @@ NOTIFICATION_DICT = {
"title": "Successfully registered!", "title": "Successfully registered!",
"body": "You have registered successfully. Now login and complete your profile." "body": "You have registered successfully. Now login and complete your profile."
}, },
TASK_CREATED: { TASK_ASSIGNED: {
"title": "Task created!", "title": "New task assigned !!",
"body": "Task created successfully." "body": "{from_user} has assigned you a new task."
}, },
INVITED_GUARDIAN: { INVITED_GUARDIAN: {
"title": "Invite guardian", "title": "Invite guardian",
"body": "Invite guardian successfully" "body": "Invite guardian successfully"
}, },
APPROVED_JUNIOR: { APPROVED_JUNIOR: {
"title": "Approve junior", "title": "Approve junior !",
"body": "You have request from junior to associate with you" "body": "You have request from {from_user} to associate with you."
}, },
REFERRAL_POINTS: { REFERRAL_POINTS: {
"title": "Earn Referral points", "title": "Earn Referral points",
@ -47,15 +47,15 @@ NOTIFICATION_DICT = {
}, },
SKIPPED_PROFILE_SETUP: { SKIPPED_PROFILE_SETUP: {
"title": "Skipped profile setup!", "title": "Skipped profile setup!",
"body": "Your guardian has been setup your profile." "body": "Your guardian {from_user} has setup your profile."
}, },
TASK_SUBMITTED: { TASK_SUBMITTED: {
"title": "Task submitted!", "title": "Task submitted!",
"body": "Your task has been submitted successfully." "body": "Your task has been submitted successfully."
}, },
TASK_ACTION: { TASK_ACTION: {
"title": "Task approval!", "title": "Task completion approval!",
"body": "You have request for task approval." "body": "You have request from {from_user} for task approval."
}, },
LEADERBOARD_RANKING: { LEADERBOARD_RANKING: {
"title": "Leader board rank!", "title": "Leader board rank!",
@ -67,6 +67,6 @@ NOTIFICATION_DICT = {
}, },
TEST_NOTIFICATION: { TEST_NOTIFICATION: {
"title": "Test Notification", "title": "Test Notification",
"body": "This notification is for testing purpose" "body": "This notification is for testing purpose from {from_user}."
} }
} }

View File

@ -35,7 +35,8 @@ class NotificationListSerializer(serializers.ModelSerializer):
class Meta(object): class Meta(object):
"""meta info""" """meta info"""
model = Notification model = Notification
fields = ['id', 'data', 'is_read'] fields = ['id', 'data', 'is_read', 'created_at']
class ReadNotificationSerializer(serializers.ModelSerializer): class ReadNotificationSerializer(serializers.ModelSerializer):
"""User task Serializer""" """User task Serializer"""

View File

@ -10,6 +10,9 @@ from firebase_admin.messaging import Message, Notification as FirebaseNotificati
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from account.models import UserNotification from account.models import UserNotification
from account.utils import get_user_full_name
from guardian.models import Guardian
from junior.models import Junior
from notifications.constants import NOTIFICATION_DICT from notifications.constants import NOTIFICATION_DICT
from notifications.models import Notification from notifications.models import Notification
@ -39,30 +42,80 @@ def remove_fcm_token(user_id: int, access_token: str, registration_id) -> None:
print(e) print(e)
def get_basic_detail(notification_type, from_user_id, to_user_id): def get_basic_detail(from_user_id, to_user_id):
""" used to get the basic details """ """
notification_data = NOTIFICATION_DICT[notification_type] used to get the basic details
"""
from_user = User.objects.get(id=from_user_id) if from_user_id else None from_user = User.objects.get(id=from_user_id) if from_user_id else None
to_user = User.objects.get(id=to_user_id) to_user = User.objects.get(id=to_user_id)
return notification_data, from_user, to_user return from_user, to_user
@shared_task() def get_notification_data(notification_type, from_user, to_user, extra_data):
def send_notification(notification_type, from_user_id, to_user_id, extra_data): """
""" used to send the push for the given notification type """ get notification and push data
(notification_data, from_user, to_user) = get_basic_detail(notification_type, from_user_id, to_user_id) :param notification_type: notification_type
:param from_user: from_user obj
:param to_user: to_user obj
:param extra_data: any extra data provided
:return: notification and push data
"""
push_data = NOTIFICATION_DICT[notification_type].copy()
notification_data = push_data.copy()
notification_data['to_user'] = get_user_full_name(to_user)
if from_user:
from_user_name = get_user_full_name(from_user)
push_data['body'] = push_data['body'].format(from_user=from_user_name)
notification_data['body'] = notification_data['body'].format(from_user=from_user_name)
notification_data['from_user'] = from_user_name
notification_data.update(extra_data)
return notification_data, push_data
def send_notification(notification_type, from_user, to_user, extra_data):
"""
used to send the push for the given notification type
"""
# (from_user, to_user) = get_basic_detail(from_user_id, to_user_id)
notification_data, push_data = get_notification_data(notification_type, from_user, to_user, extra_data)
user_notification_type = UserNotification.objects.filter(user=to_user).first() user_notification_type = UserNotification.objects.filter(user=to_user).first()
data = notification_data notification_data.update({'badge': Notification.objects.filter(notification_to=to_user, is_read=False).count()})
Notification.objects.create(notification_type=notification_type, notification_from=from_user, Notification.objects.create(notification_type=notification_type, notification_from=from_user,
notification_to=to_user, data=data) notification_to=to_user, data=notification_data)
if user_notification_type.push_notification: if user_notification_type.push_notification:
data.update({'badge': Notification.objects.filter(notification_to=to_user, is_read=False).count()}) send_push(to_user, push_data)
send_push(to_user, data)
def send_push(user, data): def send_push(user, data):
""" used to send push notification to specific user """ """ used to send push notification to specific user """
notification_data = data.pop('data', None)
user.fcmdevice_set.filter(active=True).send_message( user.fcmdevice_set.filter(active=True).send_message(
Message(notification=FirebaseNotification(data['title'], data['body']), data=notification_data) Message(notification=FirebaseNotification(data['title'], data['body']), data=data)
) )
@shared_task()
def send_notification_to_guardian(notification_type, from_user_id, to_user_id, extra_data):
from_user = None
if from_user_id:
from_user = Junior.objects.filter(auth_id=from_user_id).select_related('auth').first()
extra_data['from_user_image'] = from_user.image
from_user = from_user.auth
to_user = Guardian.objects.filter(user_id=to_user_id).select_related('user').first()
extra_data['to_user_image'] = to_user.image
send_notification(notification_type, from_user, to_user.user, extra_data)
@shared_task()
def send_notification_to_junior(notification_type, from_user_id, to_user_id, extra_data):
from_user = None
if from_user_id:
from_user = Guardian.objects.filter(user_id=from_user_id).select_related('user').first()
extra_data['from_user_image'] = from_user.image
from_user = from_user.user
to_user = Junior.objects.filter(auth_id=to_user_id).select_related('auth').first()
extra_data['to_user_image'] = to_user.image
send_notification(notification_type, from_user, to_user.auth, extra_data)

View File

@ -11,8 +11,10 @@ from rest_framework import viewsets, status, views
from account.utils import custom_response, custom_error_response from account.utils import custom_response, custom_error_response
from base.messages import SUCCESS_CODE, ERROR_CODE from base.messages import SUCCESS_CODE, ERROR_CODE
from notifications.constants import TEST_NOTIFICATION from notifications.constants import TEST_NOTIFICATION
# Import serializer
from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer
from notifications.utils import send_notification from notifications.utils import send_notification, send_notification_to_guardian, send_notification_to_junior
# Import model
from notifications.models import Notification from notifications.models import Notification
@ -54,7 +56,10 @@ class NotificationViewSet(viewsets.GenericViewSet):
to send test notification to send test notification
:return: :return:
""" """
send_notification.delay(TEST_NOTIFICATION, None, request.auth.payload['user_id'], {}) send_notification_to_guardian(TEST_NOTIFICATION, None, request.auth.payload['user_id'],
{'task_id': None})
send_notification_to_junior(TEST_NOTIFICATION, request.auth.payload['user_id'], None,
{'task_id': None})
return custom_response(SUCCESS_CODE["3000"]) return custom_response(SUCCESS_CODE["3000"])
@action(methods=['get'], detail=False, url_path='list', url_name='list', @action(methods=['get'], detail=False, url_path='list', url_name='list',

View File

@ -4,7 +4,6 @@ web_admin analytics serializer file
from rest_framework import serializers from rest_framework import serializers
from junior.models import JuniorPoints, Junior from junior.models import JuniorPoints, Junior
from web_admin.serializers.user_management_serializer import JuniorSerializer
class JuniorLeaderboardSerializer(serializers.ModelSerializer): class JuniorLeaderboardSerializer(serializers.ModelSerializer):

View File

@ -224,7 +224,7 @@ class ArticleListSerializer(serializers.ModelSerializer):
total_points = serializers.SerializerMethodField('get_total_points') total_points = serializers.SerializerMethodField('get_total_points')
is_completed = serializers.SerializerMethodField('get_is_completed') is_completed = serializers.SerializerMethodField('get_is_completed')
class Meta: class Meta(object):
""" """
meta class meta class
""" """
@ -238,9 +238,10 @@ class ArticleListSerializer(serializers.ModelSerializer):
def get_is_completed(self, obj): def get_is_completed(self, obj):
"""complete all question""" """complete all question"""
junior_article = JuniorArticle.objects.filter(article=obj).last() context_data = self.context.get('user')
junior_article = JuniorArticle.objects.filter(junior__auth=context_data, article=obj).last()
if junior_article: if junior_article:
junior_article.is_completed return junior_article.is_completed
return False return False
class ArticleQuestionSerializer(serializers.ModelSerializer): class ArticleQuestionSerializer(serializers.ModelSerializer):
@ -278,7 +279,7 @@ class ArticleQuestionSerializer(serializers.ModelSerializer):
return junior_article_obj.submitted_answer.id return junior_article_obj.submitted_answer.id
return None return None
class Meta: class Meta(object):
""" """
meta class meta class
""" """
@ -299,7 +300,7 @@ class StartAssessmentSerializer(serializers.ModelSerializer):
if data: if data:
return data.current_que_page return data.current_que_page
return NUMBER['zero'] return NUMBER['zero']
class Meta: class Meta(object):
""" """
meta class meta class
""" """
@ -325,7 +326,7 @@ class ArticleCardlistSerializer(serializers.ModelSerializer):
return data.current_card_page return data.current_card_page
return NUMBER['zero'] return NUMBER['zero']
class Meta: class Meta(object):
""" """
meta class meta class
""" """

View File

@ -12,14 +12,14 @@ from rest_framework.permissions import IsAuthenticated
# django imports # django imports
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db.models import Q from django.db.models import Q
from django.db.models import Count, OuterRef, Subquery, Sum from django.db.models import Count
from django.db.models.functions import TruncDate from django.db.models.functions import TruncDate
from django.db.models import F, Window from django.db.models import F, Window
from django.db.models.functions.window import Rank from django.db.models.functions.window import Rank
# local imports # local imports
from account.utils import custom_response from account.utils import custom_response
from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, EXPIRED from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, EXPIRED, DATE_FORMAT
from guardian.models import JuniorTask from guardian.models import JuniorTask
from junior.models import JuniorPoints from junior.models import JuniorPoints
from web_admin.pagination import CustomPageNumberPagination from web_admin.pagination import CustomPageNumberPagination
@ -32,6 +32,10 @@ USER = get_user_model()
class AnalyticsViewSet(GenericViewSet): class AnalyticsViewSet(GenericViewSet):
""" """
analytics api view analytics api view
to get user report (active users, guardians and juniors counts)
to get new user sign up report
to get task report (completed, in-progress, requested and rejected tasks count)
to get junior leaderboard and ranking
""" """
serializer_class = None serializer_class = None
permission_classes = [IsAuthenticated, AdminPermission] permission_classes = [IsAuthenticated, AdminPermission]
@ -50,7 +54,8 @@ class AnalyticsViewSet(GenericViewSet):
def total_users_count(self, request, *args, **kwargs): def total_users_count(self, request, *args, **kwargs):
""" """
api method to get total users, guardians and juniors api method to get total users, guardians and juniors
:param request: query params {start_date and end_date}, date format (yyyy-mm-dd) :param request: start_date: date format (yyyy-mm-dd)
:param request: end_date: date format (yyyy-mm-dd)
:return: :return:
""" """
@ -58,8 +63,8 @@ class AnalyticsViewSet(GenericViewSet):
start_date = end_date - datetime.timedelta(days=6) start_date = end_date - datetime.timedelta(days=6)
if request.query_params.get('start_date') and request.query_params.get('end_date'): 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') start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), '%Y-%m-%d') end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
user_qs = self.get_queryset() user_qs = self.get_queryset()
queryset = user_qs.filter(date_joined__range=(start_date, (end_date + datetime.timedelta(days=1)))) queryset = user_qs.filter(date_joined__range=(start_date, (end_date + datetime.timedelta(days=1))))
@ -74,15 +79,16 @@ class AnalyticsViewSet(GenericViewSet):
def new_signups(self, request, *args, **kwargs): def new_signups(self, request, *args, **kwargs):
""" """
api method to get new signups api method to get new signups
:param request: query params {start_date and end_date}, date format (yyyy-mm-dd) :param request: start_date: date format (yyyy-mm-dd)
:param request: end_date: date format (yyyy-mm-dd)
:return: :return:
""" """
end_date = datetime.date.today() end_date = datetime.date.today()
start_date = end_date - datetime.timedelta(days=6) start_date = end_date - datetime.timedelta(days=6)
if request.query_params.get('start_date') and request.query_params.get('end_date'): 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') start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), '%Y-%m-%d') end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
user_qs = self.get_queryset() user_qs = self.get_queryset()
signup_data = user_qs.filter(date_joined__range=[start_date, (end_date + datetime.timedelta(days=1))] signup_data = user_qs.filter(date_joined__range=[start_date, (end_date + datetime.timedelta(days=1))]
@ -94,16 +100,17 @@ class AnalyticsViewSet(GenericViewSet):
@action(methods=['get'], url_name='assign-tasks', url_path='assign-tasks', detail=False) @action(methods=['get'], url_name='assign-tasks', url_path='assign-tasks', detail=False)
def assign_tasks_report(self, request, *args, **kwargs): def assign_tasks_report(self, request, *args, **kwargs):
""" """
api method to get assign tasks api method to get assign tasks count for (completed, in-progress, requested and rejected) task
:param request: query params {start_date and end_date}, date format (yyyy-mm-dd) :param request: start_date: date format (yyyy-mm-dd)
:param request: end_date: date format (yyyy-mm-dd)
:return: :return:
""" """
end_date = datetime.date.today() end_date = datetime.date.today()
start_date = end_date - datetime.timedelta(days=6) start_date = end_date - datetime.timedelta(days=6)
if request.query_params.get('start_date') and request.query_params.get('end_date'): 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') start_date = datetime.datetime.strptime(request.query_params.get('start_date'), DATE_FORMAT)
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), '%Y-%m-%d') end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
assign_tasks = JuniorTask.objects.filter( assign_tasks = JuniorTask.objects.filter(
created_at__range=[start_date, (end_date + datetime.timedelta(days=1))] created_at__range=[start_date, (end_date + datetime.timedelta(days=1))]
@ -122,11 +129,10 @@ class AnalyticsViewSet(GenericViewSet):
serializer_class=LeaderboardSerializer) serializer_class=LeaderboardSerializer)
def junior_leaderboard(self, request): def junior_leaderboard(self, request):
""" """
to get junior leaderboard and rank
:param request: :param request:
:return: :return:
""" """
# queryset = JuniorPoints.objects.all().order_by('-total_points', 'junior__created_at')
queryset = JuniorPoints.objects.prefetch_related('junior', 'junior__auth').annotate(rank=Window( queryset = JuniorPoints.objects.prefetch_related('junior', 'junior__auth').annotate(rank=Window(
expression=Rank(), expression=Rank(),
order_by=[F('total_points').desc(), 'junior__created_at'] order_by=[F('total_points').desc(), 'junior__created_at']

View File

@ -221,10 +221,7 @@ class ArticleListViewSet(GenericViewSet, mixins.ListModelMixin):
:return: list of article :return: list of article
""" """
queryset = self.get_queryset() queryset = self.get_queryset()
count = queryset.count() serializer = self.serializer_class(queryset, context={"user": request.user}, many=True)
paginator = self.pagination_class()
paginated_queryset = paginator.paginate_queryset(queryset, request)
serializer = self.serializer_class(paginated_queryset, many=True)
return custom_response(None, data=serializer.data) return custom_response(None, data=serializer.data)
class ArticleCardListViewSet(viewsets.ModelViewSet): class ArticleCardListViewSet(viewsets.ModelViewSet):