Compare commits

..

63 Commits

Author SHA1 Message Date
d5c30f2029 added pagination in leaderboard admin 2023-08-11 15:56:22 +05:30
18cb885410 Merge pull request #193 from KiwiTechLLC/ZBKADM-71
leaderboard ranking
2023-08-11 14:13:05 +05:30
4d7209df19 Merge pull request #194 from KiwiTechLLC/sprint4
remove deleted user from leaderboard
2023-08-11 13:40:48 +05:30
94c76b7f2e remove deleted user from leaderboard 2023-08-11 13:39:25 +05:30
af8ea39200 leaderboard ranking 2023-08-11 13:37:44 +05:30
6e9304b2cc Merge pull request #192 from KiwiTechLLC/sprint4
is complete article key
2023-08-11 13:04:54 +05:30
5eab8f4907 is complete article key 2023-08-11 13:04:05 +05:30
f750487b88 Merge pull request #190 from KiwiTechLLC/sprint4
add correct and attempt answer
2023-08-11 12:21:47 +05:30
8b0032f6d2 junior point table 2023-08-11 12:18:35 +05:30
bb65f81200 add correct and attempt answer 2023-08-11 11:48:02 +05:30
04db40e100 Merge pull request #189 from KiwiTechLLC/sprint4
create article
2023-08-10 21:24:15 +05:30
1e162255d7 create article 2023-08-10 20:17:24 +05:30
a479f3cb62 Merge pull request #187 from KiwiTechLLC/sprint4
task points
2023-08-10 19:06:32 +05:30
fbd6f9ece5 task points 2023-08-10 19:05:33 +05:30
11c84208b7 task points 2023-08-10 19:00:37 +05:30
80dffb7942 Merge pull request #184 from KiwiTechLLC/ZBKADM-71
image name fix, remove '|' character
2023-08-10 18:21:10 +05:30
0a8c2cf56d image name fix, remove '|' character 2023-08-10 18:17:49 +05:30
03fb4f4176 Merge pull request #182 from KiwiTechLLC/sprint4
current page update in article api
2023-08-10 15:51:09 +05:30
22afe7e555 current page update in article api 2023-08-10 15:43:31 +05:30
69723b362f current page update in article api 2023-08-10 15:30:46 +05:30
9e612c7171 Merge pull request #181 from KiwiTechLLC/sprint4
junior points
2023-08-10 12:20:34 +05:30
7a9be0326a junior points 2023-08-10 12:19:08 +05:30
aaa1c55227 Merge pull request #180 from KiwiTechLLC/sprint4
guardian code
2023-08-10 12:07:49 +05:30
656f0da89a guardian code 2023-08-10 12:06:52 +05:30
28e71e132c Merge pull request #178 from KiwiTechLLC/sprint4
Sprint4
2023-08-10 11:56:53 +05:30
b30643299f junior points 2023-08-10 11:56:19 +05:30
b6b70af13f remove guardian code request 2023-08-10 11:02:32 +05:30
22dd7fc10b remove guardian code request 2023-08-10 10:55:33 +05:30
924bc20193 Merge pull request #176 from KiwiTechLLC/sprint4
points
2023-08-09 19:21:50 +05:30
af7582b9e2 points 2023-08-09 19:20:56 +05:30
856d27d803 Merge pull request #175 from KiwiTechLLC/sprint4
points remove from serializer
2023-08-09 18:54:12 +05:30
19f56280e4 points remove from serializer 2023-08-09 18:53:18 +05:30
d3800dbc85 Merge pull request #173 from KiwiTechLLC/sprint4
guardian code update
2023-08-09 18:10:18 +05:30
9373dc4697 Merge pull request #172 from KiwiTechLLC/ZBKADM-71
analytics section api, users counts, new signup count, task report
2023-08-09 17:20:53 +05:30
32eaa6c3f2 guardian code update 2023-08-09 17:18:07 +05:30
11ff8fc700 conflict resolved 2023-08-09 17:03:42 +05:30
9c75cb1615 analytics section api, users counts, new signup count, task report 2023-08-09 16:57:19 +05:30
3f8b0e2eb7 Merge pull request #171 from KiwiTechLLC/sprint4
financial learning section api
2023-08-09 16:44:27 +05:30
69ce6857e8 financial learning section api 2023-08-09 16:36:33 +05:30
3efa31efe4 Merge pull request #169 from KiwiTechLLC/sprint4
Sprint4
2023-08-09 14:39:01 +05:30
275b09d2ea Merge branch 'sprint4' of github.com:KiwiTechLLC/ZODBank-Backend into sprint4 2023-08-09 14:38:09 +05:30
3cb0e3ed8b guardian code add in junior list api 2023-08-09 14:37:38 +05:30
823c5ea4c4 Merge pull request #168 from KiwiTechLLC/ZBKADM-69
otp, verify otp and login bug resolved
2023-08-09 14:21:58 +05:30
08750813ce Merge pull request #167 from KiwiTechLLC/sprint4
Sprint4
2023-08-09 13:54:08 +05:30
75f4f66285 Merge branch 'dev' into sprint4 2023-08-09 13:49:39 +05:30
881bda739b article card api, check answer api 2023-08-09 13:48:02 +05:30
d86f082e58 article card api, check answer api 2023-08-09 13:37:06 +05:30
b12c5071fe Merge pull request #164 from KiwiTechLLC/sprint4
changes in add junior api
2023-08-08 16:37:08 +05:30
f75201b3dd changes in add junior api 2023-08-08 16:36:03 +05:30
45ea7013f8 Merge pull request #162 from KiwiTechLLC/sprint4
junior list api
2023-08-08 16:06:52 +05:30
7d428f5eb5 junior list api 2023-08-08 16:05:56 +05:30
9ff64e64ef Merge pull request #160 from KiwiTechLLC/sprint4
top junior api
2023-08-08 15:04:03 +05:30
4b23394569 top junior api 2023-08-08 15:03:24 +05:30
81893c8841 Merge pull request #159 from KiwiTechLLC/ZBKADM-69
change in admin login
2023-08-08 14:38:43 +05:30
7fca493d0d Merge pull request #157 from KiwiTechLLC/sprint4
junior position changes and decrease api response time
2023-08-08 14:02:27 +05:30
85e4ae8761 junior position changes and decrease api response time 2023-08-08 13:54:04 +05:30
6ebd5ae410 Merge pull request #156 from KiwiTechLLC/sprint4
guardian list api changes
2023-08-08 12:35:43 +05:30
f57b111555 guardian list api changes 2023-08-08 11:48:53 +05:30
6596414675 guardian list api changes 2023-08-08 11:46:27 +05:30
ed7fd3c15d Merge pull request #155 from KiwiTechLLC/ZBKADM-69
notification list modified and mark as read method changed
2023-08-07 20:48:37 +05:30
8cf7148114 Merge pull request #154 from KiwiTechLLC/ZBKADM-69
change method to get real time
2023-08-07 19:19:00 +05:30
b98443479f Merge pull request #153 from KiwiTechLLC/sprint4
junior article points table
2023-08-07 19:12:55 +05:30
f917244265 junior article points table 2023-08-07 19:12:14 +05:30
33 changed files with 999 additions and 121 deletions

