Compare commits

..

68 Commits

Author SHA1 Message Date
c7c55f2a04 user notification issue 2023-08-16 16:41:08 +05:30
bcf308b6eb Merge pull request #213 from KiwiTechLLC/qa
Qa
2023-08-16 11:39:02 +05:30
74328f37b2 Merge pull request #212 from KiwiTechLLC/dev
Dev
2023-08-16 11:38:39 +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
54748a6704 Merge pull request #210 from KiwiTechLLC/qa
Qa
2023-08-14 18:24:10 +05:30
d8f4467d98 Merge pull request #209 from KiwiTechLLC/dev
guardian code status
2023-08-14 18:23:41 +05:30
7c809776b6 guardian code status 2023-08-14 18:22:50 +05:30
74e704570a Merge pull request #208 from KiwiTechLLC/qa
Qa
2023-08-14 17:34:25 +05:30
a9cc05c675 Merge pull request #207 from KiwiTechLLC/dev
Dev
2023-08-14 17:33:56 +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
136d0b732a Merge pull request #204 from KiwiTechLLC/qa
Qa
2023-08-14 11:46:35 +05:30
83d7d119be Merge pull request #203 from KiwiTechLLC/dev
Dev
2023-08-14 11:46:04 +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
b974cc2010 Merge pull request #201 from KiwiTechLLC/qa
Qa
2023-08-11 17:08:10 +05:30
19a6475097 Merge pull request #200 from KiwiTechLLC/dev
Dev
2023-08-11 16:55:51 +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
d5c30f2029 added pagination in leaderboard admin 2023-08-11 15:56:22 +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
4ca60af5da Merge pull request #195 from KiwiTechLLC/dev
Dev
2023-08-11 13:50:53 +05:30
807526acfa Merge pull request #191 from KiwiTechLLC/dev
Dev
2023-08-11 12:24:28 +05:30
f4149379c2 Merge pull request #188 from KiwiTechLLC/dev
Dev
2023-08-10 19:21:12 +05:30
4f02cef0f9 Optimised login api 2023-08-10 18:43:03 +05:30
b8f1acaed8 Merge pull request #185 from KiwiTechLLC/dev
Dev
2023-08-10 18:37:06 +05:30
9e5dd5e3d5 Merge pull request #183 from KiwiTechLLC/dev
Dev
2023-08-10 17:04:06 +05:30
b961044e4d Merge pull request #179 from KiwiTechLLC/dev
Dev
2023-08-10 11:57:29 +05:30
2498394127 Merge pull request #177 from KiwiTechLLC/dev
Dev
2023-08-09 19:22:42 +05:30
2fc65d462d Merge pull request #174 from KiwiTechLLC/dev
Dev
2023-08-09 18:11:40 +05:30
cdf656fdad Merge pull request #170 from KiwiTechLLC/dev
Dev
2023-08-09 14:51:13 +05:30
8eaf8751c2 Merge pull request #165 from KiwiTechLLC/dev
Dev
2023-08-08 17:14:36 +05:30
6867920754 Merge pull request #163 from KiwiTechLLC/dev
Dev
2023-08-08 16:07:14 +05:30
22ba4288d9 Merge pull request #161 from KiwiTechLLC/dev
Dev
2023-08-08 15:04:50 +05:30
7ab16cb3de Merge pull request #158 from KiwiTechLLC/dev
Dev
2023-08-08 14:24:44 +05:30
07d150309b Merge pull request #146 from KiwiTechLLC/dev
Dev
2023-08-04 15:04:55 +05:30
3801e6e027 Merge pull request #142 from KiwiTechLLC/dev
Dev
2023-08-03 14:59:49 +05:30
e89fc513cb Merge pull request #138 from KiwiTechLLC/dev
Dev
2023-08-02 14:25:06 +05:30
e1af1c200d Merge pull request #136 from KiwiTechLLC/dev
Dev
2023-08-02 11:33:29 +05:30
4fddc7b3e2 Merge pull request #131 from KiwiTechLLC/qa
Qa
2023-07-28 20:19:40 +05:30
b238379a22 Merge pull request #130 from KiwiTechLLC/dev
Dev
2023-07-28 19:49:56 +05:30
ed18758cc5 Merge pull request #125 from KiwiTechLLC/qa
Qa
2023-07-28 11:13:10 +05:30
c081bc621d Merge pull request #124 from KiwiTechLLC/dev
merging dev into qa
2023-07-27 22:04:51 +05:30
d2c8b18e3f Merge pull request #120 from KiwiTechLLC/dev
merging dev itno qa
2023-07-27 11:37:25 +05:30
bdc0ba4fd5 Merge pull request #117 from KiwiTechLLC/dev
Dev
2023-07-26 16:58:38 +05:30
3af2584d6a Merge pull request #115 from KiwiTechLLC/dev
Dev
2023-07-26 11:09:40 +05:30
62cf2b14bf Merge pull request #113 from KiwiTechLLC/dev
merging dev into qa
2023-07-26 11:01:45 +05:30
cbd3d139a5 Merge pull request #110 from KiwiTechLLC/dev
Dev
2023-07-25 17:36:49 +05:30
7cb792c6cf Merge pull request #104 from KiwiTechLLC/dev
Dev
2023-07-25 11:52:36 +05:30
5ea28bbd75 Merge pull request #102 from KiwiTechLLC/dev
Dev
2023-07-24 15:56:54 +05:30
180104ece8 Merge pull request #100 from KiwiTechLLC/dev
Dev
2023-07-24 11:04:08 +05:30
fb74c6c207 Merge pull request #67 from KiwiTechLLC/qa
change access token duration
2023-07-14 12:46:38 +05:30
87cb49d34d Merge pull request #66 from KiwiTechLLC/qa
Qa
2023-07-13 19:25:57 +05:30
4261b5ad29 Merge pull request #31 from KiwiTechLLC/qa
Qa
2023-06-30 17:22:54 +05:30
6c0c3e0aca Merge pull request #29 from KiwiTechLLC/qa
Qa
2023-06-30 16:26:16 +05:30
c6b220d6f2 Merge pull request #27 from KiwiTechLLC/qa
Qa
2023-06-30 15:54:15 +05:30
b5b793dc88 Merge pull request #25 from KiwiTechLLC/qa
Qa
2023-06-30 11:19:12 +05:30
1b5019e347 Merge pull request #22 from KiwiTechLLC/qa
Qa
2023-06-29 21:49:47 +05:30
8c1e96a3df Merge pull request #19 from KiwiTechLLC/qa
Qa
2023-06-29 21:25:52 +05:30
545fa8229b Merge pull request #12 from KiwiTechLLC/qa
Qa to stage First commit
2023-06-28 17:53:09 +05:30
11 changed files with 130 additions and 43 deletions

