mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2026-10-23 10:47:56 +00:00
Compare commits
132
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04ed9c668c | ||
|
|
36427b50c1 | ||
|
|
5da07002e0 | ||
|
|
3017b0ece0 | ||
|
|
e73113fcca | ||
|
|
c278670c39 | ||
|
|
60af098e1e | ||
|
|
d29a60558f | ||
|
|
451c3bdae7 | ||
|
|
7c809776b6 | ||
|
|
e46d649fdc | ||
|
|
adb827f5a0 | ||
|
|
a02dfd4e31 | ||
|
|
d3b0be953e | ||
|
|
11b9f00285 | ||
|
|
08dc9f8538 | ||
|
|
6373d1e02c | ||
|
|
a1d959299a | ||
|
|
070637bf1d | ||
|
|
fd9a4902ae | ||
|
|
082f93ff9d | ||
|
|
25eaee31a4 | ||
|
|
d5c30f2029 | ||
|
|
cae28e0b54 | ||
|
|
54200dba52 | ||
|
|
846a9d42d4 | ||
|
|
69c19cf097 | ||
|
|
18cb885410 | ||
|
|
4d7209df19 | ||
|
|
94c76b7f2e | ||
|
|
af8ea39200 | ||
|
|
6e9304b2cc | ||
|
|
5eab8f4907 | ||
|
|
f750487b88 | ||
|
|
8b0032f6d2 | ||
|
|
bb65f81200 | ||
|
|
04db40e100 | ||
|
|
1e162255d7 | ||
|
|
a479f3cb62 | ||
|
|
fbd6f9ece5 | ||
|
|
11c84208b7 | ||
|
|
4f02cef0f9 | ||
|
|
80dffb7942 | ||
|
|
0a8c2cf56d | ||
|
|
03fb4f4176 | ||
|
|
22afe7e555 | ||
|
|
69723b362f | ||
|
|
9e612c7171 | ||
|
|
7a9be0326a | ||
|
|
aaa1c55227 | ||
|
|
656f0da89a | ||
|
|
28e71e132c | ||
|
|
b30643299f | ||
|
|
b6b70af13f | ||
|
|
22dd7fc10b | ||
|
|
924bc20193 | ||
|
|
af7582b9e2 | ||
|
|
856d27d803 | ||
|
|
19f56280e4 | ||
|
|
d3800dbc85 | ||
|
|
9373dc4697 | ||
|
|
32eaa6c3f2 | ||
|
|
11ff8fc700 | ||
|
|
9c75cb1615 | ||
|
|
3f8b0e2eb7 | ||
|
|
69ce6857e8 | ||
|
|
3efa31efe4 | ||
|
|
275b09d2ea | ||
|
|
3cb0e3ed8b | ||
|
|
823c5ea4c4 | ||
|
|
c9ee482512 | ||
|
|
08750813ce | ||
|
|
75f4f66285 | ||
|
|
881bda739b | ||
|
|
d86f082e58 | ||
|
|
b12c5071fe | ||
|
|
f75201b3dd | ||
|
|
45ea7013f8 | ||
|
|
7d428f5eb5 | ||
|
|
9ff64e64ef | ||
|
|
4b23394569 | ||
|
|
81893c8841 | ||
|
|
10a1ea9b76 | ||
|
|
7fca493d0d | ||
|
|
85e4ae8761 | ||
|
|
6ebd5ae410 | ||
|
|
f57b111555 | ||
|
|
6596414675 | ||
|
|
ed7fd3c15d | ||
|
|
8cf7148114 | ||
|
|
b98443479f | ||
|
|
f917244265 | ||
|
|
ceb5bc13c3 | ||
|
|
ae0fc4fe8d | ||
|
|
0a1b9c7e70 | ||
|
|
f2cf1488e9 | ||
|
|
0426974539 | ||
|
|
b0e26f41b9 | ||
|
|
c20249730a | ||
|
|
b3b499e661 | ||
|
|
f377e283fd | ||
|
|
648a2ec4d5 | ||
|
|
83ec922584 | ||
|
|
88221ec77a | ||
|
|
e853346910 | ||
|
|
a088764b7b | ||
|
|
4a2f36cde8 | ||
|
|
401ee1ddf8 | ||
|
|
baacb1a18f | ||
|
|
5f1c645e3a | ||
|
|
79648637aa | ||
|
|
756bea0471 | ||
|
|
465632f519 | ||
|
|
b9e2d9bc8a | ||
|
|
d82c8cd4ae | ||
|
|
dd0f2b027a | ||
|
|
3806d1f3a6 | ||
|
|
f3e2ab9a34 | ||
|
|
685f627707 | ||
|
|
b2d172eae5 | ||
|
|
404825dc85 | ||
|
|
6e6f0a55d0 | ||
|
|
75d0b12008 | ||
|
|
2a4011ca5d | ||
|
|
ebb468166e | ||
|
|
06176912ee | ||
|
|
ed8fc156ac | ||
|
|
bff97f59b2 | ||
|
|
4c3aa03e13 | ||
|
|
f3a8b52617 | ||
|
|
0c3a77cd11 | ||
|
|
329df77790 |
+42
-4
@@ -137,6 +137,37 @@ class ForgotPasswordSerializer(serializers.Serializer):
|
|||||||
"""Forget password serializer"""
|
"""Forget password serializer"""
|
||||||
email = serializers.EmailField()
|
email = serializers.EmailField()
|
||||||
|
|
||||||
|
|
||||||
|
class AdminLoginSerializer(serializers.ModelSerializer):
|
||||||
|
"""admin login serializer"""
|
||||||
|
email = serializers.EmailField(required=True)
|
||||||
|
password = serializers.CharField(required=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""
|
||||||
|
meta class
|
||||||
|
"""
|
||||||
|
model = User
|
||||||
|
fields = ('email', 'password')
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
user = User.objects.filter(email__iexact=attrs['email'], is_superuser=True
|
||||||
|
).only('id', 'first_name', 'last_name', 'email',
|
||||||
|
'username', 'is_active', 'is_superuser').first()
|
||||||
|
|
||||||
|
if not user or not user.check_password(attrs['password']):
|
||||||
|
raise serializers.ValidationError({'details': ERROR_CODE['2002']})
|
||||||
|
|
||||||
|
self.context.update({'user': user})
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""
|
||||||
|
used to return the user object after validation
|
||||||
|
"""
|
||||||
|
return self.context['user']
|
||||||
|
|
||||||
|
|
||||||
class SuperUserSerializer(serializers.ModelSerializer):
|
class SuperUserSerializer(serializers.ModelSerializer):
|
||||||
"""Super admin serializer"""
|
"""Super admin serializer"""
|
||||||
user_type = serializers.SerializerMethodField('get_user_type')
|
user_type = serializers.SerializerMethodField('get_user_type')
|
||||||
@@ -185,10 +216,17 @@ class GuardianSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
def get_user_type(self, obj):
|
def get_user_type(self, obj):
|
||||||
"""user type"""
|
"""user type"""
|
||||||
email_verified = UserEmailOtp.objects.filter(email=obj.user.username).last()
|
if self.context.get('user_type', ''):
|
||||||
if email_verified and email_verified.user_type is not None:
|
return self.context.get('user_type')
|
||||||
return email_verified.user_type
|
# remove the below code once user_type can be passed
|
||||||
return str(NUMBER['two'])
|
# from everywhere from where this serializer is being called
|
||||||
|
else:
|
||||||
|
email_verified = UserEmailOtp.objects.filter(
|
||||||
|
email=obj.user.username
|
||||||
|
).last()
|
||||||
|
if email_verified and email_verified.user_type is not None:
|
||||||
|
return email_verified.user_type
|
||||||
|
return str(NUMBER['two'])
|
||||||
|
|
||||||
def get_auth(self, obj):
|
def get_auth(self, obj):
|
||||||
"""user email address"""
|
"""user email address"""
|
||||||
|
|||||||
+3
-2
@@ -28,14 +28,15 @@ from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVer
|
|||||||
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage,
|
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage,
|
||||||
GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet,
|
GoogleLoginViewSet, SigninWithApple, ProfileAPIViewSet, UploadImageAPIViewSet,
|
||||||
DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet, UserNotificationAPIViewSet,
|
DefaultImageAPIViewSet, DeleteUserProfileAPIViewSet, UserNotificationAPIViewSet,
|
||||||
UpdateUserNotificationAPIViewSet, SendSupportEmail, LogoutAPIView, AccessTokenAPIView)
|
UpdateUserNotificationAPIViewSet, SendSupportEmail, LogoutAPIView, AccessTokenAPIView,
|
||||||
|
AdminLoginViewSet)
|
||||||
"""Router"""
|
"""Router"""
|
||||||
router = routers.SimpleRouter()
|
router = routers.SimpleRouter()
|
||||||
|
|
||||||
"""API End points with router"""
|
"""API End points with router"""
|
||||||
router.register('user', UserLogin, basename='user')
|
router.register('user', UserLogin, basename='user')
|
||||||
"""super admin login"""
|
"""super admin login"""
|
||||||
router.register('admin', UserLogin, basename='admin')
|
router.register('admin', AdminLoginViewSet, basename='admin')
|
||||||
"""google login end point"""
|
"""google login end point"""
|
||||||
router.register('google-login', GoogleLoginViewSet, basename='admin')
|
router.register('google-login', GoogleLoginViewSet, basename='admin')
|
||||||
router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp')
|
router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp')
|
||||||
|
|||||||
+33
-5
@@ -1,4 +1,6 @@
|
|||||||
"""Account utils"""
|
"""Account utils"""
|
||||||
|
from celery import shared_task
|
||||||
|
|
||||||
"""Import django"""
|
"""Import django"""
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from rest_framework import viewsets, status
|
from rest_framework import viewsets, status
|
||||||
@@ -20,10 +22,11 @@ from rest_framework import serializers
|
|||||||
# Import messages from base package"""
|
# Import messages from base package"""
|
||||||
from junior.models import Junior
|
from junior.models import Junior
|
||||||
from guardian.models import Guardian
|
from guardian.models import Guardian
|
||||||
from account.models import UserDelete
|
from account.models import UserDelete, UserDeviceDetails
|
||||||
from base.messages import ERROR_CODE
|
from base.messages import ERROR_CODE
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from base.constants import NUMBER
|
||||||
|
from junior.models import JuniorPoints
|
||||||
# Define delete
|
# Define delete
|
||||||
# user account condition,
|
# user account condition,
|
||||||
# Define delete
|
# Define delete
|
||||||
@@ -43,7 +46,7 @@ from django.utils import timezone
|
|||||||
# referral code,
|
# referral code,
|
||||||
# Define function for generating
|
# Define function for generating
|
||||||
# alphanumeric code
|
# alphanumeric code
|
||||||
|
# otp expiry
|
||||||
def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num):
|
def delete_user_account_condition(user, user_type_data, user_type, user_tb, data, random_num):
|
||||||
"""delete user account"""
|
"""delete user account"""
|
||||||
if user_type == '1' and user_type_data == '1':
|
if user_type == '1' and user_type_data == '1':
|
||||||
@@ -91,7 +94,9 @@ def junior_account_update(user_tb):
|
|||||||
junior_data.is_active = False
|
junior_data.is_active = False
|
||||||
junior_data.is_verified = False
|
junior_data.is_verified = False
|
||||||
junior_data.guardian_code = '{}'
|
junior_data.guardian_code = '{}'
|
||||||
|
junior_data.guardian_code_status = str(NUMBER['one'])
|
||||||
junior_data.save()
|
junior_data.save()
|
||||||
|
JuniorPoints.objects.filter(junior=junior_data).delete()
|
||||||
|
|
||||||
def guardian_account_update(user_tb):
|
def guardian_account_update(user_tb):
|
||||||
"""update guardian account after delete the user account"""
|
"""update guardian account after delete the user account"""
|
||||||
@@ -106,6 +111,7 @@ def guardian_account_update(user_tb):
|
|||||||
for data in jun_data:
|
for data in jun_data:
|
||||||
data.guardian_code.remove(guardian_data.guardian_code)
|
data.guardian_code.remove(guardian_data.guardian_code)
|
||||||
data.save()
|
data.save()
|
||||||
|
@shared_task()
|
||||||
def send_otp_email(recipient_email, otp):
|
def send_otp_email(recipient_email, otp):
|
||||||
"""Send otp on email with template"""
|
"""Send otp on email with template"""
|
||||||
from_email = settings.EMAIL_FROM_ADDRESS
|
from_email = settings.EMAIL_FROM_ADDRESS
|
||||||
@@ -121,6 +127,20 @@ def send_otp_email(recipient_email, otp):
|
|||||||
)
|
)
|
||||||
return otp
|
return otp
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def user_device_details(user, device_id):
|
||||||
|
"""
|
||||||
|
Used to store the device id of the user
|
||||||
|
user: user object
|
||||||
|
device_id: string
|
||||||
|
return
|
||||||
|
"""
|
||||||
|
device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
|
||||||
|
if device_details:
|
||||||
|
device_details.device_id = device_id
|
||||||
|
device_details.save()
|
||||||
|
|
||||||
|
|
||||||
def send_support_email(name, sender, subject, message):
|
def send_support_email(name, sender, subject, message):
|
||||||
"""Send otp on email with template"""
|
"""Send otp on email with template"""
|
||||||
to_email = [settings.EMAIL_FROM_ADDRESS]
|
to_email = [settings.EMAIL_FROM_ADDRESS]
|
||||||
@@ -138,12 +158,14 @@ def send_support_email(name, sender, subject, message):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
return name
|
return name
|
||||||
def custom_response(detail, data=None, response_status=status.HTTP_200_OK):
|
|
||||||
|
|
||||||
|
def custom_response(detail, data=None, response_status=status.HTTP_200_OK, count=None):
|
||||||
"""Custom response code"""
|
"""Custom response code"""
|
||||||
if not data:
|
if not data:
|
||||||
"""when data is none"""
|
"""when data is none"""
|
||||||
data = None
|
data = None
|
||||||
return Response({"data": data, "message": detail, "status": "success", "code": response_status})
|
return Response({"data": data, "message": detail, "status": "success", "code": response_status, "count": count})
|
||||||
|
|
||||||
|
|
||||||
def custom_error_response(detail, response_status):
|
def custom_error_response(detail, response_status):
|
||||||
@@ -229,3 +251,9 @@ def generate_code(value, user_id):
|
|||||||
|
|
||||||
|
|
||||||
OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1)
|
OTP_EXPIRY = timezone.now() + timezone.timedelta(days=1)
|
||||||
|
|
||||||
|
def get_user_full_name(user_obj):
|
||||||
|
"""
|
||||||
|
to get user's full name
|
||||||
|
"""
|
||||||
|
return f"{user_obj.first_name} {user_obj.last_name}" if user_obj.last_name else user_obj.first_name
|
||||||
|
|||||||
+105
-59
@@ -1,11 +1,12 @@
|
|||||||
"""Account view """
|
"""Account view """
|
||||||
|
import threading
|
||||||
|
|
||||||
from notifications.utils import remove_fcm_token
|
from notifications.utils import remove_fcm_token
|
||||||
|
|
||||||
"""Django import"""
|
# django imports
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from rest_framework import viewsets, status, views
|
from rest_framework import viewsets, status, views
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
import random
|
|
||||||
import logging
|
import logging
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
import jwt
|
import jwt
|
||||||
@@ -18,25 +19,27 @@ import google.auth.transport.requests
|
|||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
import requests
|
import requests
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import mixins
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
"""App Import"""
|
|
||||||
|
# local imports
|
||||||
from guardian.models import Guardian
|
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 guardian.utils import upload_image_to_alibaba
|
||||||
from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
|
from account.models import UserDeviceDetails, UserPhoneOtp, UserEmailOtp, DefaultTaskImages, UserNotification
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
"""Account serializer"""
|
|
||||||
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
|
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
|
||||||
ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer,
|
ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer,
|
||||||
GoogleLoginSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer,
|
GoogleLoginSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer,
|
||||||
DefaultTaskImagesSerializer, DefaultTaskImagesDetailsSerializer, UserDeleteSerializer,
|
DefaultTaskImagesSerializer, DefaultTaskImagesDetailsSerializer, UserDeleteSerializer,
|
||||||
UserNotificationSerializer, UpdateUserNotificationSerializer, UserPhoneOtpSerializer)
|
UserNotificationSerializer, UpdateUserNotificationSerializer, UserPhoneOtpSerializer,
|
||||||
|
AdminLoginSerializer)
|
||||||
from rest_framework_simplejwt.tokens import RefreshToken
|
from rest_framework_simplejwt.tokens import RefreshToken
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||||
from base.constants import NUMBER, ZOD, JUN, GRD
|
from base.constants import NUMBER, ZOD, JUN, GRD, USER_TYPE_FLAG
|
||||||
from guardian.tasks import generate_otp
|
from guardian.tasks import generate_otp
|
||||||
from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response,
|
from account.utils import (send_otp_email, send_support_email, custom_response, custom_error_response,
|
||||||
generate_code, OTP_EXPIRY)
|
generate_code, OTP_EXPIRY, user_device_details)
|
||||||
from junior.serializers import JuniorProfileSerializer
|
from junior.serializers import JuniorProfileSerializer
|
||||||
from guardian.serializers import GuardianProfileSerializer
|
from guardian.serializers import GuardianProfileSerializer
|
||||||
|
|
||||||
@@ -95,6 +98,8 @@ class GoogleLoginMixin(object):
|
|||||||
referral_code=generate_code(ZOD, user_obj.id)
|
referral_code=generate_code(ZOD, user_obj.id)
|
||||||
)
|
)
|
||||||
serializer = JuniorSerializer(junior_query)
|
serializer = JuniorSerializer(junior_query)
|
||||||
|
position = Junior.objects.all().count()
|
||||||
|
JuniorPoints.objects.create(junior=junior_query, position=position)
|
||||||
if str(user_type) == '2':
|
if str(user_type) == '2':
|
||||||
guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True,
|
guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True,
|
||||||
image=profile_picture,signup_method='2',
|
image=profile_picture,signup_method='2',
|
||||||
@@ -145,6 +150,8 @@ class SigninWithApple(views.APIView):
|
|||||||
junior_code=generate_code(JUN, user.id),
|
junior_code=generate_code(JUN, user.id),
|
||||||
referral_code=generate_code(ZOD, user.id))
|
referral_code=generate_code(ZOD, user.id))
|
||||||
serializer = JuniorSerializer(junior_query)
|
serializer = JuniorSerializer(junior_query)
|
||||||
|
position = Junior.objects.all().count()
|
||||||
|
JuniorPoints.objects.create(junior=junior_query, position=position)
|
||||||
if str(user_type) == '2':
|
if str(user_type) == '2':
|
||||||
guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True,
|
guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True,
|
||||||
signup_method='3',
|
signup_method='3',
|
||||||
@@ -243,7 +250,6 @@ class ForgotPasswordAPIView(views.APIView):
|
|||||||
|
|
||||||
class SendPhoneOtp(viewsets.ModelViewSet):
|
class SendPhoneOtp(viewsets.ModelViewSet):
|
||||||
"""Send otp on phone"""
|
"""Send otp on phone"""
|
||||||
queryset = UserPhoneOtp.objects.all()
|
|
||||||
serializer_class = UserPhoneOtpSerializer
|
serializer_class = UserPhoneOtpSerializer
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
otp = generate_otp()
|
otp = generate_otp()
|
||||||
@@ -260,7 +266,6 @@ class SendPhoneOtp(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class UserPhoneVerification(viewsets.ModelViewSet):
|
class UserPhoneVerification(viewsets.ModelViewSet):
|
||||||
"""Send otp on phone"""
|
"""Send otp on phone"""
|
||||||
queryset = UserPhoneOtp.objects.all()
|
|
||||||
serializer_class = UserPhoneOtpSerializer
|
serializer_class = UserPhoneOtpSerializer
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
@@ -276,29 +281,48 @@ class UserPhoneVerification(viewsets.ModelViewSet):
|
|||||||
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE["2008"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class UserLogin(viewsets.ViewSet):
|
class UserLogin(viewsets.ViewSet):
|
||||||
"""User login"""
|
"""User login"""
|
||||||
@action(methods=['post'], detail=False)
|
@action(methods=['post'], detail=False)
|
||||||
def login(self, request):
|
def login(self, request):
|
||||||
username = request.data.get('username')
|
username = request.data.get('username')
|
||||||
password = request.data.get('password')
|
password = request.data.get('password')
|
||||||
|
user_type = request.data.get('user_type')
|
||||||
device_id = request.META.get('HTTP_DEVICE_ID')
|
device_id = request.META.get('HTTP_DEVICE_ID')
|
||||||
user = authenticate(request, username=username, password=password)
|
user = authenticate(request, username=username, password=password)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if user is not None:
|
if user is not None:
|
||||||
login(request, user)
|
login(request, user)
|
||||||
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
|
if str(user_type) == USER_TYPE_FLAG["TWO"]:
|
||||||
if guardian_data:
|
guardian_data = Guardian.objects.filter(user__username=username, is_verified=True).last()
|
||||||
serializer = GuardianSerializer(guardian_data).data
|
if guardian_data:
|
||||||
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
|
serializer = GuardianSerializer(
|
||||||
if junior_data:
|
guardian_data, context={'user_type': user_type}
|
||||||
serializer = JuniorSerializer(junior_data).data
|
).data
|
||||||
device_details, created = UserDeviceDetails.objects.get_or_create(user=user)
|
else:
|
||||||
if device_details:
|
return custom_error_response(
|
||||||
device_details.device_id = device_id
|
ERROR_CODE["2070"],
|
||||||
device_details.save()
|
response_status=status.HTTP_401_UNAUTHORIZED
|
||||||
|
)
|
||||||
|
elif str(user_type) == USER_TYPE_FLAG["FIRST"]:
|
||||||
|
junior_data = Junior.objects.filter(auth__username=username, is_verified=True).last()
|
||||||
|
if junior_data:
|
||||||
|
serializer = JuniorSerializer(
|
||||||
|
junior_data, context={'user_type': user_type}
|
||||||
|
).data
|
||||||
|
else:
|
||||||
|
return custom_error_response(
|
||||||
|
ERROR_CODE["2071"],
|
||||||
|
response_status=status.HTTP_401_UNAUTHORIZED
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return custom_error_response(
|
||||||
|
ERROR_CODE["2069"],
|
||||||
|
response_status=status.HTTP_401_UNAUTHORIZED
|
||||||
|
)
|
||||||
|
# storing device id in using thread so the time would be reduced
|
||||||
|
threading.Thread(target=user_device_details, args=(user, device_id))
|
||||||
return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3003'], serializer, response_status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
|
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
|
||||||
@@ -308,9 +332,12 @@ class UserLogin(viewsets.ViewSet):
|
|||||||
refresh = RefreshToken.for_user(user)
|
refresh = RefreshToken.for_user(user)
|
||||||
access_token = str(refresh.access_token)
|
access_token = str(refresh.access_token)
|
||||||
refresh_token = str(refresh)
|
refresh_token = str(refresh)
|
||||||
data = {"auth_token":access_token, "refresh_token":refresh_token, "is_profile_complete": False,
|
data = {
|
||||||
"user_type": email_verified.user_type,
|
"auth_token":access_token,
|
||||||
}
|
"refresh_token":refresh_token,
|
||||||
|
"is_profile_complete": False,
|
||||||
|
"user_type": user_type,
|
||||||
|
}
|
||||||
is_verified = False
|
is_verified = False
|
||||||
if email_verified:
|
if email_verified:
|
||||||
is_verified = email_verified.is_verified
|
is_verified = email_verified.is_verified
|
||||||
@@ -319,43 +346,68 @@ class UserLogin(viewsets.ViewSet):
|
|||||||
email_verified.otp = otp
|
email_verified.otp = otp
|
||||||
email_verified.save()
|
email_verified.save()
|
||||||
data.update({"email_otp":otp})
|
data.update({"email_otp":otp})
|
||||||
send_otp_email(username, otp)
|
send_otp_email.delay(username, otp)
|
||||||
return custom_response(ERROR_CODE['2024'], {"email_otp": otp, "is_email_verified": is_verified},
|
return custom_response(
|
||||||
response_status=status.HTTP_200_OK)
|
ERROR_CODE['2024'],
|
||||||
|
{"email_otp": otp, "is_email_verified": is_verified},
|
||||||
|
response_status=status.HTTP_200_OK
|
||||||
|
)
|
||||||
data.update({"is_email_verified": is_verified})
|
data.update({"is_email_verified": is_verified})
|
||||||
return custom_response(SUCCESS_CODE['3003'], data, response_status=status.HTTP_200_OK)
|
return custom_response(
|
||||||
|
SUCCESS_CODE['3003'],
|
||||||
|
data,
|
||||||
|
response_status=status.HTTP_200_OK
|
||||||
|
)
|
||||||
|
|
||||||
@action(methods=['post'], detail=False)
|
@action(methods=['post'], detail=False)
|
||||||
def admin_login(self, request):
|
def admin_login(self, request):
|
||||||
username = request.data.get('username')
|
email = request.data.get('email')
|
||||||
password = request.data.get('password')
|
password = request.data.get('password')
|
||||||
user = authenticate(request, username=username, password=password)
|
user = User.objects.filter(email__iexact=email, is_superuser=True
|
||||||
try:
|
).only('id', 'first_name', 'last_name', 'email',
|
||||||
if user is not None:
|
'username', 'is_active', 'is_superuser').first()
|
||||||
login(request, user)
|
|
||||||
if user.is_superuser:
|
if not user or not user.check_password(password):
|
||||||
serializer = SuperUserSerializer(user)
|
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK)
|
|
||||||
else:
|
serializer = SuperUserSerializer(user)
|
||||||
return custom_error_response(ERROR_CODE["2002"], response_status=status.HTTP_401_UNAUTHORIZED)
|
return custom_response(SUCCESS_CODE['3003'], serializer.data, response_status=status.HTTP_200_OK)
|
||||||
except Exception as e:
|
|
||||||
logging.error(e)
|
|
||||||
refresh = RefreshToken.for_user(user)
|
class AdminLoginViewSet(viewsets.GenericViewSet):
|
||||||
access_token = str(refresh.access_token)
|
"""
|
||||||
refresh_token = str(refresh)
|
admin login api
|
||||||
data = {"auth_token": access_token, "refresh_token":refresh_token, "user_type": '3'}
|
"""
|
||||||
return custom_response(None, data, response_status=status.HTTP_200_OK)
|
serializer_class = AdminLoginSerializer
|
||||||
|
|
||||||
|
@action(methods=['post'], url_name='login', url_path='login', detail=False)
|
||||||
|
def admin_login(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
:param request:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
serializer = self.serializer_class(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
user = serializer.save()
|
||||||
|
refresh = RefreshToken.for_user(user)
|
||||||
|
access_token = str(refresh.access_token)
|
||||||
|
refresh_token = str(refresh)
|
||||||
|
data = {"auth_token": access_token, "refresh_token": refresh_token, "username": user.username,
|
||||||
|
"email": user.email, "first_name": user.first_name, "last_name": user.last_name,
|
||||||
|
"is_active": user.is_active, "user_type": '3', "is_superuser": user.is_superuser}
|
||||||
|
return custom_response(None, data)
|
||||||
|
|
||||||
|
|
||||||
class UserEmailVerification(viewsets.ModelViewSet):
|
class UserEmailVerification(viewsets.ModelViewSet):
|
||||||
"""User Email verification"""
|
"""User Email verification"""
|
||||||
serializer_class = EmailVerificationSerializer
|
serializer_class = EmailVerificationSerializer
|
||||||
queryset = UserEmailOtp.objects.all()
|
http_method_names = ('post',)
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
user_obj = User.objects.filter(username=self.request.GET.get('email')).last()
|
user_obj = User.objects.filter(username=self.request.data.get('email')).last()
|
||||||
email_data = UserEmailOtp.objects.filter(email=self.request.GET.get('email'),
|
email_data = UserEmailOtp.objects.filter(email=self.request.data.get('email'),
|
||||||
otp=self.request.GET.get('otp')).last()
|
otp=self.request.data.get('otp')).last()
|
||||||
if email_data:
|
if email_data:
|
||||||
input_datetime_str = str(email_data.expired_at)
|
input_datetime_str = str(email_data.expired_at)
|
||||||
input_format = "%Y-%m-%d %H:%M:%S.%f%z"
|
input_format = "%Y-%m-%d %H:%M:%S.%f%z"
|
||||||
@@ -369,12 +421,12 @@ class UserEmailVerification(viewsets.ModelViewSet):
|
|||||||
email_data.is_verified = True
|
email_data.is_verified = True
|
||||||
email_data.save()
|
email_data.save()
|
||||||
if email_data.user_type == '1':
|
if email_data.user_type == '1':
|
||||||
junior_data = Junior.objects.filter(auth__email=self.request.GET.get('email')).last()
|
junior_data = Junior.objects.filter(auth__email=self.request.data.get('email')).last()
|
||||||
if junior_data:
|
if junior_data:
|
||||||
junior_data.is_verified = True
|
junior_data.is_verified = True
|
||||||
junior_data.save()
|
junior_data.save()
|
||||||
else:
|
else:
|
||||||
guardian_data = Guardian.objects.filter(user__email=self.request.GET.get('email')).last()
|
guardian_data = Guardian.objects.filter(user__email=self.request.data.get('email')).last()
|
||||||
if guardian_data:
|
if guardian_data:
|
||||||
guardian_data.is_verified = True
|
guardian_data.is_verified = True
|
||||||
guardian_data.save()
|
guardian_data.save()
|
||||||
@@ -392,7 +444,6 @@ class UserEmailVerification(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class ReSendEmailOtp(viewsets.ModelViewSet):
|
class ReSendEmailOtp(viewsets.ModelViewSet):
|
||||||
"""Send otp on phone"""
|
"""Send otp on phone"""
|
||||||
queryset = UserEmailOtp.objects.all()
|
|
||||||
serializer_class = EmailVerificationSerializer
|
serializer_class = EmailVerificationSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
@@ -415,7 +466,6 @@ class ReSendEmailOtp(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class ProfileAPIViewSet(viewsets.ModelViewSet):
|
class ProfileAPIViewSet(viewsets.ModelViewSet):
|
||||||
"""Profile viewset"""
|
"""Profile viewset"""
|
||||||
queryset = User.objects.all()
|
|
||||||
serializer_class = JuniorProfileSerializer
|
serializer_class = JuniorProfileSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
@@ -434,7 +484,6 @@ class ProfileAPIViewSet(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class UploadImageAPIViewSet(viewsets.ModelViewSet):
|
class UploadImageAPIViewSet(viewsets.ModelViewSet):
|
||||||
"""upload task image"""
|
"""upload task image"""
|
||||||
queryset = DefaultTaskImages.objects.all()
|
|
||||||
serializer_class = DefaultTaskImagesSerializer
|
serializer_class = DefaultTaskImagesSerializer
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
"""upload images"""
|
"""upload images"""
|
||||||
@@ -453,7 +502,6 @@ class UploadImageAPIViewSet(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class DefaultImageAPIViewSet(viewsets.ModelViewSet):
|
class DefaultImageAPIViewSet(viewsets.ModelViewSet):
|
||||||
"""Profile viewset"""
|
"""Profile viewset"""
|
||||||
queryset = DefaultTaskImages.objects.all()
|
|
||||||
serializer_class = DefaultTaskImagesDetailsSerializer
|
serializer_class = DefaultTaskImagesDetailsSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
@@ -484,19 +532,17 @@ class DeleteUserProfileAPIViewSet(viewsets.GenericViewSet):
|
|||||||
|
|
||||||
class UserNotificationAPIViewSet(viewsets.ModelViewSet):
|
class UserNotificationAPIViewSet(viewsets.ModelViewSet):
|
||||||
"""notification viewset"""
|
"""notification viewset"""
|
||||||
queryset = UserNotification.objects.all()
|
|
||||||
serializer_class = UserNotificationSerializer
|
serializer_class = UserNotificationSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""profile view"""
|
"""profile view"""
|
||||||
queryset = self.queryset.filter(user=request.user)
|
queryset = UserNotification.objects.filter(user=request.user)
|
||||||
serializer = UserNotificationSerializer(queryset, many=True)
|
serializer = UserNotificationSerializer(queryset, many=True)
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
|
class UpdateUserNotificationAPIViewSet(viewsets.ModelViewSet):
|
||||||
"""Update notification viewset"""
|
"""Update notification viewset"""
|
||||||
queryset = UserNotification.objects.all()
|
|
||||||
serializer_class = UpdateUserNotificationSerializer
|
serializer_class = UpdateUserNotificationSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
|||||||
+24
-2
@@ -50,6 +50,13 @@ USER_TYPE = (
|
|||||||
('2', 'guardian'),
|
('2', 'guardian'),
|
||||||
('3', 'superuser')
|
('3', 'superuser')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
USER_TYPE_FLAG = {
|
||||||
|
"FIRST" : "1",
|
||||||
|
"TWO" : "2",
|
||||||
|
"THREE": "3"
|
||||||
|
}
|
||||||
|
|
||||||
"""gender"""
|
"""gender"""
|
||||||
GENDERS = (
|
GENDERS = (
|
||||||
('1', 'Male'),
|
('1', 'Male'),
|
||||||
@@ -70,6 +77,18 @@ SIGNUP_METHODS = (
|
|||||||
('2', 'google'),
|
('2', 'google'),
|
||||||
('3', 'apple')
|
('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
|
||||||
RELATIONSHIP = (
|
RELATIONSHIP = (
|
||||||
('1', 'parent'),
|
('1', 'parent'),
|
||||||
@@ -83,6 +102,7 @@ IN_PROGRESS = 2
|
|||||||
REJECTED = 3
|
REJECTED = 3
|
||||||
REQUESTED = 4
|
REQUESTED = 4
|
||||||
COMPLETED = 5
|
COMPLETED = 5
|
||||||
|
EXPIRED = 6
|
||||||
TASK_POINTS = 5
|
TASK_POINTS = 5
|
||||||
# duplicate name used defined in constant PROJECT_NAME
|
# duplicate name used defined in constant PROJECT_NAME
|
||||||
PROJECT_NAME = 'Zod Bank'
|
PROJECT_NAME = 'Zod Bank'
|
||||||
@@ -105,7 +125,9 @@ MAX_ARTICLE_CARD = 6
|
|||||||
MIN_ARTICLE_SURVEY = 5
|
MIN_ARTICLE_SURVEY = 5
|
||||||
MAX_ARTICLE_SURVEY = 10
|
MAX_ARTICLE_SURVEY = 10
|
||||||
|
|
||||||
# real time url
|
# already register
|
||||||
time_url = "http://worldtimeapi.org/api/timezone/Asia/Riyadh"
|
Already_register_user = "duplicate key value violates unique constraint"
|
||||||
|
|
||||||
ARTICLE_CARD_IMAGE_FOLDER = 'article-card-images'
|
ARTICLE_CARD_IMAGE_FOLDER = 'article-card-images'
|
||||||
|
|
||||||
|
DATE_FORMAT = '%Y-%m-%d'
|
||||||
|
|||||||
+32
-9
@@ -23,15 +23,15 @@ ERROR_CODE_REQUIRED = {
|
|||||||
|
|
||||||
# Error code
|
# Error code
|
||||||
ERROR_CODE = {
|
ERROR_CODE = {
|
||||||
"2000": "Email not found.",
|
"2000": "Invalid email address. Please enter a registered email.",
|
||||||
"2001": "This is your existing password. Please choose other one",
|
"2001": "This is your existing password. Please choose other one",
|
||||||
"2002": "Invalid login credentials.",
|
"2002": "Invalid username or password.",
|
||||||
"2003": "An account already exists with this email address.",
|
"2003": "An account already exists with this email address.",
|
||||||
"2004": "User not found.",
|
"2004": "User not found.",
|
||||||
"2005": "Your account has been activated.",
|
"2005": "Your account has been activated.",
|
||||||
"2006": "Your account is not activated.",
|
"2006": "Your account is not activated.",
|
||||||
"2007": "Your account already activated.",
|
"2007": "Your account already activated.",
|
||||||
"2008": "Invalid OTP.",
|
"2008": "The OTP entered is not correct.",
|
||||||
"2009": "The user provided cannot be found or the reset password token has become invalid/timed out.",
|
"2009": "The user provided cannot be found or the reset password token has become invalid/timed out.",
|
||||||
"2010": "Invalid Link.",
|
"2010": "Invalid Link.",
|
||||||
"2011": "Your profile has not been completed yet.",
|
"2011": "Your profile has not been completed yet.",
|
||||||
@@ -54,7 +54,7 @@ ERROR_CODE = {
|
|||||||
"2026": "New password should not same as old password",
|
"2026": "New password should not same as old password",
|
||||||
"2027": "data should contain `identityToken`",
|
"2027": "data should contain `identityToken`",
|
||||||
"2028": "You are not authorized person to sign up on this platform",
|
"2028": "You are not authorized person to sign up on this platform",
|
||||||
"2029": "Validity of otp verification is expired",
|
"2029": "Validity of otp verification has expired. Please request a new one.",
|
||||||
"2030": "Use correct user type and token",
|
"2030": "Use correct user type and token",
|
||||||
# invalid password
|
# invalid password
|
||||||
"2031": "Invalid password",
|
"2031": "Invalid password",
|
||||||
@@ -91,7 +91,14 @@ ERROR_CODE = {
|
|||||||
"2062": "Please enter email address",
|
"2062": "Please enter email address",
|
||||||
"2063": "Unauthorized access.",
|
"2063": "Unauthorized access.",
|
||||||
"2064": "To change your password first request an OTP and get it verify then change your password.",
|
"2064": "To change your password first request an OTP and get it verify then change your password.",
|
||||||
"2065": "Passwords do not match. Please try again."
|
"2065": "Passwords do not match. Please try again.",
|
||||||
|
"2066": "Task does not exist or not in expired state",
|
||||||
|
"2067": "Action not allowed. User type missing.",
|
||||||
|
"2068": "No guardian associated with this junior",
|
||||||
|
"2069": "Invalid user type",
|
||||||
|
"2070": "You did not find as a guardian",
|
||||||
|
"2071": "You did not find as a junior"
|
||||||
|
|
||||||
}
|
}
|
||||||
"""Success message code"""
|
"""Success message code"""
|
||||||
SUCCESS_CODE = {
|
SUCCESS_CODE = {
|
||||||
@@ -107,7 +114,7 @@ SUCCESS_CODE = {
|
|||||||
# Success code for link verified
|
# Success code for link verified
|
||||||
"3005": "Your account is deleted successfully.",
|
"3005": "Your account is deleted successfully.",
|
||||||
# Success code for password reset
|
# Success code for password reset
|
||||||
"3006": "Your password has been reset successfully.",
|
"3006": "Password reset successful. You can now log in with your new password.",
|
||||||
# Success code for password update
|
# Success code for password update
|
||||||
"3007": "Your password has been changed successfully.",
|
"3007": "Your password has been changed successfully.",
|
||||||
# Success code for valid link
|
# Success code for valid link
|
||||||
@@ -120,8 +127,8 @@ SUCCESS_CODE = {
|
|||||||
"3012": "Phone OTP Verified successfully",
|
"3012": "Phone OTP Verified successfully",
|
||||||
"3013": "Valid Guardian code",
|
"3013": "Valid Guardian code",
|
||||||
"3014": "Password has been updated successfully.",
|
"3014": "Password has been updated successfully.",
|
||||||
"3015": "Verification code sent on your email.",
|
"3015": "Verification code has been sent on your email.",
|
||||||
"3016": "Send otp on your Email successfully",
|
"3016": "An OTP has been sent on your email.",
|
||||||
"3017": "Profile image update successfully",
|
"3017": "Profile image update successfully",
|
||||||
"3018": "Task created successfully",
|
"3018": "Task created successfully",
|
||||||
"3019": "Support Email sent successfully",
|
"3019": "Support Email sent successfully",
|
||||||
@@ -140,7 +147,23 @@ SUCCESS_CODE = {
|
|||||||
"3032": "Task request sent successfully",
|
"3032": "Task request sent successfully",
|
||||||
"3033": "Valid Referral code",
|
"3033": "Valid Referral code",
|
||||||
"3034": "Invite guardian successfully",
|
"3034": "Invite guardian successfully",
|
||||||
"3035": "Task started successfully"
|
"3035": "Task started successfully",
|
||||||
|
"3036": "Task reassign successfully",
|
||||||
|
"3037": "Profile has been updated successfully.",
|
||||||
|
"3038": "Status has been changed successfully.",
|
||||||
|
# notification read
|
||||||
|
"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"""
|
||||||
STATUS_CODE_ERROR = {
|
STATUS_CODE_ERROR = {
|
||||||
|
|||||||
Binary file not shown.
+121
-18
@@ -1,5 +1,5 @@
|
|||||||
"""Serializer of Guardian"""
|
"""Serializer of Guardian"""
|
||||||
"""Third party Django app"""
|
# third party imports
|
||||||
import logging
|
import logging
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
# Import Refresh token of jwt
|
# Import Refresh token of jwt
|
||||||
@@ -7,7 +7,8 @@ from rest_framework_simplejwt.tokens import RefreshToken
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from datetime import datetime, time
|
from datetime import datetime, time
|
||||||
"""Import Django app"""
|
import pytz
|
||||||
|
from django.utils import timezone
|
||||||
# Import guardian's model,
|
# Import guardian's model,
|
||||||
# Import junior's model,
|
# Import junior's model,
|
||||||
# Import account's model,
|
# Import account's model,
|
||||||
@@ -16,19 +17,19 @@ from datetime import datetime, time
|
|||||||
# Import messages from
|
# Import messages from
|
||||||
# base package,
|
# base package,
|
||||||
# Import some functions
|
# Import some functions
|
||||||
# from utils file"""
|
# local imports
|
||||||
from .models import Guardian, JuniorTask
|
from .models import Guardian, JuniorTask
|
||||||
from account.models import UserProfile, UserEmailOtp, UserNotification
|
from account.models import UserProfile, UserEmailOtp, UserNotification
|
||||||
from account.utils import generate_code
|
from account.utils import generate_code
|
||||||
from junior.serializers import JuniorDetailSerializer
|
from junior.serializers import JuniorDetailSerializer
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
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
|
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
|
||||||
from .utils import real_time, convert_timedelta_into_datetime, update_referral_points
|
from .utils import real_time, convert_timedelta_into_datetime, update_referral_points
|
||||||
# notification's constant
|
# notification's constant
|
||||||
from notifications.constants import TASK_POINTS, TASK_REJECTED
|
from notifications.constants import TASK_POINTS, TASK_REJECTED
|
||||||
# send notification function
|
# send notification function
|
||||||
from notifications.utils import send_notification
|
from notifications.utils import send_notification, send_notification_to_junior
|
||||||
|
|
||||||
|
|
||||||
# In this serializer file
|
# In this serializer file
|
||||||
@@ -67,8 +68,10 @@ class UserSerializer(serializers.ModelSerializer):
|
|||||||
UserNotification.objects.get_or_create(user=user)
|
UserNotification.objects.get_or_create(user=user)
|
||||||
if user_type == str(NUMBER['one']):
|
if user_type == str(NUMBER['one']):
|
||||||
# create junior profile
|
# create junior profile
|
||||||
Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id),
|
junior = Junior.objects.create(auth=user, junior_code=generate_code(JUN, user.id),
|
||||||
referral_code=generate_code(ZOD, 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']):
|
if user_type == str(NUMBER['two']):
|
||||||
# create guardian profile
|
# create guardian profile
|
||||||
Guardian.objects.create(user=user, guardian_code=generate_code(GRD, user.id),
|
Guardian.objects.create(user=user, guardian_code=generate_code(GRD, user.id),
|
||||||
@@ -81,7 +84,7 @@ class UserSerializer(serializers.ModelSerializer):
|
|||||||
otp_verified = False
|
otp_verified = False
|
||||||
if otp and otp.is_verified:
|
if otp and otp.is_verified:
|
||||||
otp_verified = True
|
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",
|
"code": 400, "status":"failed",
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -211,7 +214,7 @@ class GuardianDetailSerializer(serializers.ModelSerializer):
|
|||||||
"""Meta info"""
|
"""Meta info"""
|
||||||
model = Guardian
|
model = Guardian
|
||||||
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
||||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
'guardian_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
||||||
'updated_at']
|
'updated_at']
|
||||||
class TaskDetailsSerializer(serializers.ModelSerializer):
|
class TaskDetailsSerializer(serializers.ModelSerializer):
|
||||||
"""Task detail serializer"""
|
"""Task detail serializer"""
|
||||||
@@ -224,7 +227,10 @@ class TaskDetailsSerializer(serializers.ModelSerializer):
|
|||||||
""" remaining time to complete task"""
|
""" remaining time to complete task"""
|
||||||
due_date_datetime = datetime.combine(obj.due_date, datetime.max.time())
|
due_date_datetime = datetime.combine(obj.due_date, datetime.max.time())
|
||||||
# fetch real time
|
# fetch real time
|
||||||
current_datetime = real_time()
|
# current_datetime = real_time()
|
||||||
|
# new code
|
||||||
|
due_date_datetime = due_date_datetime.astimezone(pytz.utc)
|
||||||
|
current_datetime = timezone.now().astimezone(pytz.utc)
|
||||||
# Perform the subtraction
|
# Perform the subtraction
|
||||||
if due_date_datetime > current_datetime:
|
if due_date_datetime > current_datetime:
|
||||||
time_difference = due_date_datetime - current_datetime
|
time_difference = due_date_datetime - current_datetime
|
||||||
@@ -244,6 +250,34 @@ class TaskDetailsSerializer(serializers.ModelSerializer):
|
|||||||
'requested_on', 'rejected_on', 'completed_on', 'is_expired',
|
'requested_on', 'rejected_on', 'completed_on', 'is_expired',
|
||||||
'junior', 'task_status', 'is_active', 'remaining_time', 'created_at','updated_at']
|
'junior', 'task_status', 'is_active', 'remaining_time', 'created_at','updated_at']
|
||||||
|
|
||||||
|
class TaskDetailsjuniorSerializer(serializers.ModelSerializer):
|
||||||
|
"""Task detail serializer"""
|
||||||
|
|
||||||
|
guardian = GuardianDetailSerializer()
|
||||||
|
remaining_time = serializers.SerializerMethodField('get_remaining_time')
|
||||||
|
|
||||||
|
def get_remaining_time(self, obj):
|
||||||
|
""" remaining time to complete task"""
|
||||||
|
due_date_datetime = datetime.combine(obj.due_date, datetime.max.time())
|
||||||
|
# fetch real time
|
||||||
|
# current_datetime = real_time()
|
||||||
|
# new code
|
||||||
|
due_date_datetime = due_date_datetime.astimezone(pytz.utc)
|
||||||
|
current_datetime = timezone.now().astimezone(pytz.utc)
|
||||||
|
# Perform the subtraction
|
||||||
|
if due_date_datetime > current_datetime:
|
||||||
|
time_difference = due_date_datetime - current_datetime
|
||||||
|
time_only = convert_timedelta_into_datetime(time_difference)
|
||||||
|
return str(time_difference.days) + ' days ' + str(time_only)
|
||||||
|
return str(NUMBER['zero']) + ' days ' + '00:00:00:00000'
|
||||||
|
|
||||||
|
|
||||||
|
class Meta(object):
|
||||||
|
"""Meta info"""
|
||||||
|
model = JuniorTask
|
||||||
|
fields = ['id', 'guardian', 'task_name', 'task_description', 'points', 'due_date','default_image', 'image',
|
||||||
|
'requested_on', 'rejected_on', 'completed_on',
|
||||||
|
'junior', 'task_status', 'is_active', 'remaining_time', 'created_at','updated_at']
|
||||||
|
|
||||||
class TopJuniorSerializer(serializers.ModelSerializer):
|
class TopJuniorSerializer(serializers.ModelSerializer):
|
||||||
"""Top junior serializer"""
|
"""Top junior serializer"""
|
||||||
@@ -320,7 +354,8 @@ class ApproveJuniorSerializer(serializers.ModelSerializer):
|
|||||||
"""update guardian code"""
|
"""update guardian code"""
|
||||||
instance = self.context['junior']
|
instance = self.context['junior']
|
||||||
instance.guardian_code = [self.context['guardian_code']]
|
instance.guardian_code = [self.context['guardian_code']]
|
||||||
instance.is_invited = True
|
instance.guardian_code_approved = True
|
||||||
|
instance.guardian_code_status = str(NUMBER['two'])
|
||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -346,18 +381,86 @@ class ApproveTaskSerializer(serializers.ModelSerializer):
|
|||||||
# update total task point
|
# update total task point
|
||||||
junior_data.total_points = junior_data.total_points + instance.points
|
junior_data.total_points = junior_data.total_points + instance.points
|
||||||
# update complete time of task
|
# update complete time of task
|
||||||
instance.completed_on = real_time()
|
# instance.completed_on = real_time()
|
||||||
send_notification.delay(TASK_POINTS, None, junior_details.auth.id, {})
|
instance.completed_on = timezone.now().astimezone(pytz.utc)
|
||||||
|
send_notification_to_junior.delay(TASK_POINTS, None, junior_details.auth.id,
|
||||||
|
{'task_id': instance.id})
|
||||||
else:
|
else:
|
||||||
# reject the task
|
# reject the task
|
||||||
instance.task_status = str(NUMBER['three'])
|
instance.task_status = str(NUMBER['three'])
|
||||||
instance.is_approved = False
|
instance.is_approved = False
|
||||||
# update total task point
|
|
||||||
junior_data.total_points = junior_data.total_points - instance.points
|
|
||||||
# update reject time of task
|
# update reject time of task
|
||||||
instance.rejected_on = real_time()
|
# instance.rejected_on = real_time()
|
||||||
send_notification.delay(TASK_REJECTED, None, junior_details.auth.id, {})
|
instance.rejected_on = timezone.now().astimezone(pytz.utc)
|
||||||
|
send_notification_to_junior.delay(TASK_REJECTED, None, junior_details.auth.id,
|
||||||
|
{'task_id': instance.id})
|
||||||
instance.save()
|
instance.save()
|
||||||
junior_data.save()
|
junior_data.save()
|
||||||
return junior_details
|
return junior_details
|
||||||
|
|
||||||
|
class GuardianDetailListSerializer(serializers.ModelSerializer):
|
||||||
|
"""Guardian serializer"""
|
||||||
|
|
||||||
|
first_name = serializers.SerializerMethodField('get_first_name')
|
||||||
|
last_name = serializers.SerializerMethodField('get_last_name')
|
||||||
|
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', 'dob',
|
||||||
|
'guardian_code', 'gender', 'phone', 'country_name', 'created_at', 'guardian_code_status',
|
||||||
|
'updated_at']
|
||||||
|
|
||||||
|
def get_guardian_id(self,obj):
|
||||||
|
"""first name of guardian"""
|
||||||
|
return obj.guardian.id
|
||||||
|
def get_first_name(self,obj):
|
||||||
|
"""first name of guardian"""
|
||||||
|
return obj.guardian.user.first_name
|
||||||
|
|
||||||
|
def get_last_name(self,obj):
|
||||||
|
"""last name of guardian"""
|
||||||
|
return obj.guardian.user.last_name
|
||||||
|
|
||||||
|
def get_email(self,obj):
|
||||||
|
"""email of guardian"""
|
||||||
|
return obj.guardian.user.email
|
||||||
|
|
||||||
|
def get_image(self,obj):
|
||||||
|
"""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
|
||||||
|
|||||||
+4
-1
@@ -2,7 +2,8 @@
|
|||||||
"""Django import"""
|
"""Django import"""
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView,
|
from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView,
|
||||||
SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView, ApproveTaskAPIView)
|
SearchTaskListAPIView, TopJuniorListAPIView, ApproveJuniorAPIView, ApproveTaskAPIView,
|
||||||
|
GuardianListAPIView)
|
||||||
"""Third party import"""
|
"""Third party import"""
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
@@ -36,6 +37,8 @@ router.register('filter-task', SearchTaskListAPIView, basename='filter-task')
|
|||||||
router.register('approve-junior', ApproveJuniorAPIView, basename='approve-junior')
|
router.register('approve-junior', ApproveJuniorAPIView, basename='approve-junior')
|
||||||
# Approve junior API"""
|
# Approve junior API"""
|
||||||
router.register('approve-task', ApproveTaskAPIView, basename='approve-task')
|
router.register('approve-task', ApproveTaskAPIView, basename='approve-task')
|
||||||
|
# guardian list API"""
|
||||||
|
router.register('guardian-list', GuardianListAPIView, basename='guardian-list')
|
||||||
# Define Url pattern"""
|
# Define Url pattern"""
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('api/v1/', include(router.urls)),
|
path('api/v1/', include(router.urls)),
|
||||||
|
|||||||
+9
-4
@@ -11,7 +11,7 @@ import tempfile
|
|||||||
# Import date time module's function
|
# Import date time module's function
|
||||||
from datetime import datetime, time
|
from datetime import datetime, time
|
||||||
# import Number constant
|
# import Number constant
|
||||||
from base.constants import NUMBER, time_url
|
from base.constants import NUMBER
|
||||||
# Import Junior's model
|
# Import Junior's model
|
||||||
from junior.models import Junior, JuniorPoints
|
from junior.models import Junior, JuniorPoints
|
||||||
# Import guardian's model
|
# Import guardian's model
|
||||||
@@ -21,7 +21,9 @@ from zod_bank.celery import app
|
|||||||
# notification's constant
|
# notification's constant
|
||||||
from notifications.constants import REFERRAL_POINTS
|
from notifications.constants import REFERRAL_POINTS
|
||||||
# send notification function
|
# send notification function
|
||||||
from notifications.utils import send_notification
|
from notifications.utils import send_notification, send_notification_to_junior
|
||||||
|
|
||||||
|
|
||||||
# Define upload image on
|
# Define upload image on
|
||||||
# ali baba cloud
|
# ali baba cloud
|
||||||
# firstly save image
|
# firstly save image
|
||||||
@@ -41,7 +43,10 @@ def upload_image_to_alibaba(image, filename):
|
|||||||
# Save the image object to a temporary file
|
# Save the image object to a temporary file
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
||||||
"""write image in temporary file"""
|
"""write image in temporary file"""
|
||||||
temp_file.write(image.read())
|
if type(image) == bytes:
|
||||||
|
temp_file.write(image)
|
||||||
|
else:
|
||||||
|
temp_file.write(image.read())
|
||||||
"""auth of bucket"""
|
"""auth of bucket"""
|
||||||
auth = oss2.Auth(settings.ALIYUN_OSS_ACCESS_KEY_ID, settings.ALIYUN_OSS_ACCESS_KEY_SECRET)
|
auth = oss2.Auth(settings.ALIYUN_OSS_ACCESS_KEY_ID, settings.ALIYUN_OSS_ACCESS_KEY_SECRET)
|
||||||
"""fetch bucket details"""
|
"""fetch bucket details"""
|
||||||
@@ -89,7 +94,7 @@ def update_referral_points(referral_code, referral_code_used):
|
|||||||
junior_query.total_points = junior_query.total_points + NUMBER['five']
|
junior_query.total_points = junior_query.total_points + NUMBER['five']
|
||||||
junior_query.referral_points = junior_query.referral_points + NUMBER['five']
|
junior_query.referral_points = junior_query.referral_points + NUMBER['five']
|
||||||
junior_query.save()
|
junior_query.save()
|
||||||
send_notification.delay(REFERRAL_POINTS, None, junior_queryset.auth.id, {})
|
send_notification_to_junior.delay(REFERRAL_POINTS, None, junior_queryset.auth.id, {})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+74
-60
@@ -10,6 +10,8 @@ from rest_framework.permissions import IsAuthenticated
|
|||||||
from rest_framework import viewsets, status
|
from rest_framework import viewsets, status
|
||||||
from rest_framework.pagination import PageNumberPagination
|
from rest_framework.pagination import PageNumberPagination
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
from rest_framework.filters import SearchFilter
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
# Import guardian's model,
|
# Import guardian's model,
|
||||||
@@ -26,17 +28,18 @@ from django.utils import timezone
|
|||||||
# Import notification constant
|
# Import notification constant
|
||||||
# Import send_notification function
|
# Import send_notification function
|
||||||
from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer,
|
from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer,
|
||||||
TopJuniorSerializer, ApproveJuniorSerializer, ApproveTaskSerializer)
|
TopJuniorSerializer, ApproveJuniorSerializer, ApproveTaskSerializer,
|
||||||
|
GuardianDetailListSerializer)
|
||||||
from .models import Guardian, JuniorTask
|
from .models import Guardian, JuniorTask
|
||||||
from junior.models import Junior, JuniorPoints
|
from junior.models import Junior, JuniorPoints, JuniorGuardianRelationship
|
||||||
from account.models import UserEmailOtp, UserNotification
|
from account.models import UserEmailOtp, UserNotification
|
||||||
from .tasks import generate_otp
|
from .tasks import generate_otp
|
||||||
from account.utils import custom_response, custom_error_response, OTP_EXPIRY, send_otp_email
|
from account.utils import custom_response, custom_error_response, OTP_EXPIRY, send_otp_email
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
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 .utils import upload_image_to_alibaba
|
||||||
from notifications.constants import REGISTRATION, TASK_CREATED, LEADERBOARD_RANKING
|
from notifications.constants import REGISTRATION, TASK_ASSIGNED, LEADERBOARD_RANKING
|
||||||
from notifications.utils import send_notification
|
from notifications.utils import send_notification_to_junior
|
||||||
|
|
||||||
""" Define APIs """
|
""" Define APIs """
|
||||||
# Define Signup API,
|
# Define Signup API,
|
||||||
@@ -56,33 +59,27 @@ class SignupViewset(viewsets.ModelViewSet):
|
|||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
"""Create user profile"""
|
"""Create user profile"""
|
||||||
try:
|
if request.data['user_type'] in [str(NUMBER['one']), str(NUMBER['two'])]:
|
||||||
if request.data['user_type'] in [str(NUMBER['one']), str(NUMBER['two'])]:
|
serializer = UserSerializer(context=request.data['user_type'], data=request.data)
|
||||||
serializer = UserSerializer(context=request.data['user_type'], data=request.data)
|
if serializer.is_valid():
|
||||||
if serializer.is_valid():
|
user = serializer.save()
|
||||||
user = serializer.save()
|
"""Generate otp"""
|
||||||
"""Generate otp"""
|
otp = generate_otp()
|
||||||
otp = generate_otp()
|
# expire otp after 1 day
|
||||||
# expire otp after 1 day
|
expiry = OTP_EXPIRY
|
||||||
expiry = OTP_EXPIRY
|
# create user email otp object
|
||||||
# create user email otp object
|
UserEmailOtp.objects.create(email=request.data['email'], otp=otp,
|
||||||
UserEmailOtp.objects.create(email=request.data['email'], otp=otp,
|
user_type=str(request.data['user_type']), expired_at=expiry)
|
||||||
user_type=str(request.data['user_type']), expired_at=expiry)
|
"""Send email to the register user"""
|
||||||
"""Send email to the register user"""
|
send_otp_email(request.data['email'], otp)
|
||||||
send_otp_email(request.data['email'], otp)
|
return custom_response(SUCCESS_CODE['3001'],
|
||||||
# send push notification for registration
|
response_status=status.HTTP_200_OK)
|
||||||
send_notification.delay(REGISTRATION, None, user.id, {})
|
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
return custom_response(SUCCESS_CODE['3001'],
|
else:
|
||||||
response_status=status.HTTP_200_OK)
|
return custom_error_response(ERROR_CODE['2028'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
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)
|
|
||||||
|
|
||||||
class UpdateGuardianProfile(viewsets.ViewSet):
|
class UpdateGuardianProfile(viewsets.ViewSet):
|
||||||
"""Update guardian profile"""
|
"""Update guardian profile"""
|
||||||
queryset = Guardian.objects.all()
|
|
||||||
serializer_class = CreateGuardianSerializer
|
serializer_class = CreateGuardianSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
@@ -116,7 +113,6 @@ class UpdateGuardianProfile(viewsets.ViewSet):
|
|||||||
class AllTaskListAPIView(viewsets.ModelViewSet):
|
class AllTaskListAPIView(viewsets.ModelViewSet):
|
||||||
"""Update guardian profile"""
|
"""Update guardian profile"""
|
||||||
serializer_class = TaskDetailsSerializer
|
serializer_class = TaskDetailsSerializer
|
||||||
queryset = JuniorTask.objects.all()
|
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
@@ -126,38 +122,37 @@ class AllTaskListAPIView(viewsets.ModelViewSet):
|
|||||||
serializer = TaskDetailsSerializer(queryset, many=True)
|
serializer = TaskDetailsSerializer(queryset, many=True)
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class TaskListAPIView(viewsets.ModelViewSet):
|
class TaskListAPIView(viewsets.ModelViewSet):
|
||||||
"""Update guardian profile"""
|
"""Update guardian profile"""
|
||||||
serializer_class = TaskDetailsSerializer
|
serializer_class = TaskDetailsSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
filter_backends = (SearchFilter,)
|
||||||
|
search_fields = ['task_name', ]
|
||||||
pagination_class = PageNumberPagination
|
pagination_class = PageNumberPagination
|
||||||
queryset = JuniorTask.objects.all()
|
|
||||||
http_method_names = ('get',)
|
http_method_names = ('get',)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = JuniorTask.objects.filter(guardian__user=self.request.user
|
||||||
|
).prefetch_related('junior', 'junior__auth'
|
||||||
|
).order_by('due_date', 'created_at')
|
||||||
|
|
||||||
|
queryset = self.filter_queryset(queryset)
|
||||||
|
return queryset
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""Create guardian profile"""
|
"""Create guardian profile"""
|
||||||
try:
|
status_value = self.request.GET.get('status')
|
||||||
status_value = self.request.GET.get('status')
|
queryset = self.get_queryset()
|
||||||
search = self.request.GET.get('search')
|
if status_value and status_value != '0':
|
||||||
if search and str(status_value) == '0':
|
queryset = queryset.filter(task_status=status_value)
|
||||||
queryset = JuniorTask.objects.filter(guardian__user=request.user,
|
paginator = self.pagination_class()
|
||||||
task_name__icontains=search).order_by('due_date', 'created_at')
|
# use Pagination
|
||||||
elif search and str(status_value) != '0':
|
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||||
queryset = JuniorTask.objects.filter(guardian__user=request.user,task_name__icontains=search,
|
# use TaskDetailsSerializer serializer
|
||||||
task_status=status_value).order_by('due_date', 'created_at')
|
serializer = self.serializer_class(paginated_queryset, many=True)
|
||||||
if search is None and str(status_value) == '0':
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
queryset = JuniorTask.objects.filter(guardian__user=request.user).order_by('due_date', 'created_at')
|
|
||||||
elif search is None and str(status_value) != '0':
|
|
||||||
queryset = JuniorTask.objects.filter(guardian__user=request.user,
|
|
||||||
task_status=status_value).order_by('due_date','created_at')
|
|
||||||
paginator = self.pagination_class()
|
|
||||||
# use Pagination
|
|
||||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
|
||||||
# use TaskDetailsSerializer serializer
|
|
||||||
serializer = TaskDetailsSerializer(paginated_queryset, many=True)
|
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
|
||||||
except Exception as e:
|
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
class CreateTaskAPIView(viewsets.ModelViewSet):
|
class CreateTaskAPIView(viewsets.ModelViewSet):
|
||||||
"""create task for junior"""
|
"""create task for junior"""
|
||||||
@@ -189,9 +184,10 @@ class CreateTaskAPIView(viewsets.ModelViewSet):
|
|||||||
serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data)
|
serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
# save serializer
|
# save serializer
|
||||||
serializer.save()
|
task = serializer.save()
|
||||||
junior_id = Junior.objects.filter(id=junior).last()
|
junior_id = Junior.objects.filter(id=junior).last()
|
||||||
send_notification.delay(TASK_CREATED, None, junior_id.auth.id, {})
|
send_notification_to_junior.delay(TASK_ASSIGNED, request.auth.payload['user_id'],
|
||||||
|
junior_id.auth.id, {'task_id': task.id})
|
||||||
return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK)
|
||||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -227,9 +223,9 @@ class SearchTaskListAPIView(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class TopJuniorListAPIView(viewsets.ModelViewSet):
|
class TopJuniorListAPIView(viewsets.ModelViewSet):
|
||||||
"""Top juniors list"""
|
"""Top juniors list"""
|
||||||
|
queryset = JuniorPoints.objects.all()
|
||||||
serializer_class = TopJuniorSerializer
|
serializer_class = TopJuniorSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
queryset = JuniorPoints.objects.all()
|
|
||||||
|
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
# context list
|
# context list
|
||||||
@@ -241,14 +237,12 @@ class TopJuniorListAPIView(viewsets.ModelViewSet):
|
|||||||
"""Fetch junior list of those who complete their tasks"""
|
"""Fetch junior list of those who complete their tasks"""
|
||||||
try:
|
try:
|
||||||
junior_total_points = self.get_queryset().order_by('-total_points')
|
junior_total_points = self.get_queryset().order_by('-total_points')
|
||||||
|
|
||||||
# Update the position field for each JuniorPoints object
|
# Update the position field for each JuniorPoints object
|
||||||
for index, junior in enumerate(junior_total_points):
|
for index, junior in enumerate(junior_total_points):
|
||||||
junior.position = index + 1
|
junior.position = index + 1
|
||||||
send_notification.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {})
|
send_notification_to_junior.delay(LEADERBOARD_RANKING, None, junior.junior.auth.id, {})
|
||||||
junior.save()
|
junior.save()
|
||||||
|
serializer = self.get_serializer(junior_total_points[:NUMBER['fifteen']], many=True)
|
||||||
serializer = self.get_serializer(junior_total_points, many=True)
|
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
@@ -282,6 +276,7 @@ class ApproveJuniorAPIView(viewsets.ViewSet):
|
|||||||
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3023'], serializer.data, response_status=status.HTTP_200_OK)
|
||||||
else:
|
else:
|
||||||
queryset[1].guardian_code = None
|
queryset[1].guardian_code = None
|
||||||
|
queryset[1].guardian_code_status = str(NUMBER['one'])
|
||||||
queryset[1].save()
|
queryset[1].save()
|
||||||
return custom_response(SUCCESS_CODE['3024'], response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3024'], response_status=status.HTTP_200_OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -329,3 +324,22 @@ class ApproveTaskAPIView(viewsets.ViewSet):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
class GuardianListAPIView(viewsets.ModelViewSet):
|
||||||
|
"""Guardian list of assosicated junior"""
|
||||||
|
|
||||||
|
serializer_class = GuardianDetailListSerializer
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
http_method_names = ('get',)
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
""" junior list"""
|
||||||
|
try:
|
||||||
|
guardian_data = JuniorGuardianRelationship.objects.filter(junior__auth__email=self.request.user)
|
||||||
|
# fetch junior object
|
||||||
|
if guardian_data:
|
||||||
|
# use GuardianDetailListSerializer serializer
|
||||||
|
serializer = GuardianDetailListSerializer(guardian_data, many=True)
|
||||||
|
return custom_response(None, serializer.data, 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)
|
||||||
|
|||||||
+23
-1
@@ -2,8 +2,26 @@
|
|||||||
"""Third party Django app"""
|
"""Third party Django app"""
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
"""Import Django app"""
|
"""Import Django app"""
|
||||||
from .models import Junior, JuniorPoints, JuniorGuardianRelationship
|
from .models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle,
|
||||||
|
JuniorArticleCard)
|
||||||
# Register your models here.
|
# 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)
|
@admin.register(Junior)
|
||||||
class JuniorAdmin(admin.ModelAdmin):
|
class JuniorAdmin(admin.ModelAdmin):
|
||||||
"""Junior Admin"""
|
"""Junior Admin"""
|
||||||
@@ -27,3 +45,7 @@ class JuniorGuardianRelationshipAdmin(admin.ModelAdmin):
|
|||||||
"""Junior Admin"""
|
"""Junior Admin"""
|
||||||
list_display = ['guardian', 'junior', 'relationship']
|
list_display = ['guardian', 'junior', 'relationship']
|
||||||
|
|
||||||
|
@admin.register(JuniorArticlePoints)
|
||||||
|
class JuniorArticlePointsAdmin(admin.ModelAdmin):
|
||||||
|
"""Junior Admin"""
|
||||||
|
list_display = ['junior', 'article', 'question', 'submitted_answer', 'is_answer_correct']
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 4.2.2 on 2023-08-02 11:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('junior', '0017_juniorguardianrelationship'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='junior',
|
||||||
|
name='relationship',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='junior',
|
||||||
|
name='guardian_code_approved',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
+67
-2
@@ -6,10 +6,11 @@ from django.contrib.auth import get_user_model
|
|||||||
"""Import ArrayField"""
|
"""Import ArrayField"""
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
"""Import django app"""
|
"""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
|
# Import guardian's model
|
||||||
from guardian.models import Guardian
|
from guardian.models import Guardian
|
||||||
|
# Import web admin's model
|
||||||
|
from web_admin.models import SurveyOption, ArticleSurvey, Article, ArticleCard
|
||||||
"""Define User model"""
|
"""Define User model"""
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
@@ -71,6 +72,11 @@ class Junior(models.Model):
|
|||||||
passcode = models.IntegerField(null=True, blank=True, default=None)
|
passcode = models.IntegerField(null=True, blank=True, default=None)
|
||||||
# junior is verified or not"""
|
# junior is verified or not"""
|
||||||
is_verified = models.BooleanField(default=False)
|
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"""
|
# Profile created and updated time"""
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
@@ -135,3 +141,62 @@ class JuniorGuardianRelationship(models.Model):
|
|||||||
return f'{self.guardian.user}'
|
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}'
|
||||||
|
|||||||
+82
-28
@@ -1,5 +1,8 @@
|
|||||||
"""Serializer file for junior"""
|
"""Serializer file for junior"""
|
||||||
"""Import Django 3rd party app"""
|
# third party imports
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
# django imports
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
@@ -7,17 +10,18 @@ from datetime import datetime
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from rest_framework_simplejwt.tokens import RefreshToken
|
from rest_framework_simplejwt.tokens import RefreshToken
|
||||||
|
|
||||||
"""Import django app"""
|
# local imports
|
||||||
from account.utils import send_otp_email, generate_code
|
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 guardian.tasks import generate_otp
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||||
from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD
|
from base.constants import (PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED, NUMBER, JUN, ZOD, EXPIRED,
|
||||||
|
GUARDIAN_CODE_STATUS)
|
||||||
from guardian.models import Guardian, JuniorTask
|
from guardian.models import Guardian, JuniorTask
|
||||||
from account.models import UserEmailOtp, UserNotification
|
from account.models import UserEmailOtp, UserNotification
|
||||||
from junior.utils import junior_notification_email, junior_approval_mail
|
from junior.utils import junior_notification_email, junior_approval_mail
|
||||||
from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime
|
from guardian.utils import real_time, update_referral_points, convert_timedelta_into_datetime
|
||||||
from notifications.utils import send_notification
|
from notifications.utils import send_notification, send_notification_to_junior, send_notification_to_guardian
|
||||||
from notifications.constants import (INVITED_GUARDIAN, APPROVED_JUNIOR, SKIPPED_PROFILE_SETUP, TASK_ACTION,
|
from notifications.constants import (INVITED_GUARDIAN, APPROVED_JUNIOR, SKIPPED_PROFILE_SETUP, TASK_ACTION,
|
||||||
TASK_SUBMITTED)
|
TASK_SUBMITTED)
|
||||||
|
|
||||||
@@ -89,7 +93,13 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
|
|||||||
"""condition for guardian code"""
|
"""condition for guardian code"""
|
||||||
if guardian_code:
|
if guardian_code:
|
||||||
junior.guardian_code = guardian_code
|
junior.guardian_code = guardian_code
|
||||||
junior.dob = validated_data.get('dob',junior.dob)
|
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_to_guardian.delay(APPROVED_JUNIOR, junior.auth.id, guardian_data.user.id, {})
|
||||||
|
junior.dob = validated_data.get('dob', junior.dob)
|
||||||
junior.passcode = validated_data.get('passcode', junior.passcode)
|
junior.passcode = validated_data.get('passcode', junior.passcode)
|
||||||
junior.country_name = validated_data.get('country_name', junior.country_name)
|
junior.country_name = validated_data.get('country_name', junior.country_name)
|
||||||
"""Update country code and phone number"""
|
"""Update country code and phone number"""
|
||||||
@@ -136,8 +146,8 @@ class JuniorDetailSerializer(serializers.ModelSerializer):
|
|||||||
"""Meta info"""
|
"""Meta info"""
|
||||||
model = Junior
|
model = Junior
|
||||||
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
||||||
'guardian_code', 'is_invited', 'referral_code','is_active', 'is_complete_profile', 'created_at',
|
'guardian_code', 'image', 'is_invited', 'referral_code','is_active', 'is_complete_profile',
|
||||||
'image', 'updated_at']
|
'created_at', 'image', 'updated_at']
|
||||||
|
|
||||||
class JuniorDetailListSerializer(serializers.ModelSerializer):
|
class JuniorDetailListSerializer(serializers.ModelSerializer):
|
||||||
"""junior serializer"""
|
"""junior serializer"""
|
||||||
@@ -172,10 +182,11 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
|
|||||||
data = JuniorPoints.objects.filter(junior=obj).last()
|
data = JuniorPoints.objects.filter(junior=obj).last()
|
||||||
if data:
|
if data:
|
||||||
return data.position
|
return data.position
|
||||||
return 99999
|
|
||||||
def get_points(self, obj):
|
def get_points(self, obj):
|
||||||
data = sum(JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).values_list('points', flat=True))
|
data = JuniorPoints.objects.filter(junior=obj).last()
|
||||||
return data
|
if data:
|
||||||
|
return data.total_points
|
||||||
|
return NUMBER['zero']
|
||||||
|
|
||||||
def get_in_progress_task(self, obj):
|
def get_in_progress_task(self, obj):
|
||||||
data = JuniorTask.objects.filter(junior=obj, task_status=IN_PROGRESS).count()
|
data = JuniorTask.objects.filter(junior=obj, task_status=IN_PROGRESS).count()
|
||||||
@@ -200,10 +211,10 @@ class JuniorDetailListSerializer(serializers.ModelSerializer):
|
|||||||
class Meta(object):
|
class Meta(object):
|
||||||
"""Meta info"""
|
"""Meta info"""
|
||||||
model = Junior
|
model = Junior
|
||||||
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'country_name', 'phone', 'gender', 'dob',
|
||||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
||||||
'updated_at', 'assigned_task','points', 'pending_task', 'in_progress_task', 'completed_task',
|
'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):
|
class JuniorProfileSerializer(serializers.ModelSerializer):
|
||||||
"""junior serializer"""
|
"""junior serializer"""
|
||||||
@@ -246,15 +257,14 @@ class JuniorProfileSerializer(serializers.ModelSerializer):
|
|||||||
fields = ['id', 'email', 'first_name', 'last_name', 'country_name', 'country_code', 'phone', 'gender', 'dob',
|
fields = ['id', 'email', 'first_name', 'last_name', 'country_name', 'country_code', 'phone', 'gender', 'dob',
|
||||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
||||||
'updated_at', 'notification_count', 'total_count', 'complete_field_count', 'signup_method',
|
'updated_at', 'notification_count', 'total_count', 'complete_field_count', 'signup_method',
|
||||||
'is_invited', 'passcode']
|
'is_invited', 'passcode', 'guardian_code_approved']
|
||||||
|
|
||||||
class AddJuniorSerializer(serializers.ModelSerializer):
|
class AddJuniorSerializer(serializers.ModelSerializer):
|
||||||
"""Add junior serializer"""
|
"""Add junior serializer"""
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
"""Meta info"""
|
"""Meta info"""
|
||||||
model = Junior
|
model = Junior
|
||||||
fields = ['id', 'gender','dob', 'is_invited']
|
fields = ['id', 'gender', 'dob', 'is_invited']
|
||||||
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
@@ -263,6 +273,7 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
|||||||
email = self.context['email']
|
email = self.context['email']
|
||||||
guardian = self.context['user']
|
guardian = self.context['user']
|
||||||
relationship = self.context['relationship']
|
relationship = self.context['relationship']
|
||||||
|
profile_image = self.context['image']
|
||||||
full_name = self.context['first_name'] + ' ' + self.context['last_name']
|
full_name = self.context['first_name'] + ' ' + self.context['last_name']
|
||||||
guardian_data = Guardian.objects.filter(user__username=guardian).last()
|
guardian_data = Guardian.objects.filter(user__username=guardian).last()
|
||||||
user_data = User.objects.create(username=email, email=email,
|
user_data = User.objects.create(username=email, email=email,
|
||||||
@@ -272,14 +283,18 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
|||||||
user_data.set_password(password)
|
user_data.set_password(password)
|
||||||
user_data.save()
|
user_data.save()
|
||||||
junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'),
|
junior_data = Junior.objects.create(auth=user_data, gender=validated_data.get('gender'),
|
||||||
|
image=profile_image,
|
||||||
dob=validated_data.get('dob'), is_invited=True,
|
dob=validated_data.get('dob'), is_invited=True,
|
||||||
guardian_code=[guardian_data.guardian_code],
|
guardian_code=[guardian_data.guardian_code],
|
||||||
junior_code=generate_code(JUN, user_data.id),
|
junior_code=generate_code(JUN, user_data.id),
|
||||||
referral_code=generate_code(ZOD, user_data.id),
|
referral_code=generate_code(ZOD, user_data.id),
|
||||||
referral_code_used=guardian_data.referral_code,
|
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,
|
JuniorGuardianRelationship.objects.create(guardian=guardian_data, junior=junior_data,
|
||||||
relationship=relationship)
|
relationship=relationship)
|
||||||
|
total_junior = Junior.objects.all().count()
|
||||||
|
JuniorPoints.objects.create(junior=junior_data, position=total_junior)
|
||||||
"""Generate otp"""
|
"""Generate otp"""
|
||||||
otp_value = generate_otp()
|
otp_value = generate_otp()
|
||||||
expiry_time = timezone.now() + timezone.timedelta(days=1)
|
expiry_time = timezone.now() + timezone.timedelta(days=1)
|
||||||
@@ -289,9 +304,8 @@ class AddJuniorSerializer(serializers.ModelSerializer):
|
|||||||
UserNotification.objects.get_or_create(user=user_data)
|
UserNotification.objects.get_or_create(user=user_data)
|
||||||
"""Notification email"""
|
"""Notification email"""
|
||||||
junior_notification_email(email, full_name, email, password)
|
junior_notification_email(email, full_name, email, password)
|
||||||
junior_approval_mail(guardian, full_name)
|
|
||||||
# push notification
|
# push notification
|
||||||
send_notification.delay(SKIPPED_PROFILE_SETUP, None, junior_data.auth.id, {})
|
send_notification_to_junior.delay(SKIPPED_PROFILE_SETUP, None, junior_data.auth.id, {})
|
||||||
return junior_data
|
return junior_data
|
||||||
|
|
||||||
|
|
||||||
@@ -306,6 +320,7 @@ class RemoveJuniorSerializer(serializers.ModelSerializer):
|
|||||||
if instance:
|
if instance:
|
||||||
instance.is_invited = False
|
instance.is_invited = False
|
||||||
instance.guardian_code = '{}'
|
instance.guardian_code = '{}'
|
||||||
|
instance.guardian_code_status = str(NUMBER['one'])
|
||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -318,12 +333,14 @@ class CompleteTaskSerializer(serializers.ModelSerializer):
|
|||||||
fields = ('id', 'image')
|
fields = ('id', 'image')
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
instance.image = validated_data.get('image', instance.image)
|
instance.image = validated_data.get('image', instance.image)
|
||||||
instance.requested_on = real_time()
|
instance.requested_on = timezone.now().astimezone(pytz.utc)
|
||||||
instance.task_status = str(NUMBER['four'])
|
instance.task_status = str(NUMBER['four'])
|
||||||
instance.is_approved = False
|
instance.is_approved = False
|
||||||
instance.save()
|
instance.save()
|
||||||
send_notification.delay(TASK_SUBMITTED, None, instance.junior.auth.id, {})
|
send_notification_to_junior.delay(TASK_SUBMITTED, instance.guardian.user.id,
|
||||||
send_notification.delay(TASK_ACTION, None, instance.guardian.user.id, {})
|
instance.junior.auth.id, {'task_id': instance.id})
|
||||||
|
send_notification_to_guardian.delay(TASK_ACTION, instance.junior.auth.id,
|
||||||
|
instance.guardian.user.id, {'task_id': instance.id})
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
class JuniorPointsSerializer(serializers.ModelSerializer):
|
class JuniorPointsSerializer(serializers.ModelSerializer):
|
||||||
@@ -335,6 +352,7 @@ class JuniorPointsSerializer(serializers.ModelSerializer):
|
|||||||
requested_task = serializers.SerializerMethodField('get_requested_task')
|
requested_task = serializers.SerializerMethodField('get_requested_task')
|
||||||
rejected_task = serializers.SerializerMethodField('get_rejected_task')
|
rejected_task = serializers.SerializerMethodField('get_rejected_task')
|
||||||
pending_task = serializers.SerializerMethodField('get_pending_task')
|
pending_task = serializers.SerializerMethodField('get_pending_task')
|
||||||
|
expired_task = serializers.SerializerMethodField('get_expired_task')
|
||||||
position = serializers.SerializerMethodField('get_position')
|
position = serializers.SerializerMethodField('get_position')
|
||||||
|
|
||||||
def get_junior_id(self, obj):
|
def get_junior_id(self, obj):
|
||||||
@@ -370,11 +388,14 @@ class JuniorPointsSerializer(serializers.ModelSerializer):
|
|||||||
def get_pending_task(self, obj):
|
def get_pending_task(self, obj):
|
||||||
return JuniorTask.objects.filter(junior=obj.junior, task_status=PENDING).count()
|
return JuniorTask.objects.filter(junior=obj.junior, task_status=PENDING).count()
|
||||||
|
|
||||||
|
def get_expired_task(self, obj):
|
||||||
|
return JuniorTask.objects.filter(junior=obj.junior, task_status=EXPIRED).count()
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
"""Meta info"""
|
"""Meta info"""
|
||||||
model = Junior
|
model = Junior
|
||||||
fields = ['junior_id', 'total_points', 'position', 'pending_task', 'in_progress_task', 'completed_task',
|
fields = ['junior_id', 'total_points', 'position', 'pending_task', 'in_progress_task', 'completed_task',
|
||||||
'requested_task', 'rejected_task']
|
'requested_task', 'rejected_task', 'expired_task']
|
||||||
|
|
||||||
class AddGuardianSerializer(serializers.ModelSerializer):
|
class AddGuardianSerializer(serializers.ModelSerializer):
|
||||||
"""Add guardian serializer"""
|
"""Add guardian serializer"""
|
||||||
@@ -393,13 +414,15 @@ class AddGuardianSerializer(serializers.ModelSerializer):
|
|||||||
relationship = self.context['relationship']
|
relationship = self.context['relationship']
|
||||||
full_name = self.context['first_name'] + ' ' + self.context['last_name']
|
full_name = self.context['first_name'] + ' ' + self.context['last_name']
|
||||||
junior_data = Junior.objects.filter(auth__username=junior).last()
|
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()
|
instance = User.objects.filter(username=email).last()
|
||||||
if instance:
|
if instance:
|
||||||
guardian_data = Guardian.objects.filter(user=instance).update(is_invited=True,
|
guardian_data = Guardian.objects.filter(user=instance).update(is_invited=True,
|
||||||
referral_code=generate_code(ZOD,
|
referral_code=generate_code(ZOD,
|
||||||
instance.id),
|
instance.id),
|
||||||
referral_code_used=junior_data.referral_code,
|
referral_code_used=junior_data.referral_code,
|
||||||
is_verified=True)
|
is_verified=True)
|
||||||
UserNotification.objects.get_or_create(user=instance)
|
UserNotification.objects.get_or_create(user=instance)
|
||||||
return guardian_data
|
return guardian_data
|
||||||
else:
|
else:
|
||||||
@@ -427,8 +450,8 @@ class AddGuardianSerializer(serializers.ModelSerializer):
|
|||||||
"""Notification email"""
|
"""Notification email"""
|
||||||
junior_notification_email(email, full_name, email, password)
|
junior_notification_email(email, full_name, email, password)
|
||||||
junior_approval_mail(email, full_name)
|
junior_approval_mail(email, full_name)
|
||||||
send_notification.delay(INVITED_GUARDIAN, None, junior_data.auth.id, {})
|
send_notification_to_junior.delay(INVITED_GUARDIAN, guardian_data.user.id, junior_data.auth.id, {})
|
||||||
send_notification.delay(APPROVED_JUNIOR, None, guardian_data.user.id, {})
|
send_notification_to_guardian.delay(APPROVED_JUNIOR, junior_data.auth.id, guardian_data.user.id, {})
|
||||||
return guardian_data
|
return guardian_data
|
||||||
|
|
||||||
class StartTaskSerializer(serializers.ModelSerializer):
|
class StartTaskSerializer(serializers.ModelSerializer):
|
||||||
@@ -439,7 +462,10 @@ class StartTaskSerializer(serializers.ModelSerializer):
|
|||||||
""" remaining time to complete task"""
|
""" remaining time to complete task"""
|
||||||
due_date = datetime.combine(obj.due_date, datetime.max.time())
|
due_date = datetime.combine(obj.due_date, datetime.max.time())
|
||||||
# fetch real time
|
# fetch real time
|
||||||
real_datetime = real_time()
|
# real_datetime = real_time()
|
||||||
|
# new code
|
||||||
|
due_date = due_date.astimezone(pytz.utc)
|
||||||
|
real_datetime = timezone.now().astimezone(pytz.utc)
|
||||||
# Perform the subtraction
|
# Perform the subtraction
|
||||||
if due_date > real_datetime:
|
if due_date > real_datetime:
|
||||||
time_difference = due_date - real_datetime
|
time_difference = due_date - real_datetime
|
||||||
@@ -454,3 +480,31 @@ class StartTaskSerializer(serializers.ModelSerializer):
|
|||||||
instance.task_status = str(NUMBER['two'])
|
instance.task_status = str(NUMBER['two'])
|
||||||
instance.save()
|
instance.save()
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
class ReAssignTaskSerializer(serializers.ModelSerializer):
|
||||||
|
"""User task Serializer"""
|
||||||
|
class Meta(object):
|
||||||
|
"""Meta class"""
|
||||||
|
model = JuniorTask
|
||||||
|
fields = ('id', 'due_date')
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
instance.task_status = str(NUMBER['one'])
|
||||||
|
instance.due_date = validated_data.get('due_date')
|
||||||
|
instance.is_approved = False
|
||||||
|
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 = None
|
||||||
|
instance.guardian_code_status = str(NUMBER['one'])
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|||||||
+16
-2
@@ -4,7 +4,9 @@ from django.urls import path, include
|
|||||||
from .views import (UpdateJuniorProfile, ValidateGuardianCode, JuniorListAPIView, AddJuniorAPIView,
|
from .views import (UpdateJuniorProfile, ValidateGuardianCode, JuniorListAPIView, AddJuniorAPIView,
|
||||||
InvitedJuniorAPIView, FilterJuniorAPIView, RemoveJuniorAPIView, JuniorTaskListAPIView,
|
InvitedJuniorAPIView, FilterJuniorAPIView, RemoveJuniorAPIView, JuniorTaskListAPIView,
|
||||||
CompleteJuniorTaskAPIView, JuniorPointsListAPIView, ValidateReferralCode,
|
CompleteJuniorTaskAPIView, JuniorPointsListAPIView, ValidateReferralCode,
|
||||||
InviteGuardianAPIView, StartTaskAPIView)
|
InviteGuardianAPIView, StartTaskAPIView, ReAssignJuniorTaskAPIView, StartArticleAPIView,
|
||||||
|
StartAssessmentAPIView, CheckAnswerAPIView, CompleteArticleAPIView, ReadArticleCardAPIView,
|
||||||
|
CreateArticleCardAPIView, RemoveGuardianCodeAPIView)
|
||||||
"""Third party import"""
|
"""Third party import"""
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
@@ -41,10 +43,22 @@ router.register('junior-points', JuniorPointsListAPIView, basename='junior-point
|
|||||||
router.register('validate-referral-code', ValidateReferralCode, basename='validate-referral-code')
|
router.register('validate-referral-code', ValidateReferralCode, basename='validate-referral-code')
|
||||||
# invite guardian API"""
|
# invite guardian API"""
|
||||||
router.register('invite-guardian', InviteGuardianAPIView, basename='invite-guardian')
|
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"""
|
# Define url pattern"""
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('api/v1/', include(router.urls)),
|
path('api/v1/', include(router.urls)),
|
||||||
path('api/v1/remove-junior/', RemoveJuniorAPIView.as_view()),
|
path('api/v1/remove-junior/', RemoveJuniorAPIView.as_view()),
|
||||||
path('api/v1/complete-task/', CompleteJuniorTaskAPIView.as_view()),
|
path('api/v1/complete-task/', CompleteJuniorTaskAPIView.as_view()),
|
||||||
path('api/v1/start-task/', StartTaskAPIView.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()),
|
||||||
]
|
]
|
||||||
|
|||||||
+4
-3
@@ -4,6 +4,7 @@ from django.conf import settings
|
|||||||
"""Third party Django app"""
|
"""Third party Django app"""
|
||||||
from templated_email import send_templated_mail
|
from templated_email import send_templated_mail
|
||||||
from .models import JuniorPoints
|
from .models import JuniorPoints
|
||||||
|
from base.constants import NUMBER
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
# junior notification
|
# junior notification
|
||||||
# email for sending email
|
# email for sending email
|
||||||
@@ -50,11 +51,11 @@ def junior_approval_mail(guardian, full_name):
|
|||||||
def update_positions_based_on_points():
|
def update_positions_based_on_points():
|
||||||
"""Update position of the junior"""
|
"""Update position of the junior"""
|
||||||
# First, retrieve all the JuniorPoints instances ordered by total_points in descending order.
|
# 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.
|
# 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:
|
for junior_point in juniors_points:
|
||||||
junior_point.position = position
|
junior_point.position = position
|
||||||
junior_point.save()
|
junior_point.save()
|
||||||
position += 1
|
position += NUMBER['one']
|
||||||
|
|||||||
+244
-28
@@ -6,6 +6,7 @@ from rest_framework.permissions import IsAuthenticated
|
|||||||
from rest_framework.pagination import PageNumberPagination
|
from rest_framework.pagination import PageNumberPagination
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from rest_framework.filters import SearchFilter
|
from rest_framework.filters import SearchFilter
|
||||||
|
from django.db.models import F
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import requests
|
import requests
|
||||||
@@ -27,20 +28,25 @@ import requests
|
|||||||
# Import upload_image_to_alibaba
|
# Import upload_image_to_alibaba
|
||||||
# Import custom_response, custom_error_response
|
# Import custom_response, custom_error_response
|
||||||
# Import constants
|
# Import constants
|
||||||
from junior.models import Junior, JuniorPoints
|
from django.db.models import Sum
|
||||||
from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,\
|
from junior.models import (Junior, JuniorPoints, JuniorGuardianRelationship, JuniorArticlePoints, JuniorArticle,
|
||||||
|
JuniorArticleCard)
|
||||||
|
from .serializers import (CreateJuniorSerializer, JuniorDetailListSerializer, AddJuniorSerializer,
|
||||||
RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer,
|
RemoveJuniorSerializer, CompleteTaskSerializer, JuniorPointsSerializer,
|
||||||
AddGuardianSerializer, StartTaskSerializer)
|
AddGuardianSerializer, StartTaskSerializer, ReAssignTaskSerializer,
|
||||||
|
RemoveGuardianCodeSerializer)
|
||||||
from guardian.models import Guardian, JuniorTask
|
from guardian.models import Guardian, JuniorTask
|
||||||
from guardian.serializers import TaskDetailsSerializer
|
from guardian.serializers import TaskDetailsSerializer, TaskDetailsjuniorSerializer
|
||||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
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 account.utils import custom_response, custom_error_response
|
||||||
from guardian.utils import upload_image_to_alibaba
|
from guardian.utils import upload_image_to_alibaba
|
||||||
from .utils import update_positions_based_on_points
|
from .utils import update_positions_based_on_points
|
||||||
from notifications.utils import send_notification
|
from notifications.utils import send_notification, send_notification_to_junior
|
||||||
from notifications.constants import REMOVE_JUNIOR
|
from notifications.constants import REMOVE_JUNIOR
|
||||||
|
from web_admin.models import Article, ArticleSurvey, SurveyOption, ArticleCard
|
||||||
|
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleListSerializer,
|
||||||
|
StartAssessmentSerializer)
|
||||||
""" Define APIs """
|
""" Define APIs """
|
||||||
# Define validate guardian code API,
|
# Define validate guardian code API,
|
||||||
# update junior profile,
|
# update junior profile,
|
||||||
@@ -59,7 +65,6 @@ from notifications.constants import REMOVE_JUNIOR
|
|||||||
# Create your views here.
|
# Create your views here.
|
||||||
class UpdateJuniorProfile(viewsets.ViewSet):
|
class UpdateJuniorProfile(viewsets.ViewSet):
|
||||||
"""Update junior profile"""
|
"""Update junior profile"""
|
||||||
queryset = Junior.objects.all()
|
|
||||||
serializer_class = CreateJuniorSerializer
|
serializer_class = CreateJuniorSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
@@ -93,7 +98,6 @@ class UpdateJuniorProfile(viewsets.ViewSet):
|
|||||||
|
|
||||||
class ValidateGuardianCode(viewsets.ViewSet):
|
class ValidateGuardianCode(viewsets.ViewSet):
|
||||||
"""Check guardian code exist or not"""
|
"""Check guardian code exist or not"""
|
||||||
queryset = Guardian.objects.all()
|
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
@@ -144,7 +148,6 @@ class JuniorListAPIView(viewsets.ModelViewSet):
|
|||||||
|
|
||||||
class AddJuniorAPIView(viewsets.ModelViewSet):
|
class AddJuniorAPIView(viewsets.ModelViewSet):
|
||||||
"""Add Junior by guardian"""
|
"""Add Junior by guardian"""
|
||||||
queryset = Junior.objects.all()
|
|
||||||
serializer_class = AddJuniorSerializer
|
serializer_class = AddJuniorSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
http_method_names = ('post',)
|
http_method_names = ('post',)
|
||||||
@@ -152,8 +155,19 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
""" junior list"""
|
""" junior list"""
|
||||||
try:
|
try:
|
||||||
info_data = {'user': request.user, 'relationship': str(request.data['relationship']), 'email': request.data['email'], 'first_name': request.data['first_name'],
|
info_data = {'user': request.user, 'relationship': str(request.data['relationship']),
|
||||||
'last_name': request.data['last_name']}
|
'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():
|
if user := User.objects.filter(username=request.data['email']).first():
|
||||||
self.associate_guardian(user)
|
self.associate_guardian(user)
|
||||||
return custom_response(SUCCESS_CODE['3021'], response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3021'], response_status=status.HTTP_200_OK)
|
||||||
@@ -163,7 +177,7 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
# save serializer
|
# save serializer
|
||||||
serializer.save()
|
serializer.save()
|
||||||
return custom_response(SUCCESS_CODE['3021'], serializer.data, response_status=status.HTTP_200_OK)
|
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:
|
except Exception as e:
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@@ -171,7 +185,10 @@ class AddJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
junior = Junior.objects.filter(auth=user).first()
|
junior = Junior.objects.filter(auth=user).first()
|
||||||
guardian = Guardian.objects.filter(user=self.request.user).first()
|
guardian = Guardian.objects.filter(user=self.request.user).first()
|
||||||
junior.guardian_code = [guardian.guardian_code]
|
junior.guardian_code = [guardian.guardian_code]
|
||||||
|
junior.guardian_code_status = str(NUMBER['two'])
|
||||||
junior.save()
|
junior.save()
|
||||||
|
JuniorGuardianRelationship.objects.get_or_create(guardian=guardian, junior=junior,
|
||||||
|
relationship=str(self.request.data['relationship']))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@@ -179,7 +196,6 @@ class InvitedJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
"""Junior list of assosicated guardian"""
|
"""Junior list of assosicated guardian"""
|
||||||
|
|
||||||
serializer_class = JuniorDetailListSerializer
|
serializer_class = JuniorDetailListSerializer
|
||||||
queryset = Junior.objects.all()
|
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
pagination_class = PageNumberPagination
|
pagination_class = PageNumberPagination
|
||||||
http_method_names = ('get',)
|
http_method_names = ('get',)
|
||||||
@@ -209,7 +225,6 @@ class FilterJuniorAPIView(viewsets.ModelViewSet):
|
|||||||
serializer_class = JuniorDetailListSerializer
|
serializer_class = JuniorDetailListSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
pagination_class = PageNumberPagination
|
pagination_class = PageNumberPagination
|
||||||
queryset = Junior.objects.all()
|
|
||||||
http_method_names = ('get',)
|
http_method_names = ('get',)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
@@ -246,15 +261,15 @@ class RemoveJuniorAPIView(views.APIView):
|
|||||||
junior_id = self.request.GET.get('id')
|
junior_id = self.request.GET.get('id')
|
||||||
guardian = Guardian.objects.filter(user__email=self.request.user).last()
|
guardian = Guardian.objects.filter(user__email=self.request.user).last()
|
||||||
# fetch junior query
|
# fetch junior query
|
||||||
junior_queryset = Junior.objects.filter(id=junior_id, guardian_code__icontains=str(guardian.guardian_code),
|
junior_queryset = Junior.objects.filter(id=junior_id,
|
||||||
is_invited=True).last()
|
guardian_code__icontains=str(guardian.guardian_code)).last()
|
||||||
if junior_queryset:
|
if junior_queryset:
|
||||||
# use RemoveJuniorSerializer serializer
|
# use RemoveJuniorSerializer serializer
|
||||||
serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True)
|
serializer = RemoveJuniorSerializer(junior_queryset, data=request.data, partial=True)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
# save serializer
|
# save serializer
|
||||||
serializer.save()
|
serializer.save()
|
||||||
send_notification.delay(REMOVE_JUNIOR, None, junior_queryset.auth.id, {})
|
send_notification_to_junior.delay(REMOVE_JUNIOR, None, junior_queryset.auth.id, {})
|
||||||
return custom_response(SUCCESS_CODE['3022'], serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(SUCCESS_CODE['3022'], serializer.data, response_status=status.HTTP_200_OK)
|
||||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
else:
|
else:
|
||||||
@@ -265,10 +280,9 @@ class RemoveJuniorAPIView(views.APIView):
|
|||||||
|
|
||||||
class JuniorTaskListAPIView(viewsets.ModelViewSet):
|
class JuniorTaskListAPIView(viewsets.ModelViewSet):
|
||||||
"""Update guardian profile"""
|
"""Update guardian profile"""
|
||||||
serializer_class = TaskDetailsSerializer
|
serializer_class = TaskDetailsjuniorSerializer
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
pagination_class = PageNumberPagination
|
pagination_class = PageNumberPagination
|
||||||
queryset = JuniorTask.objects.all()
|
|
||||||
http_method_names = ('get',)
|
http_method_names = ('get',)
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
@@ -295,7 +309,7 @@ class JuniorTaskListAPIView(viewsets.ModelViewSet):
|
|||||||
# use Pagination
|
# use Pagination
|
||||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||||
# use TaskDetailsSerializer serializer
|
# use TaskDetailsSerializer serializer
|
||||||
serializer = TaskDetailsSerializer(paginated_queryset, many=True)
|
serializer = TaskDetailsjuniorSerializer(paginated_queryset, many=True)
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
@@ -320,7 +334,8 @@ class CompleteJuniorTaskAPIView(views.APIView):
|
|||||||
|
|
||||||
image_url = upload_image_to_alibaba(image, filename)
|
image_url = upload_image_to_alibaba(image, filename)
|
||||||
# fetch junior query
|
# fetch junior query
|
||||||
task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user).last()
|
task_queryset = JuniorTask.objects.filter(id=task_id, junior__auth__email=self.request.user
|
||||||
|
).select_related('guardian', 'junior').last()
|
||||||
if task_queryset:
|
if task_queryset:
|
||||||
# use CompleteTaskSerializer serializer
|
# use CompleteTaskSerializer serializer
|
||||||
if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]:
|
if task_queryset.task_status in [str(NUMBER['four']), str(NUMBER['five'])]:
|
||||||
@@ -343,16 +358,12 @@ class JuniorPointsListAPIView(viewsets.ModelViewSet):
|
|||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
http_method_names = ('get',)
|
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):
|
def list(self, request, *args, **kwargs):
|
||||||
"""profile view"""
|
"""profile view"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
queryset = self.get_queryset()
|
|
||||||
# update position of junior
|
|
||||||
update_positions_based_on_points()
|
update_positions_based_on_points()
|
||||||
|
queryset = JuniorPoints.objects.filter(junior__auth__email=self.request.user).last()
|
||||||
|
# update position of junior
|
||||||
serializer = JuniorPointsSerializer(queryset)
|
serializer = JuniorPointsSerializer(queryset)
|
||||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -434,3 +445,208 @@ class StartTaskAPIView(views.APIView):
|
|||||||
return custom_error_response(ERROR_CODE['2060'], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2060'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
class ReAssignJuniorTaskAPIView(views.APIView):
|
||||||
|
"""Update junior task API"""
|
||||||
|
serializer_class = ReAssignTaskSerializer
|
||||||
|
model = JuniorTask
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def put(self, request, format=None):
|
||||||
|
try:
|
||||||
|
task_id = self.request.data.get('task_id')
|
||||||
|
task_queryset = JuniorTask.objects.filter(id=task_id, guardian__user__email=self.request.user).last()
|
||||||
|
if task_queryset and task_queryset.task_status == str(NUMBER['six']):
|
||||||
|
# use StartTaskSerializer serializer
|
||||||
|
serializer = ReAssignTaskSerializer(task_queryset, data=request.data, partial=True)
|
||||||
|
if serializer.is_valid():
|
||||||
|
# save serializer
|
||||||
|
serializer.save()
|
||||||
|
return custom_response(SUCCESS_CODE['3036'], 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['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)
|
||||||
|
|||||||
+10
-10
@@ -3,7 +3,7 @@ notification constants file
|
|||||||
"""
|
"""
|
||||||
from base.constants import NUMBER
|
from base.constants import NUMBER
|
||||||
REGISTRATION = NUMBER['one']
|
REGISTRATION = NUMBER['one']
|
||||||
TASK_CREATED = NUMBER['two']
|
TASK_ASSIGNED = NUMBER['two']
|
||||||
INVITED_GUARDIAN = NUMBER['three']
|
INVITED_GUARDIAN = NUMBER['three']
|
||||||
APPROVED_JUNIOR = NUMBER['four']
|
APPROVED_JUNIOR = NUMBER['four']
|
||||||
REFERRAL_POINTS = NUMBER['five']
|
REFERRAL_POINTS = NUMBER['five']
|
||||||
@@ -21,17 +21,17 @@ NOTIFICATION_DICT = {
|
|||||||
"title": "Successfully registered!",
|
"title": "Successfully registered!",
|
||||||
"body": "You have registered successfully. Now login and complete your profile."
|
"body": "You have registered successfully. Now login and complete your profile."
|
||||||
},
|
},
|
||||||
TASK_CREATED: {
|
TASK_ASSIGNED: {
|
||||||
"title": "Task created!",
|
"title": "New task assigned !!",
|
||||||
"body": "Task created successfully."
|
"body": "{from_user} has assigned you a new task."
|
||||||
},
|
},
|
||||||
INVITED_GUARDIAN: {
|
INVITED_GUARDIAN: {
|
||||||
"title": "Invite guardian",
|
"title": "Invite guardian",
|
||||||
"body": "Invite guardian successfully"
|
"body": "Invite guardian successfully"
|
||||||
},
|
},
|
||||||
APPROVED_JUNIOR: {
|
APPROVED_JUNIOR: {
|
||||||
"title": "Approve junior",
|
"title": "Approve junior !",
|
||||||
"body": "You have request from junior to associate with you"
|
"body": "You have request from {from_user} to associate with you."
|
||||||
},
|
},
|
||||||
REFERRAL_POINTS: {
|
REFERRAL_POINTS: {
|
||||||
"title": "Earn Referral points",
|
"title": "Earn Referral points",
|
||||||
@@ -47,15 +47,15 @@ NOTIFICATION_DICT = {
|
|||||||
},
|
},
|
||||||
SKIPPED_PROFILE_SETUP: {
|
SKIPPED_PROFILE_SETUP: {
|
||||||
"title": "Skipped profile setup!",
|
"title": "Skipped profile setup!",
|
||||||
"body": "Your guardian has been setup your profile."
|
"body": "Your guardian {from_user} has setup your profile."
|
||||||
},
|
},
|
||||||
TASK_SUBMITTED: {
|
TASK_SUBMITTED: {
|
||||||
"title": "Task submitted!",
|
"title": "Task submitted!",
|
||||||
"body": "Your task has been submitted successfully."
|
"body": "Your task has been submitted successfully."
|
||||||
},
|
},
|
||||||
TASK_ACTION: {
|
TASK_ACTION: {
|
||||||
"title": "Task approval!",
|
"title": "Task completion approval!",
|
||||||
"body": "You have request for task approval."
|
"body": "You have request from {from_user} for task approval."
|
||||||
},
|
},
|
||||||
LEADERBOARD_RANKING: {
|
LEADERBOARD_RANKING: {
|
||||||
"title": "Leader board rank!",
|
"title": "Leader board rank!",
|
||||||
@@ -67,6 +67,6 @@ NOTIFICATION_DICT = {
|
|||||||
},
|
},
|
||||||
TEST_NOTIFICATION: {
|
TEST_NOTIFICATION: {
|
||||||
"title": "Test Notification",
|
"title": "Test Notification",
|
||||||
"body": "This notification is for testing purpose"
|
"body": "This notification is for testing purpose from {from_user}."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from rest_framework import serializers
|
|||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from notifications.utils import register_fcm_token
|
from notifications.utils import register_fcm_token
|
||||||
|
from notifications.models import Notification
|
||||||
|
|
||||||
|
|
||||||
class RegisterDevice(serializers.Serializer):
|
class RegisterDevice(serializers.Serializer):
|
||||||
@@ -26,3 +27,20 @@ class RegisterDevice(serializers.Serializer):
|
|||||||
device_type = validated_data['type']
|
device_type = validated_data['type']
|
||||||
return register_fcm_token(self.context['user_id'], registration_id,
|
return register_fcm_token(self.context['user_id'], registration_id,
|
||||||
validated_data['device_id'], device_type)
|
validated_data['device_id'], device_type)
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationListSerializer(serializers.ModelSerializer):
|
||||||
|
"""List of notification"""
|
||||||
|
|
||||||
|
class Meta(object):
|
||||||
|
"""meta info"""
|
||||||
|
model = Notification
|
||||||
|
fields = ['id', 'data', 'is_read', 'created_at']
|
||||||
|
|
||||||
|
|
||||||
|
class ReadNotificationSerializer(serializers.ModelSerializer):
|
||||||
|
"""User task Serializer"""
|
||||||
|
class Meta(object):
|
||||||
|
"""Meta class"""
|
||||||
|
model = Notification
|
||||||
|
fields = ('id',)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from django.urls import path, include
|
|||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from notifications.views import NotificationViewSet
|
from notifications.views import NotificationViewSet, ReadNotification
|
||||||
|
|
||||||
# initiate router
|
# initiate router
|
||||||
router = routers.SimpleRouter()
|
router = routers.SimpleRouter()
|
||||||
@@ -15,4 +15,5 @@ router.register('notifications', NotificationViewSet, basename='notifications')
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('api/v1/', include(router.urls)),
|
path('api/v1/', include(router.urls)),
|
||||||
|
path('api/v1/read-notification/', ReadNotification.as_view()),
|
||||||
]
|
]
|
||||||
|
|||||||
+67
-14
@@ -10,6 +10,9 @@ from firebase_admin.messaging import Message, Notification as FirebaseNotificati
|
|||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from account.models import UserNotification
|
from account.models import UserNotification
|
||||||
|
from account.utils import get_user_full_name
|
||||||
|
from guardian.models import Guardian
|
||||||
|
from junior.models import Junior
|
||||||
from notifications.constants import NOTIFICATION_DICT
|
from notifications.constants import NOTIFICATION_DICT
|
||||||
from notifications.models import Notification
|
from notifications.models import Notification
|
||||||
|
|
||||||
@@ -39,30 +42,80 @@ def remove_fcm_token(user_id: int, access_token: str, registration_id) -> None:
|
|||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
def get_basic_detail(notification_type, from_user_id, to_user_id):
|
def get_basic_detail(from_user_id, to_user_id):
|
||||||
""" used to get the basic details """
|
"""
|
||||||
notification_data = NOTIFICATION_DICT[notification_type]
|
used to get the basic details
|
||||||
|
"""
|
||||||
from_user = User.objects.get(id=from_user_id) if from_user_id else None
|
from_user = User.objects.get(id=from_user_id) if from_user_id else None
|
||||||
to_user = User.objects.get(id=to_user_id)
|
to_user = User.objects.get(id=to_user_id)
|
||||||
return notification_data, from_user, to_user
|
return from_user, to_user
|
||||||
|
|
||||||
|
|
||||||
@shared_task()
|
def get_notification_data(notification_type, from_user, to_user, extra_data):
|
||||||
def send_notification(notification_type, from_user_id, to_user_id, extra_data):
|
"""
|
||||||
""" used to send the push for the given notification type """
|
get notification and push data
|
||||||
(notification_data, from_user, to_user) = get_basic_detail(notification_type, from_user_id, to_user_id)
|
:param notification_type: notification_type
|
||||||
|
:param from_user: from_user obj
|
||||||
|
:param to_user: to_user obj
|
||||||
|
:param extra_data: any extra data provided
|
||||||
|
:return: notification and push data
|
||||||
|
"""
|
||||||
|
push_data = NOTIFICATION_DICT[notification_type].copy()
|
||||||
|
notification_data = push_data.copy()
|
||||||
|
notification_data['to_user'] = get_user_full_name(to_user)
|
||||||
|
if from_user:
|
||||||
|
from_user_name = get_user_full_name(from_user)
|
||||||
|
push_data['body'] = push_data['body'].format(from_user=from_user_name)
|
||||||
|
notification_data['body'] = notification_data['body'].format(from_user=from_user_name)
|
||||||
|
notification_data['from_user'] = from_user_name
|
||||||
|
|
||||||
|
notification_data.update(extra_data)
|
||||||
|
|
||||||
|
return notification_data, push_data
|
||||||
|
|
||||||
|
|
||||||
|
def send_notification(notification_type, from_user, to_user, extra_data):
|
||||||
|
"""
|
||||||
|
used to send the push for the given notification type
|
||||||
|
"""
|
||||||
|
# (from_user, to_user) = get_basic_detail(from_user_id, to_user_id)
|
||||||
|
notification_data, push_data = get_notification_data(notification_type, from_user, to_user, extra_data)
|
||||||
user_notification_type = UserNotification.objects.filter(user=to_user).first()
|
user_notification_type = UserNotification.objects.filter(user=to_user).first()
|
||||||
data = notification_data
|
notification_data.update({'badge': Notification.objects.filter(notification_to=to_user, is_read=False).count()})
|
||||||
Notification.objects.create(notification_type=notification_type, notification_from=from_user,
|
Notification.objects.create(notification_type=notification_type, notification_from=from_user,
|
||||||
notification_to=to_user, data=data)
|
notification_to=to_user, data=notification_data)
|
||||||
if user_notification_type.push_notification:
|
if user_notification_type.push_notification:
|
||||||
data.update({'badge': Notification.objects.filter(notification_to=to_user, is_read=False).count()})
|
send_push(to_user, push_data)
|
||||||
send_push(to_user, data)
|
|
||||||
|
|
||||||
|
|
||||||
def send_push(user, data):
|
def send_push(user, data):
|
||||||
""" used to send push notification to specific user """
|
""" used to send push notification to specific user """
|
||||||
notification_data = data.pop('data', None)
|
|
||||||
user.fcmdevice_set.filter(active=True).send_message(
|
user.fcmdevice_set.filter(active=True).send_message(
|
||||||
Message(notification=FirebaseNotification(data['title'], data['body']), data=notification_data)
|
Message(notification=FirebaseNotification(data['title'], data['body']), data=data)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task()
|
||||||
|
def send_notification_to_guardian(notification_type, from_user_id, to_user_id, extra_data):
|
||||||
|
from_user = None
|
||||||
|
if from_user_id:
|
||||||
|
from_user = Junior.objects.filter(auth_id=from_user_id).select_related('auth').first()
|
||||||
|
extra_data['from_user_image'] = from_user.image
|
||||||
|
from_user = from_user.auth
|
||||||
|
to_user = Guardian.objects.filter(user_id=to_user_id).select_related('user').first()
|
||||||
|
extra_data['to_user_image'] = to_user.image
|
||||||
|
send_notification(notification_type, from_user, to_user.user, extra_data)
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task()
|
||||||
|
def send_notification_to_junior(notification_type, from_user_id, to_user_id, extra_data):
|
||||||
|
from_user = None
|
||||||
|
if from_user_id:
|
||||||
|
from_user = Guardian.objects.filter(user_id=from_user_id).select_related('user').first()
|
||||||
|
extra_data['from_user_image'] = from_user.image
|
||||||
|
from_user = from_user.user
|
||||||
|
to_user = Junior.objects.filter(auth_id=to_user_id).select_related('auth').first()
|
||||||
|
extra_data['to_user_image'] = to_user.image
|
||||||
|
send_notification(notification_type, from_user, to_user.auth, extra_data)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+59
-8
@@ -3,24 +3,42 @@ notifications views file
|
|||||||
"""
|
"""
|
||||||
# django imports
|
# django imports
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from rest_framework import viewsets
|
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import viewsets, status, views
|
||||||
# local imports
|
# local imports
|
||||||
from account.utils import custom_response
|
from account.utils import custom_response, custom_error_response
|
||||||
from base.messages import SUCCESS_CODE
|
from base.messages import SUCCESS_CODE, ERROR_CODE
|
||||||
from notifications.constants import TEST_NOTIFICATION
|
from notifications.constants import TEST_NOTIFICATION
|
||||||
from notifications.serializers import RegisterDevice
|
# Import serializer
|
||||||
from notifications.utils import send_notification
|
from notifications.serializers import RegisterDevice, NotificationListSerializer, ReadNotificationSerializer
|
||||||
|
from notifications.utils import send_notification, send_notification_to_guardian, send_notification_to_junior
|
||||||
|
# Import model
|
||||||
|
from notifications.models import Notification
|
||||||
|
|
||||||
|
|
||||||
class NotificationViewSet(viewsets.GenericViewSet):
|
class NotificationViewSet(viewsets.GenericViewSet):
|
||||||
""" used to do the notification actions """
|
""" used to do the notification actions """
|
||||||
serializer_class = RegisterDevice
|
serializer_class = NotificationListSerializer
|
||||||
permission_classes = [IsAuthenticated, ]
|
permission_classes = [IsAuthenticated, ]
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs) -> Response:
|
||||||
|
""" list the notifications """
|
||||||
|
queryset = Notification.objects.filter(notification_to_id=request.auth.payload['user_id']
|
||||||
|
).select_related('notification_to').order_by('-id')
|
||||||
|
paginator = self.pagination_class()
|
||||||
|
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||||
|
serializer = self.serializer_class(paginated_queryset, many=True)
|
||||||
|
self.mark_notifications_as_read(serializer.data)
|
||||||
|
return custom_response(None, serializer.data)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mark_notifications_as_read(data):
|
||||||
|
""" used to mark notification queryset as read """
|
||||||
|
ids = [obj['id'] for obj in data]
|
||||||
|
Notification.objects.filter(id__in=ids).update(is_read=True)
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, url_path='device', url_name='device', serializer_class=RegisterDevice)
|
@action(methods=['post'], detail=False, url_path='device', url_name='device', serializer_class=RegisterDevice)
|
||||||
def fcm_registration(self, request):
|
def fcm_registration(self, request):
|
||||||
"""
|
"""
|
||||||
@@ -38,5 +56,38 @@ class NotificationViewSet(viewsets.GenericViewSet):
|
|||||||
to send test notification
|
to send test notification
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
send_notification.delay(TEST_NOTIFICATION, None, request.auth.payload['user_id'], {})
|
send_notification_to_guardian(TEST_NOTIFICATION, None, request.auth.payload['user_id'],
|
||||||
|
{'task_id': None})
|
||||||
|
send_notification_to_junior(TEST_NOTIFICATION, request.auth.payload['user_id'], None,
|
||||||
|
{'task_id': None})
|
||||||
return custom_response(SUCCESS_CODE["3000"])
|
return custom_response(SUCCESS_CODE["3000"])
|
||||||
|
|
||||||
|
@action(methods=['get'], detail=False, url_path='list', url_name='list',
|
||||||
|
serializer_class=NotificationListSerializer)
|
||||||
|
def notification_list(self, request):
|
||||||
|
"""
|
||||||
|
notification list
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
queryset = Notification.objects.filter(notification_to=request.user)
|
||||||
|
serializer = NotificationListSerializer(queryset, many=True)
|
||||||
|
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||||
|
except Exception as e:
|
||||||
|
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
class ReadNotification(views.APIView):
|
||||||
|
"""Update notification API"""
|
||||||
|
serializer_class = ReadNotificationSerializer
|
||||||
|
model = Notification
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def put(self, request, format=None):
|
||||||
|
try:
|
||||||
|
notification_id = self.request.data.get('notification_id')
|
||||||
|
notification_queryset = Notification.objects.filter(id__in=notification_id,
|
||||||
|
notification_to=self.request.user).update(is_read=True)
|
||||||
|
if notification_queryset:
|
||||||
|
return custom_response(SUCCESS_CODE['3039'], response_status=status.HTTP_200_OK)
|
||||||
|
except Exception as e:
|
||||||
|
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|||||||
+2
-2
@@ -49,7 +49,7 @@ class ArticleSurvey(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Return title"""
|
"""Return title"""
|
||||||
return f'{self.id} | {self.article}'
|
return f'{self.id} | {self.question}'
|
||||||
|
|
||||||
|
|
||||||
class SurveyOption(models.Model):
|
class SurveyOption(models.Model):
|
||||||
@@ -64,7 +64,7 @@ class SurveyOption(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Return title"""
|
"""Return title"""
|
||||||
return f'{self.id} | {self.survey}'
|
return f'{self.id} | {self.option}'
|
||||||
|
|
||||||
|
|
||||||
class DefaultArticleCardImage(models.Model):
|
class DefaultArticleCardImage(models.Model):
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
"""
|
||||||
|
web_admin analytics serializer file
|
||||||
|
"""
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from junior.models import JuniorPoints, Junior
|
||||||
|
|
||||||
|
|
||||||
|
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')
|
||||||
@@ -12,7 +12,7 @@ from base.messages import ERROR_CODE
|
|||||||
from guardian.utils import upload_image_to_alibaba
|
from guardian.utils import upload_image_to_alibaba
|
||||||
from web_admin.models import Article, ArticleCard, SurveyOption, ArticleSurvey, DefaultArticleCardImage
|
from web_admin.models import Article, ArticleCard, SurveyOption, ArticleSurvey, DefaultArticleCardImage
|
||||||
from web_admin.utils import pop_id, get_image_url
|
from web_admin.utils import pop_id, get_image_url
|
||||||
|
from junior.models import JuniorArticlePoints, JuniorArticle
|
||||||
USER = get_user_model()
|
USER = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
@@ -21,15 +21,15 @@ class ArticleCardSerializer(serializers.ModelSerializer):
|
|||||||
Article Card serializer
|
Article Card serializer
|
||||||
"""
|
"""
|
||||||
id = serializers.IntegerField(required=False)
|
id = serializers.IntegerField(required=False)
|
||||||
image = serializers.FileField(required=False)
|
image_name = serializers.CharField(required=False)
|
||||||
image_url = serializers.URLField(required=False)
|
image_url = serializers.CharField(required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""
|
"""
|
||||||
meta class
|
meta class
|
||||||
"""
|
"""
|
||||||
model = ArticleCard
|
model = ArticleCard
|
||||||
fields = ('id', 'title', 'description', 'image', 'image_url')
|
fields = ('id', 'title', 'description', 'image_name', 'image_url')
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
validated_data['image_url'] = get_image_url(validated_data)
|
validated_data['image_url'] = get_image_url(validated_data)
|
||||||
@@ -215,52 +215,120 @@ class DefaultArticleCardImageSerializer(serializers.ModelSerializer):
|
|||||||
card_image = DefaultArticleCardImage.objects.create(**validated_data)
|
card_image = DefaultArticleCardImage.objects.create(**validated_data)
|
||||||
return card_image
|
return card_image
|
||||||
|
|
||||||
|
class ArticleListSerializer(serializers.ModelSerializer):
|
||||||
class UserManagementListSerializer(serializers.ModelSerializer):
|
|
||||||
"""
|
"""
|
||||||
user management serializer
|
serializer for article API
|
||||||
"""
|
"""
|
||||||
name = serializers.SerializerMethodField()
|
article_cards = ArticleCardSerializer(many=True)
|
||||||
phone_number = serializers.SerializerMethodField()
|
article_survey = ArticleSurveySerializer(many=True)
|
||||||
user_type = serializers.SerializerMethodField()
|
total_points = serializers.SerializerMethodField('get_total_points')
|
||||||
|
is_completed = serializers.SerializerMethodField('get_is_completed')
|
||||||
|
|
||||||
class Meta:
|
class Meta(object):
|
||||||
"""
|
"""
|
||||||
meta class
|
meta class
|
||||||
"""
|
"""
|
||||||
model = USER
|
model = Article
|
||||||
fields = ('name', 'email', 'phone_number', 'user_type', 'is_active')
|
fields = ('id', 'title', 'description', 'article_cards', 'article_survey', 'total_points', 'is_completed')
|
||||||
|
|
||||||
@staticmethod
|
def get_total_points(self, obj):
|
||||||
def get_name(obj):
|
"""total points of article"""
|
||||||
"""
|
total_question = ArticleSurvey.objects.filter(article=obj).count()
|
||||||
:param obj: user object
|
return total_question * NUMBER['five']
|
||||||
:return: full name
|
|
||||||
"""
|
|
||||||
return (obj.first_name + obj.last_name) if obj.last_name else obj.first_name
|
|
||||||
|
|
||||||
@staticmethod
|
def get_is_completed(self, obj):
|
||||||
def get_phone_number(obj):
|
"""complete all question"""
|
||||||
"""
|
context_data = self.context.get('user')
|
||||||
:param obj: user object
|
junior_article = JuniorArticle.objects.filter(junior__auth=context_data, article=obj).last()
|
||||||
:return: user phone number
|
if junior_article:
|
||||||
"""
|
return junior_article.is_completed
|
||||||
if profile := obj.guardian_profile.all().first():
|
return False
|
||||||
return profile.phone
|
|
||||||
elif profile := obj.junior_profile.all().first():
|
|
||||||
return profile.phone
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
class ArticleQuestionSerializer(serializers.ModelSerializer):
|
||||||
def get_user_type(obj):
|
"""
|
||||||
|
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(object):
|
||||||
"""
|
"""
|
||||||
:param obj: user object
|
meta class
|
||||||
:return: user type
|
|
||||||
"""
|
"""
|
||||||
if obj.guardian_profile.all().first():
|
model = ArticleSurvey
|
||||||
return dict(USER_TYPE).get('2')
|
fields = ('id', 'question', 'options', 'points', 'is_attempt', 'correct_answer', 'attempted_answer')
|
||||||
elif obj.junior_profile.all().first():
|
|
||||||
return dict(USER_TYPE).get('1')
|
class StartAssessmentSerializer(serializers.ModelSerializer):
|
||||||
else:
|
"""
|
||||||
return None
|
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(object):
|
||||||
|
"""
|
||||||
|
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(object):
|
||||||
|
"""
|
||||||
|
meta class
|
||||||
|
"""
|
||||||
|
model = ArticleCard
|
||||||
|
fields = ('id', 'title', 'description', 'image_name', 'image_url', 'current_page')
|
||||||
|
|||||||
@@ -87,9 +87,9 @@ class AdminVerifyOTPSerializer(serializers.Serializer):
|
|||||||
# fetch email otp object of the user
|
# fetch email otp object of the user
|
||||||
user_otp_details = UserEmailOtp.objects.filter(email=email, otp=otp).last()
|
user_otp_details = UserEmailOtp.objects.filter(email=email, otp=otp).last()
|
||||||
if not user_otp_details:
|
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'):
|
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():
|
if user_otp_details.expired_at.replace(tzinfo=None) < datetime.utcnow():
|
||||||
raise serializers.ValidationError({'details': ERROR_CODE['2029']})
|
raise serializers.ValidationError({'details': ERROR_CODE['2029']})
|
||||||
user_otp_details.is_verified = True
|
user_otp_details.is_verified = True
|
||||||
|
|||||||
@@ -0,0 +1,298 @@
|
|||||||
|
"""
|
||||||
|
web_admin user_management serializers file
|
||||||
|
"""
|
||||||
|
# django imports
|
||||||
|
from rest_framework import serializers
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
from base.constants import USER_TYPE
|
||||||
|
# local imports
|
||||||
|
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||||
|
from guardian.models import Guardian
|
||||||
|
from junior.models import Junior
|
||||||
|
|
||||||
|
USER = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class UserManagementListSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
user management serializer
|
||||||
|
"""
|
||||||
|
name = serializers.SerializerMethodField()
|
||||||
|
country_code = serializers.SerializerMethodField()
|
||||||
|
phone = serializers.SerializerMethodField()
|
||||||
|
user_type = serializers.SerializerMethodField()
|
||||||
|
is_active = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""
|
||||||
|
meta class
|
||||||
|
"""
|
||||||
|
model = USER
|
||||||
|
fields = ('id', 'name', 'email', 'country_code', 'phone', 'user_type', 'is_active')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_name(obj):
|
||||||
|
"""
|
||||||
|
:param obj: user object
|
||||||
|
:return: full name
|
||||||
|
"""
|
||||||
|
return f"{obj.first_name} {obj.last_name}" if obj.last_name else obj.first_name
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_country_code(obj):
|
||||||
|
"""
|
||||||
|
:param obj: user object
|
||||||
|
:return: user phone number
|
||||||
|
"""
|
||||||
|
if profile := obj.guardian_profile.all().first():
|
||||||
|
return profile.country_code if profile.country_code else None
|
||||||
|
elif profile := obj.junior_profile.all().first():
|
||||||
|
return profile.country_code if profile.country_code else None
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_phone(obj):
|
||||||
|
"""
|
||||||
|
:param obj: user object
|
||||||
|
:return: user phone number
|
||||||
|
"""
|
||||||
|
if profile := obj.guardian_profile.all().first():
|
||||||
|
return profile.phone if profile.phone else None
|
||||||
|
elif profile := obj.junior_profile.all().first():
|
||||||
|
return profile.phone if profile.phone else None
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_user_type(obj):
|
||||||
|
"""
|
||||||
|
:param obj: user object
|
||||||
|
:return: user type
|
||||||
|
"""
|
||||||
|
if obj.guardian_profile.all().first():
|
||||||
|
return dict(USER_TYPE).get('2')
|
||||||
|
elif obj.junior_profile.all().first():
|
||||||
|
return dict(USER_TYPE).get('1')
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_is_active(obj):
|
||||||
|
"""
|
||||||
|
:param obj: user object
|
||||||
|
:return: user type
|
||||||
|
"""
|
||||||
|
if profile := obj.guardian_profile.all().first():
|
||||||
|
return profile.is_active
|
||||||
|
elif profile := obj.junior_profile.all().first():
|
||||||
|
return profile.is_active
|
||||||
|
else:
|
||||||
|
return obj.is_active
|
||||||
|
|
||||||
|
|
||||||
|
class GuardianSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
guardian serializer
|
||||||
|
"""
|
||||||
|
name = serializers.SerializerMethodField()
|
||||||
|
first_name = serializers.SerializerMethodField()
|
||||||
|
last_name = serializers.SerializerMethodField()
|
||||||
|
username = serializers.SerializerMethodField()
|
||||||
|
email = serializers.EmailField(required=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""
|
||||||
|
meta class
|
||||||
|
"""
|
||||||
|
model = Guardian
|
||||||
|
fields = ('id', 'name', 'first_name', 'last_name', 'username', 'dob', 'gender', 'country_code', 'phone',
|
||||||
|
'is_active', 'country_name', 'image', 'email')
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
"""
|
||||||
|
to validate request data
|
||||||
|
:return: validated attrs
|
||||||
|
"""
|
||||||
|
email = attrs.get('email')
|
||||||
|
phone = attrs.get('phone')
|
||||||
|
if USER.objects.filter(email=email).exclude(id=self.context.get('user_id')).exists():
|
||||||
|
raise serializers.ValidationError({'details': ERROR_CODE['2003']})
|
||||||
|
if Guardian.objects.filter(phone=phone).exclude(user__id=self.context.get('user_id')).exists():
|
||||||
|
raise serializers.ValidationError({'details': ERROR_CODE['2012']})
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
"""
|
||||||
|
to update user and its related profile
|
||||||
|
:param instance: user's guardian object
|
||||||
|
:param validated_data:
|
||||||
|
:return: guardian object
|
||||||
|
"""
|
||||||
|
instance.user.email = self.validated_data.get('email', instance.user.email)
|
||||||
|
instance.user.username = self.validated_data.get('email', instance.user.username)
|
||||||
|
instance.user.save()
|
||||||
|
instance.country_code = validated_data.get('country_code', instance.country_code)
|
||||||
|
instance.phone = validated_data.get('phone', instance.phone)
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_name(obj):
|
||||||
|
"""
|
||||||
|
:param obj: guardian object
|
||||||
|
:return: full name
|
||||||
|
"""
|
||||||
|
return f"{obj.user.first_name} {obj.user.last_name}" if obj.user.last_name else obj.user.first_name
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_first_name(obj):
|
||||||
|
"""
|
||||||
|
:param obj: guardian object
|
||||||
|
:return: first name
|
||||||
|
"""
|
||||||
|
return obj.user.first_name
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_last_name(obj):
|
||||||
|
"""
|
||||||
|
:param obj: guardian object
|
||||||
|
:return: last name
|
||||||
|
"""
|
||||||
|
return obj.user.last_name
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_username(obj):
|
||||||
|
"""
|
||||||
|
:param obj: guardian object
|
||||||
|
:return: email
|
||||||
|
"""
|
||||||
|
return obj.user.username
|
||||||
|
|
||||||
|
|
||||||
|
class JuniorSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
junior serializer
|
||||||
|
"""
|
||||||
|
name = serializers.SerializerMethodField()
|
||||||
|
first_name = serializers.SerializerMethodField()
|
||||||
|
last_name = serializers.SerializerMethodField()
|
||||||
|
username = serializers.SerializerMethodField()
|
||||||
|
email = serializers.EmailField(required=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""
|
||||||
|
meta class
|
||||||
|
"""
|
||||||
|
model = Junior
|
||||||
|
fields = ('id', 'name', 'first_name', 'last_name', 'username', 'dob', 'gender', 'country_code', 'phone',
|
||||||
|
'is_active', 'country_name', 'image', 'email')
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
"""
|
||||||
|
to validate request data
|
||||||
|
:return: validated attrs
|
||||||
|
"""
|
||||||
|
email = attrs.get('email')
|
||||||
|
phone = attrs.get('phone')
|
||||||
|
if email and USER.objects.filter(email=email).exclude(id=self.context.get('user_id')).exists():
|
||||||
|
raise serializers.ValidationError({'details': ERROR_CODE['2003']})
|
||||||
|
if phone and Junior.objects.filter(phone=phone).exclude(auth__id=self.context.get('user_id')).exists():
|
||||||
|
raise serializers.ValidationError({'details': ERROR_CODE['2012']})
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
"""
|
||||||
|
:param instance: user's junior object
|
||||||
|
:param validated_data: validated data
|
||||||
|
:return: instance
|
||||||
|
"""
|
||||||
|
instance.auth.email = self.validated_data.get('email', instance.auth.email)
|
||||||
|
instance.auth.username = self.validated_data.get('email', instance.auth.username)
|
||||||
|
instance.auth.save()
|
||||||
|
instance.country_code = validated_data.get('country_code', instance.country_code)
|
||||||
|
instance.phone = validated_data.get('phone', instance.phone)
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_username(obj):
|
||||||
|
"""
|
||||||
|
:param obj: junior object
|
||||||
|
:return: email
|
||||||
|
"""
|
||||||
|
return obj.auth.username
|
||||||
|
|
||||||
|
|
||||||
|
class UserManagementDetailSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
user management details serializer
|
||||||
|
"""
|
||||||
|
user_type = serializers.SerializerMethodField()
|
||||||
|
guardian_profile = GuardianSerializer(many=True)
|
||||||
|
junior_profile = JuniorSerializer(many=True)
|
||||||
|
associated_users = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""
|
||||||
|
meta class
|
||||||
|
"""
|
||||||
|
model = USER
|
||||||
|
fields = ('id', 'user_type', 'email', 'guardian_profile', 'junior_profile', 'associated_users')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_user_type(obj):
|
||||||
|
"""
|
||||||
|
:param obj: user object
|
||||||
|
:return: user type
|
||||||
|
"""
|
||||||
|
if obj.guardian_profile.all().first():
|
||||||
|
return dict(USER_TYPE).get('2')
|
||||||
|
elif obj.junior_profile.all().first():
|
||||||
|
return dict(USER_TYPE).get('1')
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_associated_users(obj):
|
||||||
|
"""
|
||||||
|
:param obj: user object
|
||||||
|
:return: associated user
|
||||||
|
"""
|
||||||
|
if profile := obj.guardian_profile.all().first():
|
||||||
|
if profile.guardian_code:
|
||||||
|
junior = Junior.objects.filter(guardian_code__contains=[profile.guardian_code], is_verified=True)
|
||||||
|
serializer = JuniorSerializer(junior, many=True)
|
||||||
|
return serializer.data
|
||||||
|
elif profile := obj.junior_profile.all().first():
|
||||||
|
if profile.guardian_code:
|
||||||
|
guardian = Guardian.objects.filter(guardian_code__in=profile.guardian_code, is_verified=True)
|
||||||
|
serializer = GuardianSerializer(guardian, many=True)
|
||||||
|
return serializer.data
|
||||||
|
else:
|
||||||
|
return None
|
||||||
+9
-2
@@ -6,15 +6,22 @@ from django.urls import path, include
|
|||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from web_admin.views.article import ArticleViewSet, DefaultArticleCardImagesViewSet, UserManagementViewSet
|
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.auth import ForgotAndResetPasswordViewSet
|
||||||
|
from web_admin.views.user_management import UserManagementViewSet
|
||||||
|
|
||||||
# initiate router
|
# initiate router
|
||||||
router = routers.SimpleRouter()
|
router = routers.SimpleRouter()
|
||||||
|
|
||||||
router.register('article', ArticleViewSet, basename='article')
|
router.register('article', ArticleViewSet, basename='article')
|
||||||
router.register('default-card-images', DefaultArticleCardImagesViewSet, basename='default-card-images')
|
router.register('default-card-images', DefaultArticleCardImagesViewSet, basename='default-card-images')
|
||||||
router.register('user', UserManagementViewSet, basename='user')
|
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
|
# forgot and reset password api for admin
|
||||||
router.register('admin', ForgotAndResetPasswordViewSet, basename='admin')
|
router.register('admin', ForgotAndResetPasswordViewSet, basename='admin')
|
||||||
|
|||||||
+17
-1
@@ -1,6 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
web_utils file
|
web_utils file
|
||||||
"""
|
"""
|
||||||
|
import base64
|
||||||
|
|
||||||
from base.constants import ARTICLE_CARD_IMAGE_FOLDER
|
from base.constants import ARTICLE_CARD_IMAGE_FOLDER
|
||||||
from guardian.utils import upload_image_to_alibaba
|
from guardian.utils import upload_image_to_alibaba
|
||||||
|
|
||||||
@@ -16,8 +18,22 @@ def pop_id(data):
|
|||||||
|
|
||||||
|
|
||||||
def get_image_url(data):
|
def get_image_url(data):
|
||||||
if 'image_url' in data:
|
"""
|
||||||
|
to get image url
|
||||||
|
:param data:
|
||||||
|
:return: image url
|
||||||
|
"""
|
||||||
|
if 'image_url' in data and 'http' in data['image_url']:
|
||||||
|
if 'image_name' in data:
|
||||||
|
data.pop('image_name')
|
||||||
return data['image_url']
|
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']
|
||||||
|
filename = f"{ARTICLE_CARD_IMAGE_FOLDER}/{image_name}"
|
||||||
|
# upload image on ali baba
|
||||||
|
image_url = upload_image_to_alibaba(base64_image, filename)
|
||||||
|
return image_url
|
||||||
elif 'image' in data and data['image'] is not None:
|
elif 'image' in data and data['image'] is not None:
|
||||||
image = data.pop('image')
|
image = data.pop('image')
|
||||||
filename = f"{ARTICLE_CARD_IMAGE_FOLDER}/{image.name}"
|
filename = f"{ARTICLE_CARD_IMAGE_FOLDER}/{image.name}"
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
"""
|
||||||
|
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
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
class AnalyticsViewSet(GenericViewSet):
|
||||||
|
"""
|
||||||
|
analytics api view
|
||||||
|
to get user report (active users, guardians and juniors counts)
|
||||||
|
to get new user sign up report
|
||||||
|
to get task report (completed, in-progress, requested and rejected tasks count)
|
||||||
|
to get junior leaderboard and ranking
|
||||||
|
"""
|
||||||
|
serializer_class = None
|
||||||
|
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: start_date: date format (yyyy-mm-dd)
|
||||||
|
:param request: 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'), DATE_FORMAT)
|
||||||
|
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
|
||||||
|
|
||||||
|
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: start_date: date format (yyyy-mm-dd)
|
||||||
|
:param request: 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'), DATE_FORMAT)
|
||||||
|
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
|
||||||
|
|
||||||
|
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 count for (completed, in-progress, requested and rejected) task
|
||||||
|
:param request: start_date: date format (yyyy-mm-dd)
|
||||||
|
:param request: 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'), DATE_FORMAT)
|
||||||
|
end_date = datetime.datetime.strptime(request.query_params.get('end_date'), DATE_FORMAT)
|
||||||
|
|
||||||
|
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):
|
||||||
|
"""
|
||||||
|
to get junior leaderboard and rank
|
||||||
|
:param request:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
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)
|
||||||
+43
-22
@@ -4,7 +4,7 @@ web_admin views file
|
|||||||
# django imports
|
# django imports
|
||||||
from rest_framework.viewsets import GenericViewSet, mixins
|
from rest_framework.viewsets import GenericViewSet, mixins
|
||||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
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.decorators import action
|
||||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
@@ -16,8 +16,8 @@ from base.messages import SUCCESS_CODE, ERROR_CODE
|
|||||||
from web_admin.models import Article, ArticleCard, ArticleSurvey, DefaultArticleCardImage
|
from web_admin.models import Article, ArticleCard, ArticleSurvey, DefaultArticleCardImage
|
||||||
from web_admin.permission import AdminPermission
|
from web_admin.permission import AdminPermission
|
||||||
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleCardSerializer,
|
from web_admin.serializers.article_serializer import (ArticleSerializer, ArticleCardSerializer,
|
||||||
DefaultArticleCardImageSerializer,
|
DefaultArticleCardImageSerializer, ArticleListSerializer,
|
||||||
UserManagementListSerializer)
|
ArticleCardlistSerializer)
|
||||||
|
|
||||||
USER = get_user_model()
|
USER = get_user_model()
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ class ArticleViewSet(GenericViewSet, mixins.CreateModelMixin, mixins.UpdateModel
|
|||||||
serializer_class = ArticleSerializer
|
serializer_class = ArticleSerializer
|
||||||
permission_classes = [IsAuthenticated, AdminPermission]
|
permission_classes = [IsAuthenticated, AdminPermission]
|
||||||
queryset = Article
|
queryset = Article
|
||||||
filter_backends = (OrderingFilter, SearchFilter,)
|
filter_backends = (SearchFilter,)
|
||||||
search_fields = ['title']
|
search_fields = ['title']
|
||||||
http_method_names = ['get', 'post', 'put', 'delete']
|
http_method_names = ['get', 'post', 'put', 'delete']
|
||||||
|
|
||||||
@@ -77,10 +77,11 @@ class ArticleViewSet(GenericViewSet, mixins.CreateModelMixin, mixins.UpdateModel
|
|||||||
:return: list of article
|
:return: list of article
|
||||||
"""
|
"""
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
|
count = queryset.count()
|
||||||
paginator = self.pagination_class()
|
paginator = self.pagination_class()
|
||||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||||
serializer = self.serializer_class(paginated_queryset, many=True)
|
serializer = self.serializer_class(paginated_queryset, many=True)
|
||||||
return custom_response(None, data=serializer.data)
|
return custom_response(None, data=serializer.data, count=count)
|
||||||
|
|
||||||
def retrieve(self, request, *args, **kwargs):
|
def retrieve(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -109,7 +110,7 @@ class ArticleViewSet(GenericViewSet, mixins.CreateModelMixin, mixins.UpdateModel
|
|||||||
return custom_response(SUCCESS_CODE["3029"])
|
return custom_response(SUCCESS_CODE["3029"])
|
||||||
return custom_error_response(ERROR_CODE["2041"], status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE["2041"], status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@action(methods=['get'], url_name='remove_card', url_path='remove_card',
|
@action(methods=['get'], url_name='remove-card', url_path='remove-card',
|
||||||
detail=True)
|
detail=True)
|
||||||
def remove_article_card(self, request, *args, **kwargs):
|
def remove_article_card(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -125,7 +126,7 @@ class ArticleViewSet(GenericViewSet, mixins.CreateModelMixin, mixins.UpdateModel
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
return custom_error_response(ERROR_CODE["2042"], response_status=status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE["2042"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@action(methods=['get'], url_name='remove_survey', url_path='remove_survey',
|
@action(methods=['get'], url_name='remove-survey', url_path='remove-survey',
|
||||||
detail=True)
|
detail=True)
|
||||||
def remove_article_survey(self, request, *args, **kwargs):
|
def remove_article_survey(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -195,30 +196,50 @@ class DefaultArticleCardImagesViewSet(GenericViewSet, mixins.CreateModelMixin, m
|
|||||||
return custom_response(None, data=serializer.data)
|
return custom_response(None, data=serializer.data)
|
||||||
|
|
||||||
|
|
||||||
class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin):
|
class ArticleListViewSet(GenericViewSet, mixins.ListModelMixin):
|
||||||
"""
|
"""
|
||||||
api to manage (list, view, edit) user
|
article api
|
||||||
"""
|
"""
|
||||||
serializer_class = UserManagementListSerializer
|
serializer_class = ArticleListSerializer
|
||||||
permission_classes = []
|
permission_classes = [IsAuthenticated,]
|
||||||
queryset = USER.objects.prefetch_related(
|
queryset = Article
|
||||||
'guardian_profile', 'junior_profile')
|
http_method_names = ['get',]
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'):
|
article = self.queryset.objects.filter(is_deleted=False).prefetch_related(
|
||||||
return self.queryset.filter(junior_profile__isnull=True)
|
'article_cards', 'article_survey', 'article_survey__options'
|
||||||
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'):
|
).order_by('-created_at')
|
||||||
return self.queryset.filter(guardian_profile__isnull=True)
|
queryset = self.filter_queryset(article)
|
||||||
else:
|
return queryset
|
||||||
return self.queryset
|
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
api method to list all the user
|
article list api method
|
||||||
:param request:
|
:param request:
|
||||||
:return:
|
:param args:
|
||||||
|
:param kwargs:
|
||||||
|
:return: list of article
|
||||||
"""
|
"""
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
serializer = self.serializer_class(queryset, many=True)
|
serializer = self.serializer_class(queryset, context={"user": request.user}, many=True)
|
||||||
return custom_response(None, data=serializer.data)
|
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)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class ForgotAndResetPasswordViewSet(GenericViewSet):
|
|||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
serializer.save()
|
serializer.save()
|
||||||
return custom_response(SUCCESS_CODE['3015'])
|
return custom_response(SUCCESS_CODE['3015'])
|
||||||
return custom_error_response(ERROR_CODE['2063'], status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2000'], status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@action(methods=['post'], url_name='verify-otp', url_path='verify-otp',
|
@action(methods=['post'], url_name='verify-otp', url_path='verify-otp',
|
||||||
detail=False, serializer_class=AdminVerifyOTPSerializer)
|
detail=False, serializer_class=AdminVerifyOTPSerializer)
|
||||||
@@ -45,7 +45,7 @@ class ForgotAndResetPasswordViewSet(GenericViewSet):
|
|||||||
serializer = self.serializer_class(data=request.data)
|
serializer = self.serializer_class(data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
return custom_response(SUCCESS_CODE['3011'])
|
return custom_response(SUCCESS_CODE['3011'])
|
||||||
return custom_error_response(ERROR_CODE['2063'], status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2008'], status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
@action(methods=['post'], url_name='create-password', url_path='create-password',
|
@action(methods=['post'], url_name='create-password', url_path='create-password',
|
||||||
detail=False, serializer_class=AdminCreatePasswordSerializer)
|
detail=False, serializer_class=AdminCreatePasswordSerializer)
|
||||||
@@ -59,5 +59,5 @@ class ForgotAndResetPasswordViewSet(GenericViewSet):
|
|||||||
user = USER.objects.filter(email=serializer.validated_data.get('email')).first()
|
user = USER.objects.filter(email=serializer.validated_data.get('email')).first()
|
||||||
user.set_password(serializer.validated_data.get('new_password'))
|
user.set_password(serializer.validated_data.get('new_password'))
|
||||||
user.save()
|
user.save()
|
||||||
return custom_response(SUCCESS_CODE['3007'])
|
return custom_response(SUCCESS_CODE['3006'])
|
||||||
return custom_error_response(ERROR_CODE['2064'], status.HTTP_400_BAD_REQUEST)
|
return custom_error_response(ERROR_CODE['2064'], status.HTTP_400_BAD_REQUEST)
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
"""
|
||||||
|
web_admin user_management 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.decorators import action
|
||||||
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
from account.utils import custom_response, custom_error_response
|
||||||
|
from base.constants import USER_TYPE
|
||||||
|
from base.messages import SUCCESS_CODE, ERROR_CODE
|
||||||
|
from web_admin.permission import AdminPermission
|
||||||
|
from web_admin.serializers.user_management_serializer import (UserManagementListSerializer,
|
||||||
|
UserManagementDetailSerializer, GuardianSerializer,
|
||||||
|
JuniorSerializer)
|
||||||
|
|
||||||
|
USER = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class UserManagementViewSet(GenericViewSet, mixins.ListModelMixin,
|
||||||
|
mixins.RetrieveModelMixin, mixins.UpdateModelMixin):
|
||||||
|
"""
|
||||||
|
api to manage (list, view, edit) user
|
||||||
|
"""
|
||||||
|
serializer_class = UserManagementListSerializer
|
||||||
|
permission_classes = [IsAuthenticated, AdminPermission]
|
||||||
|
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']
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'):
|
||||||
|
queryset = self.queryset.filter(junior_profile__isnull=True)
|
||||||
|
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'):
|
||||||
|
queryset = self.queryset.filter(guardian_profile__isnull=True)
|
||||||
|
else:
|
||||||
|
queryset = self.queryset
|
||||||
|
queryset = self.filter_queryset(queryset)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
api method to list all the user
|
||||||
|
:param request: user_type {'guardian' for Guardian list, 'junior' for Junior list}
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
queryset = self.get_queryset()
|
||||||
|
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=queryset.count())
|
||||||
|
|
||||||
|
def retrieve(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
to get details of single user
|
||||||
|
:param request: user_id along with
|
||||||
|
user_type {'guardian' for Guardian, 'junior' for Junior} mandatory
|
||||||
|
:return: user details
|
||||||
|
"""
|
||||||
|
if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]:
|
||||||
|
return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST)
|
||||||
|
queryset = self.queryset
|
||||||
|
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'):
|
||||||
|
queryset = queryset.filter(guardian_profile__user__id=kwargs['pk'])
|
||||||
|
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'):
|
||||||
|
queryset = queryset.filter(junior_profile__auth__id=kwargs['pk'])
|
||||||
|
serializer = UserManagementDetailSerializer(queryset, many=True)
|
||||||
|
return custom_response(None, data=serializer.data)
|
||||||
|
|
||||||
|
def partial_update(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
api method to update user detail (email, phone number)
|
||||||
|
:param request: user_id along with
|
||||||
|
user_type {'guardian' for Guardian, 'junior' for Junior} mandatory
|
||||||
|
:return: success message
|
||||||
|
"""
|
||||||
|
if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]:
|
||||||
|
return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST)
|
||||||
|
queryset = self.queryset
|
||||||
|
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'):
|
||||||
|
user_obj = queryset.filter(guardian_profile__user__id=kwargs['pk']).first()
|
||||||
|
serializer = GuardianSerializer(user_obj.guardian_profile.all().first(),
|
||||||
|
request.data, context={'user_id': kwargs['pk']})
|
||||||
|
|
||||||
|
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'):
|
||||||
|
user_obj = queryset.filter(junior_profile__auth__id=kwargs['pk']).first()
|
||||||
|
serializer = JuniorSerializer(user_obj.junior_profile.all().first(),
|
||||||
|
request.data, context={'user_id': kwargs['pk']})
|
||||||
|
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
serializer.save()
|
||||||
|
return custom_response(SUCCESS_CODE['3037'])
|
||||||
|
|
||||||
|
@action(methods=['get'], url_name='change-status', url_path='change-status', detail=True)
|
||||||
|
def change_status(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
api to change user status (mark as active or inactive)
|
||||||
|
:param request: user_id along with
|
||||||
|
user_type {'guardian' for Guardian, 'junior' for Junior} mandatory
|
||||||
|
:return: success message
|
||||||
|
"""
|
||||||
|
if self.request.query_params.get('user_type') not in [dict(USER_TYPE).get('1'), dict(USER_TYPE).get('2')]:
|
||||||
|
return custom_error_response(ERROR_CODE['2067'], status.HTTP_400_BAD_REQUEST)
|
||||||
|
queryset = self.queryset
|
||||||
|
if self.request.query_params.get('user_type') == dict(USER_TYPE).get('2'):
|
||||||
|
user_obj = queryset.filter(guardian_profile__user__id=kwargs['pk']).first()
|
||||||
|
obj = user_obj.guardian_profile.all().first()
|
||||||
|
obj.is_active = False if obj.is_active else True
|
||||||
|
obj.save()
|
||||||
|
elif self.request.query_params.get('user_type') == dict(USER_TYPE).get('1'):
|
||||||
|
user_obj = queryset.filter(junior_profile__auth__id=kwargs['pk']).first()
|
||||||
|
obj = user_obj.junior_profile.all().first()
|
||||||
|
obj.is_active = False if obj.is_active else True
|
||||||
|
obj.save()
|
||||||
|
return custom_response(SUCCESS_CODE['3038'])
|
||||||
@@ -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
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/3.0/topics/i18n/
|
# https://docs.djangoproject.com/en/3.0/topics/i18n/
|
||||||
|
|||||||
Reference in New Issue
Block a user