View File

@ -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

View File

@ -23,7 +23,8 @@ from guardian.models import Guardian
from account.models import UserDelete
from base.messages import ERROR_CODE
from django.utils import timezone
from base.constants import NUMBER
from junior.models import JuniorPoints
# Define delete
# user account condition,
# Define delete
@ -91,7 +92,9 @@ def junior_account_update(user_tb):
junior_data.is_active = False
junior_data.is_verified = False
junior_data.guardian_code = '{}'
junior_data.guardian_code_status = str(NUMBER['one'])
junior_data.save()
JuniorPoints.objects.filter(junior=junior_data).delete()
def guardian_account_update(user_tb):
"""update guardian account after delete the user account"""

View File

@ -23,7 +23,7 @@ from django.conf import settings
# local imports
from guardian.models import Guardian
from junior.models import Junior
from junior.models import Junior, JuniorPoints
from guardian.utils import upload_image_to_alibaba
from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
from django.contrib.auth.models import User
@ -97,6 +97,8 @@ class GoogleLoginMixin(object):
referral_code=generate_code(ZOD, user_obj.id)
)
serializer = JuniorSerializer(junior_query)
position = Junior.objects.all().count()
JuniorPoints.objects.create(junior=junior_query, position=position)
if str(user_type) == '2':
guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True,
image=profile_picture,signup_method='2',
@ -147,6 +149,8 @@ class SigninWithApple(views.APIView):
junior_code=generate_code(JUN, user.id),
referral_code=generate_code(ZOD, user.id))
serializer = JuniorSerializer(junior_query)
position = Junior.objects.all().count()
JuniorPoints.objects.create(junior=junior_query, position=position)
if str(user_type) == '2':
guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True,
signup_method='3',
@ -245,7 +249,6 @@ class ForgotPasswordAPIView(views.APIView):
class SendPhoneOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
queryset = UserPhoneOtp.objects.all()
serializer_class = UserPhoneOtpSerializer
def create(self, request, *args, **kwargs):
otp = generate_otp()
@ -262,7 +265,6 @@ class SendPhoneOtp(viewsets.ModelViewSet):
class UserPhoneVerification(viewsets.ModelViewSet):
"""Send otp on phone"""
queryset = UserPhoneOtp.objects.all()
serializer_class = UserPhoneOtpSerializer
def list(self, request, *args, **kwargs):
try:
@ -334,10 +336,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)
@ -369,7 +370,6 @@ class AdminLoginViewSet(viewsets.GenericViewSet):
class UserEmailVerification(viewsets.ModelViewSet):
"""User Email verification"""
serializer_class = EmailVerificationSerializer
queryset = UserEmailOtp.objects.all()
def list(self, request, *args, **kwargs):
try:
@ -412,7 +412,6 @@ class UserEmailVerification(viewsets.ModelViewSet):
class ReSendEmailOtp(viewsets.ModelViewSet):
"""Send otp on phone"""
queryset = UserEmailOtp.objects.all()
serializer_class = EmailVerificationSerializer
permission_classes = [IsAuthenticated]
@ -435,7 +434,6 @@ class ReSendEmailOtp(viewsets.ModelViewSet):
class ProfileAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset"""
queryset = User.objects.all()
serializer_class = JuniorProfileSerializer
permission_classes = [IsAuthenticated]
@ -454,7 +452,6 @@ class ProfileAPIViewSet(viewsets.ModelViewSet):
class UploadImageAPIViewSet(viewsets.ModelViewSet):
"""upload task image"""
queryset = DefaultTaskImages.objects.all()
serializer_class = DefaultTaskImagesSerializer
def create(self, request, *args, **kwargs):
"""upload images"""
@ -473,7 +470,6 @@ class UploadImageAPIViewSet(viewsets.ModelViewSet):
class DefaultImageAPIViewSet(viewsets.ModelViewSet):
"""Profile viewset"""
queryset = DefaultTaskImages.objects.all()
serializer_class = DefaultTaskImagesDetailsSerializer
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
@ -504,7 +500,6 @@ class DeleteUserProfileAPIViewSet(viewsets.GenericViewSet):
class UserNotificationAPIViewSet(viewsets.ModelViewSet):
"""notification viewset"""
queryset = UserNotification.objects.all()
serializer_class = UserNotificationSerializer
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
@ -516,7 +511,6 @@ class UserNotificationAPIViewSet(viewsets.ModelViewSet):
class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
"""Update notification viewset"""
queryset = UserNotification.objects.all()
serializer_class = UpdateUserNotificationSerializer
permission_classes = [IsAuthenticated]

View File

@ -70,6 +70,18 @@ SIGNUP_METHODS = (
('2', 'google'),
('3', 'apple')
)
# guardian code status
GUARDIAN_CODE_STATUS = (
('1', 'no guardian code'),
('2', 'exist guardian code'),
('3', 'request for guardian code')
)
# article status
ARTICLE_STATUS = (
('1', 'read'),
('2', 'in_progress'),
('3', 'completed')
)
# relationship
RELATIONSHIP = (
('1', 'parent'),
@ -106,7 +118,7 @@ MAX_ARTICLE_CARD = 6
MIN_ARTICLE_SURVEY = 5
MAX_ARTICLE_SURVEY = 10
# real time url
time_url = "http://worldtimeapi.org/api/timezone/Asia/Riyadh"
# already register
Already_register_user = "duplicate key value violates unique constraint"
ARTICLE_CARD_IMAGE_FOLDER = 'article-card-images'

View File

@ -149,7 +149,18 @@ SUCCESS_CODE = {
"3037": "Profile has been updated successfully.",
"3038": "Status has been changed successfully.",
# notification read
"3039": "Notification read successfully"
"3039": "Notification read successfully",
# start article
"3040": "Start article successfully",
# complete article
"3041": "Article completed successfully",
# submit assessment successfully
"3042": "Assessment completed successfully",
# read article
"3043": "Read article card successfully",
# remove guardian code request
"3044": "Remove guardian code request successfully",
}
"""status code error"""
STATUS_CODE_ERROR = {

Binary file not shown.

View File

@ -23,7 +23,7 @@ from account.models import UserProfile, UserEmailOtp, UserNotification
from account.utils import generate_code
from junior.serializers import JuniorDetailSerializer
from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER, JUN, ZOD, GRD
from base.constants import NUMBER, JUN, ZOD, GRD, Already_register_user
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
from .utils import real_time, convert_timedelta_into_datetime, update_referral_points
# notification's constant
@ -68,8 +68,10 @@ class UserSerializer(serializers.ModelSerializer):
UserNotification.objects.get_or_create(user=user)
if user_type == str(NUMBER['one']):
# create junior profile
Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id),
referral_code=generate_code(ZOD, user.id))
junior = Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id),
referral_code=generate_code(ZOD, user.id))
position = Junior.objects.all().count()
JuniorPoints.objects.create(junior=junior, position=position)
if user_type == str(NUMBER['two']):
# create guardian profile
Guardian.objects.create(user=user, guardian_code=generate_code(GRD, user.id),
@ -82,7 +84,7 @@ class UserSerializer(serializers.ModelSerializer):
otp_verified = False
if otp and otp.is_verified:
otp_verified = True
raise serializers.ValidationError({"details":ERROR_CODE['2021'], "otp_verified":bool(otp_verified),
raise serializers.ValidationError({"details": ERROR_CODE['2021'], "otp_verified":bool(otp_verified),
"code": 400, "status":"failed",
})
@ -353,6 +355,7 @@ class ApproveJuniorSerializer(serializers.ModelSerializer):
instance = self.context['junior']
instance.guardian_code = [self.context['guardian_code']]
instance.guardian_code_approved = True
instance.guardian_code_status = str(NUMBER['two'])
instance.save()
return instance
@ -385,8 +388,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)
@ -403,11 +404,20 @@ class GuardianDetailListSerializer(serializers.ModelSerializer):
email = serializers.SerializerMethodField('get_email')
image = serializers.SerializerMethodField('get_image')
guardian_id = serializers.SerializerMethodField('get_guardian_id')
guardian_code = serializers.SerializerMethodField('get_guardian_code')
gender = serializers.SerializerMethodField('get_gender')
phone = serializers.SerializerMethodField('get_phone')
country_name = serializers.SerializerMethodField('get_country_name')
dob = serializers.SerializerMethodField('get_dob')
guardian_code_status = serializers.SerializerMethodField('get_guardian_code_status')
# code info
class Meta(object):
"""Meta info"""
model = JuniorGuardianRelationship
fields = ['guardian_id', 'first_name', 'last_name', 'email', 'relationship', 'image', 'created_at',
fields = ['guardian_id', 'first_name', 'last_name', 'email', 'relationship', 'image', 'dob',
'guardian_code', 'gender', 'phone', 'country_name', 'created_at', 'guardian_code_status',
'updated_at']
def get_guardian_id(self,obj):
@ -422,9 +432,33 @@ class GuardianDetailListSerializer(serializers.ModelSerializer):
return obj.guardian.user.last_name
def get_email(self,obj):
"""emailof guardian"""
"""email of guardian"""
return obj.guardian.user.email
def get_image(self,obj):
"""first name of guardian"""
"""guardian image"""
return obj.guardian.image
def get_guardian_code(self,obj):
""" guardian code"""
return obj.guardian.guardian_code
def get_gender(self,obj):
""" guardian gender"""
return obj.guardian.gender
def get_phone(self,obj):
"""guardian phone"""
return obj.guardian.phone
def get_country_name(self,obj):
""" guardian country name """
return obj.guardian.country_name
def get_dob(self,obj):
"""guardian dob """
return obj.guardian.dob
def get_guardian_code_status(self,obj):
"""guardian code status"""
return obj.junior.guardian_code_status

View File

@ -11,7 +11,7 @@ import tempfile
# Import date time module's function
from datetime import datetime, time
# import Number constant
from base.constants import NUMBER, time_url
from base.constants import NUMBER
# Import Junior's model
from junior.models import Junior, JuniorPoints
# Import guardian's model

View File

@ -10,8 +10,8 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework import viewsets, status
from rest_framework.pagination import PageNumberPagination
from django.contrib.auth.models import User
from rest_framework.filters import SearchFilter
from rest_framework.filters import SearchFilter
from django.utils import timezone
# Import guardian's model,
@ -36,7 +36,7 @@ from account.models import UserEmailOtp, UserNotification
from .tasks import generate_otp
from account.utils import custom_response, custom_error_response, OTP_EXPIRY, send_otp_email
from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER
from base.constants import NUMBER, GUARDIAN_CODE_STATUS
from .utils import upload_image_to_alibaba
from notifications.constants import REGISTRATION, TASK_CREATED, LEADERBOARD_RANKING
from notifications.utils import send_notification
@ -59,33 +59,29 @@ class SignupViewset(viewsets.ModelViewSet):
serializer_class = UserSerializer
def create(self, request, *args, **kwargs):
"""Create user profile"""
try:
if request.data['user_type'] in [str(NUMBER['one']), str(NUMBER['two'])]:
serializer = UserSerializer(context=request.data['user_type'], data=request.data)
if serializer.is_valid():
user = serializer.save()
"""Generate otp"""
otp = generate_otp()
# expire otp after 1 day
expiry = OTP_EXPIRY
# create user email otp object
UserEmailOtp.objects.create(email=request.data['email'], otp=otp,
user_type=str(request.data['user_type']), expired_at=expiry)
"""Send email to the register user"""
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'],
response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
else:
return custom_error_response(ERROR_CODE['2028'], response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
if request.data['user_type'] in [str(NUMBER['one']), str(NUMBER['two'])]:
serializer = UserSerializer(context=request.data['user_type'], data=request.data)
if serializer.is_valid():
user = serializer.save()
"""Generate otp"""
otp = generate_otp()
# expire otp after 1 day
expiry = OTP_EXPIRY
# create user email otp object
UserEmailOtp.objects.create(email=request.data['email'], otp=otp,
user_type=str(request.data['user_type']), expired_at=expiry)
"""Send email to the register user"""
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'],
response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
else:
return custom_error_response(ERROR_CODE['2028'], response_status=status.HTTP_400_BAD_REQUEST)
class UpdateGuardianProfile(viewsets.ViewSet):
"""Update guardian profile"""
queryset = Guardian.objects.all()
serializer_class = CreateGuardianSerializer
permission_classes = [IsAuthenticated]
@ -119,7 +115,6 @@ class UpdateGuardianProfile(viewsets.ViewSet):
class AllTaskListAPIView(viewsets.ModelViewSet):
"""Update guardian profile"""
serializer_class = TaskDetailsSerializer
queryset = JuniorTask.objects.all()
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
@ -261,9 +256,9 @@ class SearchTaskListAPIView(viewsets.ModelViewSet):
class TopJuniorListAPIView(viewsets.ModelViewSet):
"""Top juniors list"""
queryset = JuniorPoints.objects.all()
serializer_class = TopJuniorSerializer
permission_classes = [IsAuthenticated]
queryset = JuniorPoints.objects.all()
def get_serializer_context(self):
# context list
@ -275,14 +270,12 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
"""Fetch junior list of those who complete their tasks"""
try:
junior_total_points = self.get_queryset().order_by('-total_points')
# Update the position field for each JuniorPoints object
for index, junior in enumerate(junior_total_points):
junior.position = index + 1
send_notification.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {})
junior.save()
serializer = self.get_serializer(junior_total_points, 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)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
@ -316,6 +309,7 @@ class ApproveJuniorAPIView(viewsets.ViewSet):
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
else:
queryset[1].guardian_code = None
queryset[1].guardian_code_status = str(NUMBER['one'])
queryset[1].save()
return custom_response(SUCCESS_CODE['3024'], response_status=status.HTTP_200_OK)
except Exception as e:
@ -379,6 +373,6 @@ class GuardianListAPIView(viewsets.ModelViewSet):
# use GuardianDetailListSerializer serializer
serializer = GuardianDetailListSerializer(guardian_data, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(ERROR_CODE['2068'], response_status=status.HTTP_200_OK)
return custom_response({"status": GUARDIAN_CODE_STATUS[1][0]}, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)

View File

@ -2,8 +2,26 @@
"""Third party Django app"""
from django.contrib import admin
"""Import Django app"""
from .models import Junior, JuniorPoints, JuniorGuardianRelationship
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"""
@ -27,3 +45,7 @@ class JuniorGuardianRelationshipAdmin(admin.ModelAdmin):
"""Junior Admin"""
list_display = ['guardian', 'junior', 'relationship']
@admin.register(JuniorArticlePoints)
class JuniorArticlePointsAdmin(admin.ModelAdmin):
"""Junior Admin"""
list_display = ['junior', 'article', 'question', 'submitted_answer', 'is_answer_correct']