View File

@ -216,10 +216,17 @@ class GuardianSerializer(serializers.ModelSerializer):
def get_user_type(self, obj):
"""user type"""
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'])
if self.context.get('user_type', ''):
return self.context.get('user_type')
# remove the below code once user_type can be passed
# 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):
"""user email address"""

View File

@ -1,4 +1,6 @@
"""Account utils"""
from celery import shared_task
"""Import django"""
from django.conf import settings
from rest_framework import viewsets, status
@ -20,7 +22,7 @@ from rest_framework import serializers
# Import messages from base package"""
from junior.models import Junior
from guardian.models import Guardian
from account.models import UserDelete
from account.models import UserDelete, UserDeviceDetails
from base.messages import ERROR_CODE
from django.utils import timezone
from base.constants import NUMBER
@ -44,7 +46,7 @@ from junior.models import JuniorPoints
# referral code,
# Define function for generating
# alphanumeric code
# otp expiry
def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num):
"""delete user account"""
if user_type == '1' and user_type_data == '1':
@ -109,6 +111,7 @@ def guardian_account_update(user_tb):
for data in jun_data:
data.guardian_code.remove(guardian_data.guardian_code)
data.save()
@shared_task()
def send_otp_email(recipient_email, otp):
"""Send otp on email with template"""
from_email = settings.EMAIL_FROM_ADDRESS
@ -124,6 +127,20 @@ def send_otp_email(recipient_email, 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):
"""Send otp on email with template"""
to_email = [settings.EMAIL_FROM_ADDRESS]