View File

@ -0,0 +1,30 @@
# Generated by Django 4.2.2 on 2023-08-07 13:29
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('web_admin', '0004_alter_surveyoption_survey'),
('junior', '0018_remove_junior_relationship_and_more'),
]
operations = [
migrations.CreateModel(
name='JuniorArticlePoints',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('earn_points', models.IntegerField(blank=True, default=5, null=True)),
('is_attempt', models.BooleanField(default=False)),
('is_answer_correct', 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', to='web_admin.article')),
('junior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='juniors_details', to='junior.junior', verbose_name='Junior')),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='questions', to='web_admin.articlesurvey')),
('submitted_answer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submitted_answer', to='web_admin.surveyoption')),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-08-08 05:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('junior', '0019_juniorarticlepoints'),
]
operations = [
migrations.AddField(
model_name='junior',
name='guardian_code_status',
field=models.CharField(blank=True, choices=[('1', 'no guardian code'), ('2', 'exist guardian code'), ('3', 'request for guardian code')], default='1', max_length=31, null=True),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 4.2.2 on 2023-08-08 09:45
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('web_admin', '0004_alter_surveyoption_survey'),
('junior', '0020_junior_guardian_code_status'),
]
operations = [
migrations.AlterField(
model_name='juniorarticlepoints',
name='submitted_answer',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='submitted_answer', to='web_admin.surveyoption'),
),
]

View File

@ -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')),
],
),
]

View File

@ -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')),
],
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.2 on 2023-08-10 08:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('junior', '0023_juniorarticlecard'),
]
operations = [
migrations.AddField(
model_name='juniorarticle',
name='current_card_page',
field=models.IntegerField(blank=True, default=0, null=True),
),
migrations.AddField(
model_name='juniorarticle',
name='current_que_page',
field=models.IntegerField(blank=True, default=0, null=True),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2.2 on 2023-08-10 14:46
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('junior', '0024_juniorarticle_current_card_page_and_more'),
]
operations = [
migrations.AlterField(
model_name='juniorarticle',
name='junior',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='juniors_article', to='junior.junior', verbose_name='Junior'),
),
]

View File

@ -6,10 +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
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, ArticleCard
"""Define User model"""
User = get_user_model()
# Create your models here.
@ -73,6 +74,9 @@ class Junior(models.Model):
is_verified = models.BooleanField(default=False)
"""guardian code is approved or not"""
guardian_code_approved = models.BooleanField(default=False)
# guardian code status"""
guardian_code_status = models.CharField(max_length=31, choices=GUARDIAN_CODE_STATUS, default='1',
null=True, blank=True)
# Profile created and updated time"""
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@ -137,3 +141,62 @@ class JuniorGuardianRelationship(models.Model):
return f'{self.guardian.user}'
class JuniorArticlePoints(models.Model):
"""
Survey Options model
"""
# associated junior with the task
junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='juniors_details', verbose_name='Junior')
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='junior_articles')
question = models.ForeignKey(ArticleSurvey, on_delete=models.CASCADE, related_name='questions')
submitted_answer = models.ForeignKey(SurveyOption, on_delete=models.SET_NULL, null=True,
related_name='submitted_answer')
# earn points"""
earn_points = models.IntegerField(blank=True, null=True, default=5)
is_attempt = models.BooleanField(default=False)
is_answer_correct = 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.question}'
class JuniorArticle(models.Model):
"""
Survey Options model
"""
# associated junior with the task
junior = models.ForeignKey(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')
current_card_page = models.IntegerField(blank=True, null=True, default=0)
current_que_page = models.IntegerField(blank=True, null=True, default=0)
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}'

View File