View File

@ -1,11 +1,12 @@
"""Account view """
import threading
from notifications.utils import remove_fcm_token
# django imports
from datetime import datetime, timedelta
from rest_framework import viewsets, status, views
from rest_framework.decorators import action
import random
import logging
from django.utils import timezone
import jwt
@ -35,10 +36,10 @@ from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSeriali
AdminLoginSerializer)
from rest_framework_simplejwt.tokens import RefreshToken
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 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 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)
class UserLogin(viewsets.ViewSet):
"""User login"""
@action(methods=['post'], detail=False)
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user_type = request.data.get('user_type')
device_id = request.META.get('HTTP_DEVICE_ID')
user = authenticate(request, username=username, password=password)
try:
if user is not None:
login(request, user)
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
if guardian_data:
serializer = GuardianSerializer(guardian_data).data
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
if junior_data:
serializer = JuniorSerializer(junior_data).data
device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
if device_details:
device_details.device_id = device_id
device_details.save()
if str(user_type) == USER_TYPE_FLAG["TWO"]:
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
if guardian_data:
serializer = GuardianSerializer(
guardian_data, context={'user_type': user_type}
).data
else:
return custom_error_response(
ERROR_CODE["2070"],
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)
else:
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)
access_token = str(refresh.access_token)
refresh_token = str(refresh)
data = {"auth_token":access_token, "refresh_token":refresh_token, "is_profile_complete": False,
"user_type": email_verified.user_type,
}
data = {
"auth_token":access_token,
"refresh_token":refresh_token,
"is_profile_complete": False,
"user_type": user_type,
}
is_verified = False
if email_verified:
is_verified = email_verified.is_verified
@ -323,11 +346,18 @@ class UserLogin(viewsets.ViewSet):
email_verified.otp = otp
email_verified.save()
data.update({"email_otp":otp})
send_otp_email(username, otp)
return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified},
response_status=status.HTTP_200_OK)
send_otp_email.delay(username, otp)
return custom_response(
ERROR_CODE['2024'],
{"email_otp": otp, "is_email_verified": is_verified},
response_status=status.HTTP_200_OK
)
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)
def admin_login(self, request):
@ -505,7 +535,7 @@ class UserNotificationAPIViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
"""profile view"""
queryset = self.queryset.filter(user=request.user)
queryset = UserNotification.objects.filter(user=request.user)
serializer = UserNotificationSerializer(queryset, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)

View File

@ -50,6 +50,13 @@ USER_TYPE = (
('2', 'guardian'),
('3', 'superuser')
)
USER_TYPE_FLAG = {
"FIRST" : "1",
"TWO" : "2",
"THREE": "3"
}
"""gender"""
GENDERS = (
('1', 'Male'),

View File

@ -94,7 +94,10 @@ ERROR_CODE = {
"2065": "Passwords do not match. Please try again.",
"2066": "Task does not exist or not in expired state",
"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"""

View File

@ -146,8 +146,8 @@ class JuniorDetailSerializer(serializers.ModelSerializer):
"""Meta info"""
model = Junior
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',
'image', 'updated_at']
'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile',
'created_at', 'image', 'updated_at']
class JuniorDetailListSerializer(serializers.ModelSerializer):
"""junior serializer"""
@ -320,7 +320,7 @@ class RemoveJuniorSerializer(serializers.ModelSerializer):
if instance:
instance.is_invited = False
instance.guardian_code = '{}'
instance.guardian_code_status = str(NUMBER['1'])
instance.guardian_code_status = str(NUMBER['one'])
instance.save()
return instance
@ -502,6 +502,7 @@ class RemoveGuardianCodeSerializer(serializers.ModelSerializer):
model = Junior
fields = ('id', )
def update(self, instance, validated_data):
instance.guardian_code = None
instance.guardian_code_status = str(NUMBER['one'])
instance.save()
return instance