@ -12,10 +12,11 @@ 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
from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD, EXPIRED,
GUARDIAN_CODE_STATUS)
from guardian.models import Guardian, JuniorTask
from account.models import UserEmailOtp, UserNotification
from junior.utils import junior_notification_email, junior_approval_mail
@ -95,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)
@ -142,7 +146,7 @@ class JuniorDetailSerializer(serializers.ModelSerializer):
"""Meta info"""
model = Junior
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
'guardian_code', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at',
'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at',
'image', 'updated_at']
class JuniorDetailListSerializer(serializers.ModelSerializer):
@ -178,10 +182,11 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
data = JuniorPoints.objects.filter(junior=obj).last()
if data:
return data.position
return 99999
def get_points(self, obj):
data = sum(JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).values_list('points', flat=True))
return data
data = JuniorPoints.objects.filter(junior=obj).last()
if data:
return data.total_points
return NUMBER['zero']
def get_in_progress_task(self, obj):
data = JuniorTask.objects.filter(junior=obj, task_status=IN_PROGRESS).count()
@ -206,10 +211,10 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
class Meta(object):
"""Meta info"""
model = Junior
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'country_name', 'phone', 'gender', 'dob',
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
'updated_at', 'assigned_task','points', 'pending_task', 'in_progress_task', 'completed_task',
'requested_task', 'rejected_task', 'position', 'is_invited']
'requested_task', 'rejected_task', 'position', 'is_invited', 'guardian_code_status']
class JuniorProfileSerializer(serializers.ModelSerializer):
"""junior serializer"""
@ -256,11 +261,10 @@ class JuniorProfileSerializer(serializers.ModelSerializer):
class AddJuniorSerializer(serializers.ModelSerializer):
"""Add junior serializer"""
class Meta(object):
"""Meta info"""
model = Junior
fields = ['id', 'gender','dob', 'is_invited']
fields = ['id', 'gender', 'dob', 'is_invited']
def create(self, validated_data):
@ -269,6 +273,7 @@ class AddJuniorSerializer(serializers.ModelSerializer):
email = self.context['email']
guardian = self.context['user']
relationship = self.context['relationship']
profile_image = self.context['image']
full_name = self.context['first_name'] + ' ' + self.context['last_name']
guardian_data = Guardian.objects.filter(user__username=guardian).last()
user_data = User.objects.create(username=email, email=email,
@ -278,14 +283,18 @@ class AddJuniorSerializer(serializers.ModelSerializer):
user_data.set_password(password)
user_data.save()
junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'),
image=profile_image,
dob=validated_data.get('dob'), is_invited=True,
guardian_code=[guardian_data.guardian_code],
junior_code=generate_code(JUN, user_data.id),
referral_code=generate_code(ZOD, user_data.id),
referral_code_used=guardian_data.referral_code,
is_password_set=False, is_verified=True)
is_password_set=False, is_verified=True,
guardian_code_status=GUARDIAN_CODE_STATUS[1][0])
JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data,
relationship=relationship)
total_junior = Junior.objects.all().count()
JuniorPoints.objects.create(junior=junior_data, position=total_junior)
"""Generate otp"""
otp_value = generate_otp()
expiry_time = timezone.now() + timezone.timedelta(days=1)
@ -311,6 +320,7 @@ class RemoveJuniorSerializer(serializers.ModelSerializer):
if instance:
instance.is_invited = False
instance.guardian_code = '{}'
instance.guardian_code_status = str(NUMBER['1'])
instance.save()
return instance
@ -403,13 +413,15 @@ class AddGuardianSerializer(serializers.ModelSerializer):
relationship = self.context['relationship']
full_name = self.context['first_name'] + ' ' + self.context['last_name']
junior_data = Junior.objects.filter(auth__username=junior).last()
junior_data.guardian_code_status = GUARDIAN_CODE_STATUS[2][0]
junior_data.save()
instance = User.objects.filter(username=email).last()
if instance:
guardian_data = Guardian.objects.filter(user=instance).update(is_invited=True,
referral_code=generate_code(ZOD,
referral_code=generate_code(ZOD,
instance.id),
referral_code_used=junior_data.referral_code,
is_verified=True)
is_verified=True)
UserNotification.objects.get_or_create(user=instance)
return guardian_data
else:
@ -481,3 +493,16 @@ class ReAssignTaskSerializer(serializers.ModelSerializer):
instance.requested_on = None
instance.save()
return instance
class RemoveGuardianCodeSerializer(serializers.ModelSerializer):
"""User task Serializer"""
class Meta(object):
"""Meta class"""
model = Junior
fields = ('id', )
def update(self, instance, validated_data):
instance.guardian_code_status = str(NUMBER['one'])
instance.save()
return instance

View File

@ -4,7 +4,9 @@ from django.urls import path, include
from .views import (UpdateJuniorProfile, ValidateGuardianCode, JuniorListAPIView, AddJuniorAPIView,
InvitedJuniorAPIView, FilterJuniorAPIView, RemoveJuniorAPIView, JuniorTaskListAPIView,
CompleteJuniorTaskAPIView, JuniorPointsListAPIView, ValidateReferralCode,
InviteGuardianAPIView, StartTaskAPIView, ReAssignJuniorTaskAPIView)
InviteGuardianAPIView, StartTaskAPIView, ReAssignJuniorTaskAPIView, StartArticleAPIView,
StartAssessmentAPIView, CheckAnswerAPIView, CompleteArticleAPIView, ReadArticleCardAPIView,
CreateArticleCardAPIView, RemoveGuardianCodeAPIView)
"""Third party import"""
from rest_framework import routers
@ -41,6 +43,14 @@ router.register('junior-points', JuniorPointsListAPIView, basename='junior-point
router.register('validate-referral-code', ValidateReferralCode, basename='validate-referral-code')
# invite guardian API"""
router.register('invite-guardian', InviteGuardianAPIView, basename='invite-guardian')
# start article"""
router.register('start-article', StartArticleAPIView, basename='start-article')
# start assessment api"""
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)),
@ -48,4 +58,7 @@ 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()),
path('api/v1/remove-guardian-code-request/', RemoveGuardianCodeAPIView.as_view()),
]

View File

@ -4,6 +4,7 @@ from django.conf import settings
"""Third party Django app"""
from templated_email import send_templated_mail
from .models import JuniorPoints
from base.constants import NUMBER
from django.db.models import F
# junior notification
# email for sending email
@ -50,11 +51,11 @@ def junior_approval_mail(guardian, full_name):
def update_positions_based_on_points():
"""Update position of the junior"""
# First, retrieve all the JuniorPoints instances ordered by total_points in descending order.
juniors_points = JuniorPoints.objects.order_by('-total_points')
juniors_points = JuniorPoints.objects.order_by('-total_points', 'created_at')
# Now, iterate through the queryset and update the position field based on the order.
position = 1
position = NUMBER['one']
for junior_point in juniors_points:
junior_point.position = position
junior_point.save()
position += 1
position += NUMBER['one']

View File

@ -6,6 +6,7 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.pagination import PageNumberPagination
from django.contrib.auth.models import User
from rest_framework.filters import SearchFilter
from django.db.models import F
import datetime
import requests
@ -27,20 +28,25 @@ import requests
# Import upload_image_to_alibaba
# Import custom_response, custom_error_response
# Import constants
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,\
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,
RemoveGuardianCodeSerializer)
from guardian.models import Guardian, JuniorTask
from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer
from base.messages import ERROR_CODE, SUCCESS_CODE
from base.constants import NUMBER
from base.constants import NUMBER, ARTICLE_STATUS
from account.utils import custom_response, custom_error_response
from guardian.utils import upload_image_to_alibaba
from .utils import update_positions_based_on_points
from notifications.utils import send_notification
from notifications.constants import REMOVE_JUNIOR
from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer,
StartAssessmentSerializer)
""" Define APIs """
# Define validate guardian code API,
# update junior profile,
@ -59,7 +65,6 @@ from notifications.constants import REMOVE_JUNIOR
# Create your views here.
class UpdateJuniorProfile(viewsets.ViewSet):
"""Update junior profile"""
queryset = Junior.objects.all()
serializer_class = CreateJuniorSerializer
permission_classes = [IsAuthenticated]
@ -93,7 +98,6 @@ class UpdateJuniorProfile(viewsets.ViewSet):
class ValidateGuardianCode(viewsets.ViewSet):
"""Check guardian code exist or not"""
queryset = Guardian.objects.all()
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
@ -151,8 +155,19 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
""" junior list"""
try:
info_data = {'user': request.user, 'relationship': str(request.data['relationship']), 'email': request.data['email'], 'first_name': request.data['first_name'],
'last_name': request.data['last_name']}
info_data = {'user': request.user, 'relationship': str(request.data['relationship']),
'email': request.data['email'], 'first_name': request.data['first_name'],
'last_name': request.data['last_name'], 'image':None}
profile_image = request.data.get('image')
if profile_image:
# check image size
if profile_image.size == NUMBER['zero']:
return custom_error_response(ERROR_CODE['2035'], response_status=status.HTTP_400_BAD_REQUEST)
# convert into file
filename = f"images/{profile_image.name}"
# upload image on ali baba
image_url = upload_image_to_alibaba(profile_image, filename)
info_data.update({"image": image_url})
if user := User.objects.filter(username=request.data['email']).first():
self.associate_guardian(user)
return custom_response(SUCCESS_CODE['3021'], response_status=status.HTTP_200_OK)
@ -162,7 +177,7 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3021'], serializer.data, response_status=status.HTTP_200_OK)
return custom_error_response(serializer.error, response_status=status.HTTP_400_BAD_REQUEST)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
@ -170,6 +185,7 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
junior = Junior.objects.filter(auth=user).first()
guardian = Guardian.objects.filter(user=self.request.user).first()
junior.guardian_code = [guardian.guardian_code]
junior.guardian_code_status = str(NUMBER['two'])
junior.save()
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian, junior=junior,
relationship=str(self.request.data['relationship']))
@ -180,7 +196,6 @@ class InvitedJuniorAPIView(viewsets.ModelViewSet):
"""Junior list of assosicated guardian"""
serializer_class = JuniorDetailListSerializer
queryset = Junior.objects.all()
permission_classes = [IsAuthenticated]
pagination_class = PageNumberPagination
http_method_names = ('get',)
@ -210,7 +225,6 @@ class FilterJuniorAPIView(viewsets.ModelViewSet):
serializer_class = JuniorDetailListSerializer
permission_classes = [IsAuthenticated]
pagination_class = PageNumberPagination
queryset = Junior.objects.all()
http_method_names = ('get',)
def get_queryset(self):
@ -247,7 +261,8 @@ class RemoveJuniorAPIView(views.APIView):
junior_id = self.request.GET.get('id')
guardian = Guardian.objects.filter(user__email=self.request.user).last()
# fetch junior query
junior_queryset = Junior.objects.filter(id=junior_id, guardian_code__icontains=str(guardian.guardian_code)).last()
junior_queryset = Junior.objects.filter(id=junior_id,
guardian_code__icontains=str(guardian.guardian_code)).last()
if junior_queryset:
# use RemoveJuniorSerializer serializer
serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True)
@ -268,7 +283,6 @@ class JuniorTaskListAPIView(viewsets.ModelViewSet):
serializer_class = TaskDetailsjuniorSerializer
permission_classes = [IsAuthenticated]
pagination_class = PageNumberPagination
queryset = JuniorTask.objects.all()
http_method_names = ('get',)
def list(self, request, *args, **kwargs):
@ -343,16 +357,12 @@ class JuniorPointsListAPIView(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
http_method_names = ('get',)
def get_queryset(self):
"""get queryset"""
return JuniorTask.objects.filter(junior__auth__email=self.request.user).last()
def list(self, request, *args, **kwargs):
"""profile view"""
try:
queryset = self.get_queryset()
# update position of junior
update_positions_based_on_points()
queryset = JuniorPoints.objects.filter(junior__auth__email=self.request.user).last()
# update position of junior
serializer = JuniorPointsSerializer(queryset)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
except Exception as e:
@ -458,3 +468,184 @@ class ReAssignJuniorTaskAPIView(views.APIView):
return custom_error_response(ERROR_CODE['2066'], response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class StartArticleAPIView(viewsets.ModelViewSet):
"""Start article"""
permission_classes = [IsAuthenticated]
http_method_names = ('post',)
def create(self, request, *args, **kwargs):
""" junior list"""
try:
junior_instance = Junior.objects.filter(auth=self.request.user).last()
article_id = request.data.get('article_id')
article_data = Article.objects.filter(id=article_id).last()
if not JuniorArticle.objects.filter(junior=junior_instance, article=article_data).last():
JuniorArticle.objects.create(junior=junior_instance, article=article_data, status=str(NUMBER['two']),
current_card_page=NUMBER['zero'], current_que_page=NUMBER['zero'])
if article_data:
question_query = ArticleSurvey.objects.filter(article=article_id)
for question in question_query:
if not JuniorArticlePoints.objects.filter(junior=junior_instance,
article=article_data,
question=question):
JuniorArticlePoints.objects.create(junior=junior_instance,
article=article_data,
question=question)
return custom_response(SUCCESS_CODE['3040'], response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class StartAssessmentAPIView(viewsets.ModelViewSet):
"""Junior Points viewset"""
serializer_class = StartAssessmentSerializer
permission_classes = [IsAuthenticated]
http_method_names = ('get',)
def get_queryset(self):
article_id = self.request.GET.get('article_id')
# if referral_code:
article = Article.objects.filter(id=article_id, is_deleted=False).prefetch_related(
'article_cards', 'article_survey', 'article_survey__options'
).order_by('-created_at')
return article
def list(self, request, *args, **kwargs):
"""profile view"""
try:
queryset = self.get_queryset()
paginator = self.pagination_class()
paginated_queryset = paginator.paginate_queryset(queryset, request)
serializer = self.serializer_class(paginated_queryset, context={"user":request.user}, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class CheckAnswerAPIView(viewsets.ModelViewSet):
"""Junior Points viewset"""
permission_classes = [IsAuthenticated]
http_method_names = ('get',)
def get_queryset(self):
question_id = self.request.GET.get('question_id')
article = ArticleSurvey.objects.filter(id=question_id).last()
return article
def list(self, request, *args, **kwargs):
"""profile view"""
try:
answer_id = self.request.GET.get('answer_id')
current_page = self.request.GET.get('current_page')
queryset = self.get_queryset()
submit_ans = SurveyOption.objects.filter(id=answer_id, is_answer=True).last()
junior_article_points = JuniorArticlePoints.objects.filter(junior__auth=self.request.user,
question=queryset)
if submit_ans:
junior_article_points.update(submitted_answer=submit_ans, is_attempt=True, is_answer_correct=True)
JuniorPoints.objects.filter(junior__auth=self.request.user).update(total_points=
F('total_points') + queryset.points)
else:
junior_article_points.update(submitted_answer=submit_ans, is_attempt=True, earn_points=0,
is_answer_correct=False)
JuniorArticle.objects.filter(junior__auth=self.request.user,
article=queryset.article).update(
current_que_page=int(current_page) + NUMBER['one'])
return custom_response(None, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class CompleteArticleAPIView(views.APIView):
"""Remove junior API"""
permission_classes = [IsAuthenticated]
http_method_names = ('put', 'get',)
def put(self, request, format=None):
try:
article_id = self.request.data.get('article_id')
JuniorArticle.objects.filter(junior__auth=request.user, article__id=article_id).update(
is_completed=True, status=str(NUMBER['three'])
)
return custom_response(SUCCESS_CODE['3041'], response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
def get(self, request, *args, **kwargs):
""" junior list"""
try:
article_id = self.request.GET.get('article_id')
total_earn_points = JuniorArticlePoints.objects.filter(junior__auth=request.user,
article__id=article_id,
is_answer_correct=True).aggregate(
total_earn_points=Sum('earn_points'))['total_earn_points']
data = {"total_earn_points":total_earn_points}
return custom_response(SUCCESS_CODE['3042'], data, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class ReadArticleCardAPIView(views.APIView):
"""Remove junior API"""
permission_classes = [IsAuthenticated]
http_method_names = ('put',)
def put(self, request, *args, **kwargs):
""" junior list"""
try:
junior_instance = Junior.objects.filter(auth=self.request.user).last()
article = self.request.data.get('article_id')
article_card = self.request.data.get('article_card')
current_page = self.request.data.get('current_page')
JuniorArticleCard.objects.filter(junior=junior_instance,
article__id=article,
article_card__id=article_card).update(is_read=True)
JuniorArticle.objects.filter(junior=junior_instance,
article__id=article).update(current_card_page=int(current_page)+NUMBER['one'])
return custom_response(SUCCESS_CODE['3043'], response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class CreateArticleCardAPIView(viewsets.ModelViewSet):
"""Start article"""
permission_classes = [IsAuthenticated]
http_method_names = ('post',)
def create(self, request, *args, **kwargs):
""" junior list"""
try:
junior_instance = Junior.objects.filter(auth=self.request.user).last()
article_id = request.data.get('article_id')
article_data = Article.objects.filter(id=article_id).last()
if article_data:
article_cards = ArticleCard.objects.filter(article=article_id)
for article_card in article_cards:
if not JuniorArticleCard.objects.filter(junior=junior_instance,
article=article_data,
article_card=article_card):
JuniorArticleCard.objects.create(junior=junior_instance,
article=article_data,
article_card=article_card)
return custom_response(None, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
class RemoveGuardianCodeAPIView(views.APIView):
"""Update junior task API"""
serializer_class = RemoveGuardianCodeSerializer
permission_classes = [IsAuthenticated]
def put(self, request, format=None):
try:
junior_queryset = Junior.objects.filter(auth=self.request.user).last()
if junior_queryset:
# use RemoveGuardianCodeSerializer serializer
serializer = RemoveGuardianCodeSerializer(junior_queryset, data=request.data, partial=True)
if serializer.is_valid():
# save serializer
serializer.save()
return custom_response(SUCCESS_CODE['3044'], response_status=status.HTTP_200_OK)
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
else:
# task in another state
return custom_error_response(ERROR_CODE['2047'], response_status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)

View File

@ -49,7 +49,7 @@ class ArticleSurvey(models.Model):
def __str__(self):
"""Return title"""
return f'{self.id} | {self.article}'
return f'{self.id} | {self.question}'
class SurveyOption(models.Model):
@ -64,7 +64,7 @@ class SurveyOption(models.Model):
def __str__(self):
"""Return title"""
return f'{self.id} | {self.survey}'
return f'{self.id} | {self.option}'
class DefaultArticleCardImage(models.Model):

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

@ -0,0 +1,53 @@
"""
web_admin analytics serializer file
"""
from rest_framework import serializers
from junior.models import JuniorPoints, Junior
from web_admin.serializers.user_management_serializer import JuniorSerializer
class JuniorLeaderboardSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField()
first_name = serializers.SerializerMethodField()
last_name = serializers.SerializerMethodField()
class Meta:
"""
meta class
"""
model = Junior
fields = ('id', 'name', 'first_name', 'last_name', 'is_active', 'image')
@staticmethod
def get_name(obj):
"""
:param obj: junior object
:return: full name
"""
return f"{obj.auth.first_name} {obj.auth.last_name}" if obj.auth.last_name else obj.auth.first_name
@staticmethod
def get_first_name(obj):
"""
:param obj: junior object
:return: first name
"""
return obj.auth.first_name
@staticmethod
def get_last_name(obj):
"""
:param obj: junior object
:return: last name
"""
return obj.auth.last_name
class LeaderboardSerializer(serializers.ModelSerializer):
junior = JuniorLeaderboardSerializer()
rank = serializers.IntegerField()
class Meta:
model = JuniorPoints
fields = ('total_points', 'rank', 'junior')

View File

@ -12,7 +12,7 @@ from base.messages import ERROR_CODE
from guardian.utils import upload_image_to_alibaba
from web_admin.models import Article, ArticleCard, SurveyOption, ArticleSurvey, DefaultArticleCardImage
from web_admin.utils import pop_id, get_image_url
from junior.models import JuniorArticlePoints, JuniorArticle
USER = get_user_model()
@ -220,16 +220,114 @@ class ArticleListSerializer(serializers.ModelSerializer):
serializer for article API
"""
article_cards = ArticleCardSerializer(many=True)
article_survey = ArticleSurveySerializer(many=True)
total_points = serializers.SerializerMethodField('get_total_points')
is_completed = serializers.SerializerMethodField('get_is_completed')
class Meta:
"""
meta class
"""
model = Article
fields = ('id', 'title', 'description', 'article_cards', 'total_points')
fields = ('id', 'title', 'description', 'article_cards', 'article_survey', 'total_points', 'is_completed')
def get_total_points(self, obj):
"""total points of article"""
total_question = ArticleSurvey.objects.filter(article=obj).count()
return total_question * 5
return total_question * NUMBER['five']
def get_is_completed(self, obj):
"""complete all question"""
junior_article = JuniorArticle.objects.filter(article=obj).last()
if junior_article:
junior_article.is_completed
return False
class ArticleQuestionSerializer(serializers.ModelSerializer):
"""
article survey serializer
"""
id = serializers.IntegerField(required=False)
options = SurveyOptionSerializer(many=True)
is_attempt = serializers.SerializerMethodField('get_is_attempt')
correct_answer = serializers.SerializerMethodField('get_correct_answer')
attempted_answer = serializers.SerializerMethodField('get_attempted_answer')
def get_is_attempt(self, obj):
"""attempt question or not"""
context_data = self.context.get('user')
junior_article_obj = JuniorArticlePoints.objects.filter(junior__auth=context_data, question=obj).last()
if junior_article_obj:
return junior_article_obj.is_attempt
return False
def get_correct_answer(self, obj):
"""attempt question or not"""
ans_obj = SurveyOption.objects.filter(survey=obj, is_answer=True).last()
if ans_obj:
return ans_obj.id
return str("None")
def get_attempted_answer(self, obj):
"""attempt question or not"""
context_data = self.context.get('user')
junior_article_obj = JuniorArticlePoints.objects.filter(junior__auth=context_data,
question=obj, is_answer_correct=True).last()
if junior_article_obj:
return junior_article_obj.submitted_answer.id
return None
class Meta:
"""
meta class
"""
model = ArticleSurvey
fields = ('id', 'question', 'options', 'points', 'is_attempt', 'correct_answer', 'attempted_answer')
class StartAssessmentSerializer(serializers.ModelSerializer):
"""
serializer for article API
"""
article_survey = ArticleQuestionSerializer(many=True)
current_page = serializers.SerializerMethodField('get_current_page')
def get_current_page(self, obj):
"""current page"""
context_data = self.context.get('user')
data = JuniorArticle.objects.filter(junior__auth=context_data, article=obj).last()
if data:
return data.current_que_page
return NUMBER['zero']
class Meta:
"""
meta class
"""
model = Article
fields = ('article_survey', 'current_page')
class ArticleCardlistSerializer(serializers.ModelSerializer):
"""
Article Card serializer
"""
id = serializers.IntegerField(required=False)
image_name = serializers.CharField(required=False)
image_url = serializers.CharField(required=False)
current_page = serializers.SerializerMethodField('get_current_page')
def get_current_page(self, obj):
"""current page"""
context_data = self.context.get('user')
data = JuniorArticle.objects.filter(junior__auth=context_data, article=obj.article).last()
if data:
return data.current_card_page
return NUMBER['zero']
class Meta:
"""
meta class
"""
model = ArticleCard
fields = ('id', 'title', 'description', 'image_name', 'image_url', 'current_page')

View File

@ -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

View File

@ -6,7 +6,9 @@ from django.urls import path, include
from rest_framework import routers
# local imports
from web_admin.views.article import ArticleViewSet, DefaultArticleCardImagesViewSet, ArticleListViewSet
from web_admin.views.analytics import AnalyticsViewSet
from web_admin.views.article import (ArticleViewSet, DefaultArticleCardImagesViewSet, ArticleListViewSet,
ArticleCardListViewSet)
from web_admin.views.auth import ForgotAndResetPasswordViewSet
from web_admin.views.user_management import UserManagementViewSet
@ -16,7 +18,11 @@ router = routers.SimpleRouter()
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('analytics', AnalyticsViewSet, basename='user-analytics')
router.register('article-list', ArticleListViewSet, basename='article-list')
router.register('article-card-list', ArticleCardListViewSet, basename='article-card-list')
# forgot and reset password api for admin
router.register('admin', ForgotAndResetPasswordViewSet, basename='admin')

View File

@ -29,7 +29,7 @@ def get_image_url(data):
return data['image_url']
elif 'image_url' in data and type(data['image_url']) == str and data['image_url'].startswith('data:image'):
base64_image = base64.b64decode(data.get('image_url').split(',')[1])
image_name = f"{data['title']} | {data.pop('image_name')}" if 'image_name' in data else data['title']
image_name = f"{data['title']} {data.pop('image_name')}" if 'image_name' in data else data['title']
filename = f"{ARTICLE_CARD_IMAGE_FOLDER}/{image_name}"
# upload image on ali baba
image_url = upload_image_to_alibaba(base64_image, filename)

View File

@ -0,0 +1,137 @@
"""
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, OuterRef, Subquery, Sum
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
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()
class AnalyticsViewSet(GenericViewSet):
"""
analytics api view
"""
serializer_class = None
permission_classes = [IsAuthenticated, AdminPermission]
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):
"""
api method to get new signups
: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()
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):
"""
api method to get assign tasks
: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')
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)
@action(methods=['get'], url_name='junior-leaderboard', url_path='junior-leaderboard', detail=False,
serializer_class=LeaderboardSerializer)
def junior_leaderboard(self, request):
"""
:param request:
:return:
"""
# queryset = JuniorPoints.objects.all().order_by('-total_points', 'junior__created_at')
queryset = JuniorPoints.objects.prefetch_related('junior', 'junior__auth').annotate(rank=Window(
expression=Rank(),
order_by=[F('total_points').desc(), 'junior__created_at']
)).order_by('-total_points', 'junior__created_at')
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

@ -4,7 +4,7 @@ web_admin views file
# django imports
from rest_framework.viewsets import GenericViewSet, mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework import status
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated, AllowAny
from django.contrib.auth import get_user_model
@ -16,7 +16,8 @@ from base.messages import SUCCESS_CODE, ERROR_CODE
from web_admin.models import Article, ArticleCard, ArticleSurvey, DefaultArticleCardImage
from web_admin.permission import AdminPermission
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleCardSerializer,
DefaultArticleCardImageSerializer, ArticleListSerializer)
DefaultArticleCardImageSerializer, ArticleListSerializer,
ArticleCardlistSerializer)
USER = get_user_model()
@ -224,4 +225,24 @@ class ArticleListViewSet(GenericViewSet, mixins.ListModelMixin):
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, count=count)
return custom_response(None, data=serializer.data)
class ArticleCardListViewSet(viewsets.ModelViewSet):
"""Junior Points viewset"""
serializer_class = ArticleCardlistSerializer
permission_classes = [IsAuthenticated]
http_method_names = ('get',)
def get_queryset(self):
"""get queryset"""
return ArticleCard.objects.filter(article=self.request.GET.get('article_id'))
def list(self, request, *args, **kwargs):
"""profile view"""
try:
queryset = self.get_queryset()
# article card list
serializer = ArticleCardlistSerializer(queryset, context={"user": self.request.user}, many=True)
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
except Exception as e:
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)

View File

@ -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)

View File

@ -177,6 +177,31 @@ AUTH_PASSWORD_VALIDATORS = [
},
]
LOGGING = {
"version": 1,
"filters": {
"require_debug_true": {
"()": "django.utils.log.RequireDebugTrue"
}
},
"handlers": {
"console": {
"level": "DEBUG",
"filters": [
"require_debug_true"
],
"class": "logging.StreamHandler"
}
},
"loggers": {
"django.db.backends": {
"level": "DEBUG",
"handlers": [
"console"
]
}
}
}
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/