View File

@ -11,8 +11,10 @@ from rest_framework import viewsets, status, views
from account.utils import custom_response, custom_error_response
from base.messages import SUCCESS_CODE, ERROR_CODE
from notifications.constants import TEST_NOTIFICATION
# Import serializer
from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer
from notifications.utils import send_notification
# Import model
from notifications.models import Notification

13
web_admin/pagination.py Normal file
View File

@ -0,0 +1,13 @@
"""
web_admin pagination file
"""
from rest_framework.pagination import PageNumberPagination
class CustomPageNumberPagination(PageNumberPagination):
"""
custom paginator class
"""
page_size = 10 # Set the desired page size
page_size_query_param = 'page_size'
max_page_size = 100 # Set a maximum page size if needed

View File

@ -224,7 +224,7 @@ class ArticleListSerializer(serializers.ModelSerializer):
total_points = serializers.SerializerMethodField('get_total_points')
is_completed = serializers.SerializerMethodField('get_is_completed')
class Meta:
class Meta(object):
"""
meta class
"""
@ -238,9 +238,10 @@ class ArticleListSerializer(serializers.ModelSerializer):
def get_is_completed(self, obj):
"""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:
junior_article.is_completed
return junior_article.is_completed
return False
class ArticleQuestionSerializer(serializers.ModelSerializer):
@ -278,7 +279,7 @@ class ArticleQuestionSerializer(serializers.ModelSerializer):
return junior_article_obj.submitted_answer.id
return None
class Meta:
class Meta(object):
"""
meta class
"""
@ -299,7 +300,7 @@ class StartAssessmentSerializer(serializers.ModelSerializer):
if data:
return data.current_que_page
return NUMBER['zero']
class Meta:
class Meta(object):
"""
meta class
"""
@ -325,7 +326,7 @@ class ArticleCardlistSerializer(serializers.ModelSerializer):
return data.current_card_page
return NUMBER['zero']
class Meta:
class Meta(object):
"""
meta class
"""

View File

@ -1,10 +1,15 @@
"""
web_admin analytics view file
"""
# python imports
import datetime
# third party imports
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
# django imports
from django.contrib.auth import get_user_model
from django.db.models import Q
from django.db.models import Count
@ -12,10 +17,13 @@ from django.db.models.functions import TruncDate
from django.db.models import F, Window
from django.db.models.functions.window import Rank
# local imports
from account.utils import custom_response
from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, EXPIRED, DATE_FORMAT
from guardian.models import JuniorTask
from junior.models import JuniorPoints
from web_admin.pagination import CustomPageNumberPagination
from web_admin.permission import AdminPermission
from web_admin.serializers.analytics_serializer import LeaderboardSerializer
USER = get_user_model()
@ -30,6 +38,7 @@ class AnalyticsViewSet(GenericViewSet):
to get junior leaderboard and ranking
"""
serializer_class = None
permission_classes = [IsAuthenticated, AdminPermission]
def get_queryset(self):
user_qs = USER.objects.filter(
@ -128,7 +137,7 @@ class AnalyticsViewSet(GenericViewSet):
expression=Rank(),
order_by=[F('total_points').desc(), 'junior__created_at']
)).order_by('-total_points', 'junior__created_at')
paginator = self.pagination_class()
paginator = CustomPageNumberPagination()
paginated_queryset = paginator.paginate_queryset(queryset, request)
serializer = self.serializer_class(paginated_queryset, many=True)
return custom_response(None, serializer.data)

View File

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