mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-25 13:49:40 +00:00
@ -13,28 +13,38 @@ from rest_framework.decorators import action
|
||||
from django.contrib.auth import authenticate, login
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
from guardian.utils import upload_image_to_alibaba
|
||||
from .utils import get_token
|
||||
|
||||
class GoogleSignInSerializer(serializers.Serializer):
|
||||
"""Google login Serializer"""
|
||||
email = serializers.EmailField()
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Create or update user model"""
|
||||
with transaction.atomic():
|
||||
if User.objects.filter(email__iexact=self.validated_data['email']).exists():
|
||||
return User.objects.get(email__iexact=self.validated_data['email'])
|
||||
class GoogleLoginSerializer(serializers.Serializer):
|
||||
access_token = serializers.CharField(max_length=5000, required=True)
|
||||
|
||||
class Meta:
|
||||
"""meta class"""
|
||||
fields = ('access_token',)
|
||||
|
||||
|
||||
class UpdateJuniorProfileImageSerializer(serializers.ModelSerializer):
|
||||
"""update junior image"""
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Junior
|
||||
fields = ['image']
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""update image """
|
||||
junior_image = validated_data.get('image', instance.image)
|
||||
instance.image = junior_image
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
if not User.objects.filter(email__iexact=self.validated_data['email']).exists():
|
||||
instance = User.objects.create(username=self.validated_data['email'],
|
||||
email=self.validated_data['email'])
|
||||
return instance
|
||||
|
||||
class UpdateGuardianImageSerializer(serializers.ModelSerializer):
|
||||
"""Reset Password after verification"""
|
||||
"""update guardian image"""
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Guardian
|
||||
fields = '__all__'
|
||||
fields = ['image']
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""update image """
|
||||
@ -42,21 +52,7 @@ class UpdateGuardianImageSerializer(serializers.ModelSerializer):
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
class UpdateJuniorProfileImageSerializer(serializers.ModelSerializer):
|
||||
"""Reset Password after verification"""
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Junior
|
||||
fields = '__all__'
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""update image """
|
||||
image = validated_data.get('image', instance.image)
|
||||
filename = f"images/{image.name}"
|
||||
image_url = upload_image_to_alibaba(image, filename)
|
||||
instance.image = image_url
|
||||
instance.save()
|
||||
return instance
|
||||
class ResetPasswordSerializer(serializers.Serializer):
|
||||
"""Reset Password after verification"""
|
||||
verification_code = serializers.CharField(max_length=10)
|
||||
@ -93,7 +89,7 @@ class ChangePasswordSerializer(serializers.Serializer):
|
||||
if self.context.password not in ('', None):
|
||||
if user.check_password(value):
|
||||
return value
|
||||
raise serializers.ValidationError({"details":ERROR_CODE['2015']})
|
||||
raise serializers.ValidationError(ERROR_CODE['2015'])
|
||||
def create(self, validated_data):
|
||||
new_password = validated_data.pop('new_password')
|
||||
current_password = validated_data.pop('current_password')
|
||||
@ -138,9 +134,13 @@ class GuardianSerializer(serializers.ModelSerializer):
|
||||
access_token = str(refresh.access_token)
|
||||
return access_token
|
||||
|
||||
|
||||
def get_user_type(self, obj):
|
||||
"""user type"""
|
||||
return GUARDIAN
|
||||
email_verified = UserEmailOtp.objects.filter(email=obj.user.username).last()
|
||||
if email_verified and email_verified.user_type != None:
|
||||
return email_verified.user_type
|
||||
return '2'
|
||||
|
||||
def get_auth(self, obj):
|
||||
"""user email address"""
|
||||
@ -157,8 +157,8 @@ class GuardianSerializer(serializers.ModelSerializer):
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Guardian
|
||||
fields = ['auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', 'gender', 'dob',
|
||||
'referral_code', 'is_active', 'is_complete_profile', 'passcode',
|
||||
fields = ['id', 'auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'family_name', 'gender', 'dob',
|
||||
'referral_code', 'is_active', 'is_complete_profile', 'passcode', 'image',
|
||||
'created_at', 'updated_at', 'user_type']
|
||||
|
||||
|
||||
@ -176,7 +176,10 @@ class JuniorSerializer(serializers.ModelSerializer):
|
||||
return access_token
|
||||
|
||||
def get_user_type(self, obj):
|
||||
return JUNIOR
|
||||
email_verified = UserEmailOtp.objects.filter(email=obj.auth.username).last()
|
||||
if email_verified and email_verified.user_type != None:
|
||||
return email_verified.user_type
|
||||
return '1'
|
||||
|
||||
def get_auth(self, obj):
|
||||
return obj.auth.username
|
||||
@ -190,8 +193,8 @@ class JuniorSerializer(serializers.ModelSerializer):
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Junior
|
||||
fields = ['auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at',
|
||||
fields = ['id', 'auth_token', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
||||
'updated_at', 'user_type']
|
||||
|
||||
class EmailVerificationSerializer(serializers.ModelSerializer):
|
||||
|
@ -5,16 +5,17 @@ from rest_framework.decorators import api_view
|
||||
"""Third party import"""
|
||||
from rest_framework import routers
|
||||
from .views import (UserLogin, SendPhoneOtp, UserPhoneVerification, UserEmailVerification, ReSendEmailOtp,
|
||||
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage)
|
||||
ForgotPasswordAPIView, ResetPasswordAPIView, ChangePasswordAPIView, UpdateProfileImage,
|
||||
GoogleLoginViewSet, SigninWithApple)
|
||||
"""Router"""
|
||||
router = routers.SimpleRouter()
|
||||
|
||||
"""API End points with router"""
|
||||
router.register('user', UserLogin, basename='user')
|
||||
router.register('admin', UserLogin, basename='admin')
|
||||
# router.register('google-login', GoogleLoginAPIViewset, basename='admin')
|
||||
router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp')
|
||||
router.register('user-phone-verification', UserPhoneVerification, basename='user-phone-verification')
|
||||
router.register('google-login', GoogleLoginViewSet, basename='admin')
|
||||
# router.register('send-phone-otp', SendPhoneOtp, basename='send-phone-otp')
|
||||
# router.register('user-phone-verification', UserPhoneVerification, basename='user-phone-verification')
|
||||
router.register('user-email-verification', UserEmailVerification, basename='user-email-verification')
|
||||
router.register('resend-email-otp', ReSendEmailOtp, basename='resend-email-otp')
|
||||
urlpatterns = [
|
||||
@ -22,5 +23,6 @@ urlpatterns = [
|
||||
path('api/v1/forgot-password/', ForgotPasswordAPIView.as_view()),
|
||||
path('api/v1/reset-password/', ResetPasswordAPIView.as_view()),
|
||||
path('api/v1/change-password/', ChangePasswordAPIView.as_view()),
|
||||
path('api/v1/update-profile-image/', UpdateProfileImage.as_view())
|
||||
path('api/v1/update-profile-image/', UpdateProfileImage.as_view()),
|
||||
path('api/v1/apple-login/', SigninWithApple.as_view(), name='signup_with_apple'),
|
||||
]
|
||||
|
@ -3,8 +3,13 @@
|
||||
from django.conf import settings
|
||||
from rest_framework import viewsets, status
|
||||
from rest_framework.response import Response
|
||||
|
||||
from templated_email import send_templated_mail
|
||||
import jwt
|
||||
from datetime import datetime
|
||||
from calendar import timegm
|
||||
from uuid import uuid4
|
||||
import secrets
|
||||
|
||||
def send_otp_email(recipient_email, otp):
|
||||
from_email = settings.EMAIL_FROM_ADDRESS
|
||||
recipient_list = [recipient_email]
|
||||
@ -36,3 +41,53 @@ def custom_error_response(detail, response_status):
|
||||
if not detail:
|
||||
detail = {}
|
||||
return Response({"error": detail, "status": "failed", "code": response_status})
|
||||
|
||||
|
||||
def get_user_data(attrs):
|
||||
"""
|
||||
used to decode token
|
||||
"""
|
||||
user_data = jwt.decode(jwt=attrs['token'], options={'verify_signature': False},
|
||||
algorithms=['RS256'])
|
||||
return user_data
|
||||
|
||||
|
||||
def generate_jwt_token(token_type: str, now_time: int, data: dict = dict):
|
||||
"""
|
||||
used to generate jwt token
|
||||
"""
|
||||
if type(data) == type:
|
||||
data = {}
|
||||
data.update({
|
||||
'token_type': token_type,
|
||||
'iss': 'your_site_url',
|
||||
'iat': timegm(datetime.utcnow().utctimetuple()),
|
||||
'jti': uuid4().hex
|
||||
})
|
||||
TOKEN_TYPE = ["access", "refresh"]
|
||||
if token_type == TOKEN_TYPE[1]:
|
||||
exp = now_time + settings.SIMPLE_JWT['REFRESH_TOKEN_LIFETIME']
|
||||
else:
|
||||
exp = now_time + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME']
|
||||
|
||||
data.update({
|
||||
"exp": timegm(exp.utctimetuple())
|
||||
})
|
||||
|
||||
|
||||
signing_key = secrets.token_hex(32)
|
||||
|
||||
return jwt.encode(payload=data, key=signing_key,
|
||||
algorithm='HS256')
|
||||
|
||||
|
||||
def get_token(data: dict = dict):
|
||||
""" create access and refresh token """
|
||||
now_time = datetime.utcnow()
|
||||
access = generate_jwt_token('access', now_time, data)
|
||||
refresh = generate_jwt_token('refresh', now_time, data)
|
||||
|
||||
return {
|
||||
'access': access,
|
||||
'refresh': refresh
|
||||
}
|
181
account/views.py
181
account/views.py
@ -1,7 +1,12 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from rest_framework import viewsets, status, views
|
||||
from rest_framework.decorators import action
|
||||
import random
|
||||
import logging
|
||||
from django.utils import timezone
|
||||
import jwt
|
||||
from guardian.utils import upload_image_to_alibaba
|
||||
from django.contrib.auth import authenticate, login
|
||||
from guardian.models import Guardian
|
||||
from junior.models import Junior
|
||||
@ -9,50 +14,145 @@ from account.models import UserProfile, UserPhoneOtp, UserEmailOtp
|
||||
from django.contrib.auth.models import User
|
||||
from .serializers import (SuperUserSerializer, GuardianSerializer, JuniorSerializer, EmailVerificationSerializer,
|
||||
ForgotPasswordSerializer, ResetPasswordSerializer, ChangePasswordSerializer,
|
||||
GoogleSignInSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer)
|
||||
GoogleLoginSerializer, UpdateGuardianImageSerializer, UpdateJuniorProfileImageSerializer)
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from guardian.tasks import generate_otp
|
||||
from django.conf import settings
|
||||
from account.utils import send_otp_email
|
||||
from account.utils import custom_response, custom_error_response
|
||||
from django.core.mail import EmailMessage
|
||||
from django.core.mail import send_mail
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from templated_email import send_templated_mail
|
||||
import google.oauth2.credentials
|
||||
import google.auth.transport.requests
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from .utils import get_token
|
||||
|
||||
|
||||
class GoogleLoginMixin:
|
||||
def google_login(self, request):
|
||||
access_token = request.data.get('access_token')
|
||||
user_type = request.data.get('user_type')
|
||||
if not access_token:
|
||||
return Response({'error': 'Access token is required.'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
# Validate the access token and obtain the user's email and name
|
||||
credentials = google.oauth2.credentials.Credentials.from_authorized_user_info(
|
||||
info={
|
||||
'access_token': access_token,
|
||||
'token_uri': 'https://oauth2.googleapis.com/token',
|
||||
'client_id': settings.GOOGLE_CLIENT_ID,
|
||||
'client_secret': settings.GOOGLE_CLIENT_SECRET,
|
||||
'refresh_token': None,
|
||||
}
|
||||
)
|
||||
user_info_endpoint = f'https://www.googleapis.com/oauth2/v3/userinfo?access_token={access_token}'
|
||||
headers = {'Authorization': f'Bearer {credentials.token}'}
|
||||
response = requests.get(user_info_endpoint, headers=headers)
|
||||
response.raise_for_status()
|
||||
user_info = response.json()
|
||||
email = user_info['email']
|
||||
first_name = user_info['given_name']
|
||||
last_name = user_info['family_name']
|
||||
profile_picture = user_info['picture']
|
||||
except Exception as e:
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# Check if the user exists in your database or create a new user
|
||||
# ...
|
||||
user_data = User.objects.filter(email__iexact=email)
|
||||
if user_data.exists():
|
||||
if str(user_type) == '1':
|
||||
junior_query = Junior.objects.filter(auth=user_data.last()).last()
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
if str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.filter(user=user_data.last()).last()
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
|
||||
if not User.objects.filter(email__iexact=email).exists():
|
||||
user_obj = User.objects.create(username=email, email=email, first_name=first_name, last_name=last_name)
|
||||
if str(user_type) == '1':
|
||||
junior_query = Junior.objects.create(auth=user_obj, is_verified=True, is_active=True,
|
||||
image=profile_picture)
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
if str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.create(user=user_obj, is_verified=True, is_active=True,
|
||||
image=profile_picture)
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
# Return a JSON response with the user's email and name
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class GoogleLoginViewSet(GoogleLoginMixin, viewsets.GenericViewSet):
|
||||
serializer_class = GoogleLoginSerializer
|
||||
|
||||
def create(self, request):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return self.google_login(request)
|
||||
|
||||
class SigninWithApple(views.APIView):
|
||||
"""This API is for sign in with Apple for app."""
|
||||
def post(self, request):
|
||||
token = request.data.get("access_token")
|
||||
user_type = request.data.get("user_type")
|
||||
if not token:
|
||||
return custom_error_response(ERROR_CODE['2027'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
try:
|
||||
decoded_data = jwt.decode(token, options={"verify_signature": False})
|
||||
user_data = {"email": decoded_data.get('email'), "username": decoded_data.get('email'), "is_active": True}
|
||||
if decoded_data.get("email"):
|
||||
try:
|
||||
user = User.objects.get(email=decoded_data.get("email"))
|
||||
if str(user_type) == '1':
|
||||
junior_query = Junior.objects.filter(auth=user).last()
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
if str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.filter(user=user).last()
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
|
||||
except User.DoesNotExist:
|
||||
user = User.objects.create(**user_data)
|
||||
if str(user_type) == '1':
|
||||
junior_query = Junior.objects.create(auth=user, is_verified=True, is_active=True)
|
||||
serializer = JuniorSerializer(junior_query)
|
||||
if str(user_type) == '2':
|
||||
guardian_query = Guardian.objects.create(user=user, is_verified=True, is_active=True)
|
||||
serializer = GuardianSerializer(guardian_query)
|
||||
return custom_response(SUCCESS_CODE['3003'], serializer.data,
|
||||
response_status=status.HTTP_200_OK)
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
return custom_error_response(str(e), response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
# class GoogleLoginAPIViewset(viewsets.ModelViewSet):
|
||||
# """Google Login"""
|
||||
# serializer_class = GoogleSignInSerializer
|
||||
#
|
||||
# def create(self, request, *args, **kwargs):
|
||||
# """
|
||||
# Override default behaviour of create method
|
||||
# """
|
||||
# provider_type = []
|
||||
# serializer = self.get_serializer(data=request.data)
|
||||
# if serializer.is_valid(raise_exception=True):
|
||||
# # provider = self.get_provider_view(request.data.get('provider'))
|
||||
# # if User is not authenticated then send error message
|
||||
# # if not provider.is_authenticated(request):
|
||||
# # return custom_error_response({}, status.HTTP_400_BAD_REQUEST)
|
||||
#
|
||||
# user = serializer.save()
|
||||
# if User.objects.filter(email__iexact=user.email).exists():
|
||||
# print("ppppppppppppp")
|
||||
# return custom_response(SUCCESS_CODE["3003"], response_status=status.HTTP_200_OK)
|
||||
# return custom_response(ERROR_CODE["2002"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class UpdateProfileImage(views.APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
def put(self, request, format=None):
|
||||
if request.data['user_type'] == '1':
|
||||
if str(request.data['user_type']) == '1':
|
||||
junior_query = Junior.objects.filter(auth=request.user).last()
|
||||
serializer = UpdateJuniorProfileImageSerializer(junior_query, data=request.data, partial=True)
|
||||
else:
|
||||
image = request.data['image']
|
||||
filename = f"images/{image.name}"
|
||||
image_url = upload_image_to_alibaba(image, filename)
|
||||
image_data = image_url
|
||||
serializer = UpdateJuniorProfileImageSerializer(junior_query,
|
||||
data={'image':image_data}, partial=True)
|
||||
if str(request.data['user_type']) == '2':
|
||||
guardian_query = Guardian.objects.filter(user=request.user).last()
|
||||
serializer = UpdateGuardianImageSerializer(guardian_query, data=request.data, partial=True)
|
||||
image = request.data['image']
|
||||
filename = f"images/{image.name}"
|
||||
image_url = upload_image_to_alibaba(image, filename)
|
||||
image_data = image_url
|
||||
serializer = UpdateGuardianImageSerializer(guardian_query,
|
||||
data={'image':image_data}, partial=True)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return custom_response(SUCCESS_CODE['3017'], serializer.data, response_status=status.HTTP_200_OK)
|
||||
@ -96,9 +196,15 @@ class ForgotPasswordAPIView(views.APIView):
|
||||
'verification_code': verification_code
|
||||
}
|
||||
)
|
||||
|
||||
expiry = timezone.now() + timezone.timedelta(days=1)
|
||||
user_data, created = UserEmailOtp.objects.get_or_create(email=email)
|
||||
if created:
|
||||
user_data.expired_at = expiry
|
||||
user_data.save()
|
||||
if user_data:
|
||||
user_data.otp = verification_code
|
||||
user_data.expired_at = expiry
|
||||
user_data.save()
|
||||
return custom_response(SUCCESS_CODE['3015'],
|
||||
response_status=status.HTTP_200_OK)
|
||||
@ -206,6 +312,15 @@ class UserEmailVerification(viewsets.ModelViewSet):
|
||||
email_data = UserEmailOtp.objects.filter(email=self.request.GET.get('email'),
|
||||
otp=self.request.GET.get('otp')).last()
|
||||
if email_data:
|
||||
input_datetime_str = str(email_data.expired_at)
|
||||
input_format = "%Y-%m-%d %H:%M:%S.%f%z"
|
||||
output_format = "%Y-%m-%d %H:%M:%S.%f"
|
||||
input_datetime = datetime.strptime(input_datetime_str, input_format)
|
||||
output_datetime_str = input_datetime.strftime(output_format)
|
||||
format_str = "%Y-%m-%d %H:%M:%S.%f"
|
||||
datetime_obj = datetime.strptime(output_datetime_str, format_str)
|
||||
if datetime.today() > datetime_obj:
|
||||
return custom_error_response(ERROR_CODE["2029"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
email_data.is_verified = True
|
||||
email_data.save()
|
||||
if email_data.user_type == '1':
|
||||
@ -229,12 +344,18 @@ class UserEmailVerification(viewsets.ModelViewSet):
|
||||
|
||||
class ReSendEmailOtp(viewsets.ModelViewSet):
|
||||
"""Send otp on phone"""
|
||||
serializer_class = EmailVerificationSerializer
|
||||
def create(self, request, *args, **kwargs):
|
||||
otp = generate_otp()
|
||||
if User.objects.filter(email=request.data['email']):
|
||||
expiry = timezone.now() + timezone.timedelta(days=1)
|
||||
email_data, created = UserEmailOtp.objects.get_or_create(email=request.data['email'])
|
||||
if created:
|
||||
email_data.expired_at = expiry
|
||||
email_data.save()
|
||||
if email_data:
|
||||
email_data.otp = otp
|
||||
email_data.expired_at = expiry
|
||||
email_data.save()
|
||||
send_otp_email(request.data['email'], otp)
|
||||
return custom_response(SUCCESS_CODE['3016'], response_status=status.HTTP_200_OK)
|
||||
|
@ -35,6 +35,20 @@ GENDERS = (
|
||||
('1', 'Male'),
|
||||
('2', 'Female')
|
||||
)
|
||||
TASK_STATUS = (
|
||||
('1', 'pending'),
|
||||
('2', 'in-progress'),
|
||||
('3', 'rejected'),
|
||||
('4', 'requested'),
|
||||
('5', 'completed')
|
||||
)
|
||||
|
||||
PENDING = 1
|
||||
IN_PROGRESS = 2
|
||||
REJECTED = 3
|
||||
REQUESTED = 4
|
||||
COMPLETED = 5
|
||||
TASK_POINTS = 5
|
||||
# duplicate name used defined in constant PROJECT_NAME
|
||||
PROJECT_NAME = 'Zod Bank'
|
||||
GUARDIAN = 'guardian'
|
||||
|
@ -45,11 +45,14 @@ ERROR_CODE = {
|
||||
"2019": "Either File extension or File size doesn't meet the requirements",
|
||||
"2020": "Enter valid mobile number",
|
||||
"2021": "Already register",
|
||||
"2022":"Invalid Guardian code",
|
||||
"2023":"Invalid user",
|
||||
"2024":"Email not verified",
|
||||
"2025":"Invalid input. Expected a list of strings.",
|
||||
"2026" : "New password should not same as old password"
|
||||
"2022": "Invalid Guardian code",
|
||||
"2023": "Invalid user",
|
||||
"2024": "Email not verified",
|
||||
"2025": "Invalid input. Expected a list of strings.",
|
||||
"2026": "New password should not same as old password",
|
||||
"2027": "data should contain `identityToken`",
|
||||
"2028": "You are not authorized person to sign up on this platform",
|
||||
"2029": "Validity of otp verification is expired"
|
||||
}
|
||||
SUCCESS_CODE = {
|
||||
# Success code for password
|
||||
@ -78,7 +81,8 @@ SUCCESS_CODE = {
|
||||
"3014": "Password has been updated successfully.",
|
||||
"3015": "Verification code sent on your email.",
|
||||
"3016": "Send otp on your Email successfully",
|
||||
"3017": "Profile image update successfully"
|
||||
"3017": "Profile image update successfully",
|
||||
"3018": "Task created successfully"
|
||||
}
|
||||
|
||||
STATUS_CODE_ERROR = {
|
||||
|
@ -2,7 +2,7 @@
|
||||
"""Third party Django app"""
|
||||
from django.contrib import admin
|
||||
"""Import Django app"""
|
||||
from .models import Guardian
|
||||
from .models import Guardian, JuniorTask
|
||||
# Register your models here.
|
||||
@admin.register(Guardian)
|
||||
class GuardianAdmin(admin.ModelAdmin):
|
||||
@ -12,3 +12,12 @@ class GuardianAdmin(admin.ModelAdmin):
|
||||
def __str__(self):
|
||||
"""Return email id"""
|
||||
return self.user__email
|
||||
|
||||
@admin.register(JuniorTask)
|
||||
class TaskAdmin(admin.ModelAdmin):
|
||||
"""Junior Admin"""
|
||||
list_display = ['id', 'task_name', 'task_status', 'junior', 'due_date', 'points', 'created_at', 'updated_at']
|
||||
|
||||
def __str__(self):
|
||||
"""Return email id"""
|
||||
return str(self.task_name) + str(self.points)
|
||||
|
36
guardian/migrations/0008_juniortask.py
Normal file
36
guardian/migrations/0008_juniortask.py
Normal file
@ -0,0 +1,36 @@
|
||||
# Generated by Django 4.2.2 on 2023-07-04 09:24
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('junior', '0006_alter_junior_country_name'),
|
||||
('guardian', '0007_alter_guardian_country_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='JuniorTask',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('task_name', models.CharField(max_length=100)),
|
||||
('task_description', models.CharField(max_length=500)),
|
||||
('points', models.IntegerField(default=5)),
|
||||
('due_date', models.DateField(blank=True, null=True)),
|
||||
('image', models.ImageField(blank=True, default=None, null=True, upload_to='')),
|
||||
('task_status', models.CharField(blank=True, choices=[('1', 'pending'), ('2', 'in-progress'), ('3', 'rejected'), ('4', 'requested'), ('5', 'completed')], default='pending', max_length=15, null=True)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('guardian', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='guardian', to='guardian.guardian', verbose_name='Guardian')),
|
||||
('junior', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='junior', to='junior.junior', verbose_name='Junior')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Junior Task',
|
||||
'db_table': 'junior_task',
|
||||
},
|
||||
),
|
||||
]
|
18
guardian/migrations/0009_alter_juniortask_image.py
Normal file
18
guardian/migrations/0009_alter_juniortask_image.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.2 on 2023-07-04 12:56
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('guardian', '0008_juniortask'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='juniortask',
|
||||
name='image',
|
||||
field=models.URLField(blank=True, default=None, null=True),
|
||||
),
|
||||
]
|
18
guardian/migrations/0010_alter_juniortask_task_status.py
Normal file
18
guardian/migrations/0010_alter_juniortask_task_status.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.2 on 2023-07-04 13:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('guardian', '0009_alter_juniortask_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='juniortask',
|
||||
name='task_status',
|
||||
field=models.CharField(choices=[('1', 'pending'), ('2', 'in-progress'), ('3', 'rejected'), ('4', 'requested'), ('5', 'completed')], default='pending', max_length=15),
|
||||
),
|
||||
]
|
@ -0,0 +1,28 @@
|
||||
# Generated by Django 4.2.2 on 2023-07-05 11:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('guardian', '0010_alter_juniortask_task_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='juniortask',
|
||||
name='default_image',
|
||||
field=models.ImageField(blank=True, default=None, null=True, upload_to=''),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='juniortask',
|
||||
name='is_approved',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='juniortask',
|
||||
name='task_status',
|
||||
field=models.CharField(choices=[('1', 'pending'), ('2', 'in-progress'), ('3', 'rejected'), ('4', 'requested'), ('5', 'completed')], default=1, max_length=15),
|
||||
),
|
||||
]
|
18
guardian/migrations/0012_alter_juniortask_default_image.py
Normal file
18
guardian/migrations/0012_alter_juniortask_default_image.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.2 on 2023-07-06 05:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('guardian', '0011_juniortask_default_image_juniortask_is_approved_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='juniortask',
|
||||
name='default_image',
|
||||
field=models.URLField(blank=True, default=None, null=True),
|
||||
),
|
||||
]
|
18
guardian/migrations/0013_alter_guardian_image.py
Normal file
18
guardian/migrations/0013_alter_guardian_image.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.2 on 2023-07-06 06:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('guardian', '0012_alter_juniortask_default_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='guardian',
|
||||
name='image',
|
||||
field=models.URLField(blank=True, default=None, null=True),
|
||||
),
|
||||
]
|
@ -3,7 +3,8 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth import get_user_model
|
||||
"""Import Django app"""
|
||||
from base.constants import GENDERS
|
||||
from base.constants import GENDERS, TASK_STATUS, PENDING, TASK_POINTS
|
||||
from junior.models import Junior
|
||||
User = get_user_model()
|
||||
# Create your models here.
|
||||
|
||||
@ -15,7 +16,7 @@ class Guardian(models.Model):
|
||||
phone = models.CharField(max_length=31, null=True, blank=True, default=None)
|
||||
country_name = models.CharField(max_length=100, null=True, blank=True, default=None)
|
||||
"""Image info"""
|
||||
image = models.ImageField(null=True, blank=True, default=None)
|
||||
image = models.URLField(null=True, blank=True, default=None)
|
||||
"""Personal info"""
|
||||
family_name = models.CharField(max_length=50, null=True, blank=True, default=None)
|
||||
gender = models.CharField(choices=GENDERS, max_length=15, null=True, blank=True, default=None)
|
||||
@ -41,3 +42,31 @@ class Guardian(models.Model):
|
||||
def __str__(self):
|
||||
"""Return email id"""
|
||||
return f'{self.user}'
|
||||
|
||||
class JuniorTask(models.Model):
|
||||
"""Guardian model"""
|
||||
guardian = models.ForeignKey(Guardian, on_delete=models.CASCADE, related_name='guardian', verbose_name='Guardian')
|
||||
task_name = models.CharField(max_length=100)
|
||||
task_description = models.CharField(max_length=500)
|
||||
points = models.IntegerField(default=TASK_POINTS)
|
||||
due_date = models.DateField(auto_now_add=False, null=True, blank=True)
|
||||
default_image = models.URLField(null=True, blank=True, default=None)
|
||||
image = models.URLField(null=True, blank=True, default=None)
|
||||
junior = models.ForeignKey(Junior, on_delete=models.CASCADE, related_name='junior', verbose_name='Junior')
|
||||
task_status = models.CharField(choices=TASK_STATUS, max_length=15, default=PENDING)
|
||||
is_active = models.BooleanField(default=True)
|
||||
is_approved = models.BooleanField(default=False)
|
||||
"""Profile created and updated time"""
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta(object):
|
||||
""" Meta class """
|
||||
db_table = 'junior_task'
|
||||
verbose_name = 'Junior Task'
|
||||
|
||||
def __str__(self):
|
||||
"""Return email id"""
|
||||
return f'{self.task_name}'
|
||||
|
||||
|
||||
|
@ -7,8 +7,10 @@ from rest_framework_simplejwt.tokens import RefreshToken
|
||||
from django.db import transaction
|
||||
from django.contrib.auth.models import User
|
||||
"""Import Django app"""
|
||||
from .models import Guardian
|
||||
from .models import Guardian, JuniorTask
|
||||
from account.models import UserProfile, UserEmailOtp
|
||||
from account.serializers import JuniorSerializer
|
||||
from junior.serializers import JuniorDetailSerializer
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from .utils import upload_image_to_alibaba
|
||||
from junior.models import Junior
|
||||
@ -134,3 +136,83 @@ class CreateGuardianSerializer(serializers.ModelSerializer):
|
||||
with transaction.atomic():
|
||||
instance = super().save(**kwargs)
|
||||
return instance
|
||||
|
||||
|
||||
|
||||
class TaskSerializer(serializers.ModelSerializer):
|
||||
class Meta(object):
|
||||
model = JuniorTask
|
||||
fields = ['task_name','task_description','points', 'due_date', 'junior', 'default_image']
|
||||
def create(self, validated_data):
|
||||
validated_data['guardian'] = Guardian.objects.filter(user=self.context['user']).last()
|
||||
images = self.context['image']
|
||||
validated_data['default_image'] = images
|
||||
instance = JuniorTask.objects.create(**validated_data)
|
||||
return instance
|
||||
|
||||
class GuardianDetailSerializer(serializers.ModelSerializer):
|
||||
"""junior serializer"""
|
||||
|
||||
email = serializers.SerializerMethodField('get_auth')
|
||||
first_name = serializers.SerializerMethodField('get_first_name')
|
||||
last_name = serializers.SerializerMethodField('get_last_name')
|
||||
|
||||
def get_auth(self, obj):
|
||||
"""user email address"""
|
||||
return obj.user.username
|
||||
|
||||
def get_first_name(self, obj):
|
||||
"""user first name"""
|
||||
return obj.user.first_name
|
||||
|
||||
def get_last_name(self, obj):
|
||||
"""user last name"""
|
||||
return obj.user.last_name
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Guardian
|
||||
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
||||
'updated_at']
|
||||
class TaskDetailsSerializer(serializers.ModelSerializer):
|
||||
|
||||
guardian = GuardianDetailSerializer()
|
||||
junior = JuniorDetailSerializer()
|
||||
class Meta(object):
|
||||
model = JuniorTask
|
||||
fields = ['id', 'guardian', 'task_name', 'task_description', 'points', 'due_date','default_image', 'image',
|
||||
'junior', 'task_status', 'is_active', 'created_at','updated_at']
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class TopJuniorSerializer(serializers.ModelSerializer):
|
||||
total_points = serializers.SerializerMethodField()
|
||||
|
||||
email = serializers.SerializerMethodField('get_auth')
|
||||
first_name = serializers.SerializerMethodField('get_first_name')
|
||||
last_name = serializers.SerializerMethodField('get_last_name')
|
||||
|
||||
def get_auth(self, obj):
|
||||
return obj.auth.username
|
||||
|
||||
def get_first_name(self, obj):
|
||||
return obj.auth.first_name
|
||||
|
||||
def get_last_name(self, obj):
|
||||
return obj.auth.last_name
|
||||
|
||||
class Meta:
|
||||
model = Junior
|
||||
fields = ['id', 'email', 'first_name', 'last_name', 'phone', 'country_code', 'country_name', 'gender', 'dob', 'image', 'junior_code', 'guardian_code', 'referral_code', 'referral_code_used', 'is_active', 'is_complete_profile', 'passcode', 'is_verified', 'created_at', 'updated_at', 'total_points']
|
||||
|
||||
def get_total_points(self, obj):
|
||||
junior_ids_with_total_points = self.context.get('junior_ids_with_total_points')
|
||||
if junior_ids_with_total_points:
|
||||
junior_id = obj.id
|
||||
for item in junior_ids_with_total_points:
|
||||
if item['junior'] == junior_id:
|
||||
return item['total_points']
|
||||
return 0
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
""" Urls files"""
|
||||
"""Django import"""
|
||||
from django.urls import path, include
|
||||
from .views import SignupViewset, UpdateGuardianProfile
|
||||
from .views import (SignupViewset, UpdateGuardianProfile, AllTaskListAPIView, CreateTaskAPIView, TaskListAPIView,
|
||||
SearchTaskListAPIView, TopJuniorListAPIView)
|
||||
"""Third party import"""
|
||||
from rest_framework import routers
|
||||
|
||||
@ -13,6 +14,16 @@ router = routers.SimpleRouter()
|
||||
router.register('sign-up', SignupViewset, basename='sign-up')
|
||||
"""Create guardian profile API"""
|
||||
router.register('create-guardian-profile', UpdateGuardianProfile, basename='update-guardian-profile')
|
||||
"""Create Task API"""
|
||||
router.register('create-task', CreateTaskAPIView, basename='create-task')
|
||||
"""All Task list API"""
|
||||
router.register('all-task-list', AllTaskListAPIView, basename='all-task-list')
|
||||
"""Task list bases on the status API"""
|
||||
router.register('task-list', TaskListAPIView, basename='task-list')
|
||||
"""Leaderboard API"""
|
||||
router.register('top-junior', TopJuniorListAPIView, basename='top-junior')
|
||||
"""Search Task list on the bases of status, due date, and task title API"""
|
||||
router.register('filter-task', SearchTaskListAPIView, basename='filter-task')
|
||||
"""Define Url pattern"""
|
||||
urlpatterns = [
|
||||
path('api/v1/', include(router.urls)),
|
||||
|
@ -10,4 +10,6 @@ def upload_image_to_alibaba(image, filename):
|
||||
bucket = oss2.Bucket(auth, settings.ALIYUN_OSS_ENDPOINT, settings.ALIYUN_OSS_BUCKET_NAME)
|
||||
# Upload the temporary file to Alibaba OSS
|
||||
bucket.put_object_from_file(filename, temp_file.name)
|
||||
return f"https://{settings.ALIYUN_OSS_BUCKET_NAME}.{settings.ALIYUN_OSS_ENDPOINT}/{filename}"
|
||||
new_filename = filename.replace(' ', '%20')
|
||||
return f"https://{settings.ALIYUN_OSS_BUCKET_NAME}.{settings.ALIYUN_OSS_ENDPOINT}/{new_filename}"
|
||||
|
||||
|
@ -2,33 +2,45 @@
|
||||
"""Third party Django app"""
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework import viewsets, status
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils import timezone
|
||||
from datetime import datetime, timedelta
|
||||
"""Import Django app"""
|
||||
from .serializers import UserSerializer, CreateGuardianSerializer
|
||||
from .models import Guardian
|
||||
from .serializers import (UserSerializer, CreateGuardianSerializer, TaskSerializer, TaskDetailsSerializer,
|
||||
TopJuniorSerializer)
|
||||
from .models import Guardian, JuniorTask
|
||||
from junior.models import Junior
|
||||
from junior.serializers import JuniorDetailSerializer
|
||||
from account.models import UserEmailOtp
|
||||
from .tasks import generate_otp
|
||||
from account.utils import send_otp_email
|
||||
from account.utils import custom_response, custom_error_response
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from .utils import upload_image_to_alibaba
|
||||
from django.db.models import Sum
|
||||
# Create your views here.
|
||||
class SignupViewset(viewsets.ModelViewSet):
|
||||
"""Signup view set"""
|
||||
serializer_class = UserSerializer
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""Create user profile"""
|
||||
serializer = UserSerializer(context=request.data['user_type'], data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
"""Generate otp"""
|
||||
otp = generate_otp()
|
||||
UserEmailOtp.objects.create(email=request.data['email'], otp=otp, user_type=str(request.data['user_type']))
|
||||
"""Send email to the register user"""
|
||||
send_otp_email(request.data['email'], otp)
|
||||
return custom_response(SUCCESS_CODE['3001'], {"email_otp": otp},
|
||||
response_status=status.HTTP_200_OK)
|
||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
if request.data['user_type'] in ['1', '2']:
|
||||
serializer = UserSerializer(context=request.data['user_type'], data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
"""Generate otp"""
|
||||
otp = generate_otp()
|
||||
expiry = timezone.now() + timezone.timedelta(days=1)
|
||||
UserEmailOtp.objects.create(email=request.data['email'], otp=otp,
|
||||
user_type=str(request.data['user_type']), expired_at=expiry)
|
||||
"""Send email to the register user"""
|
||||
send_otp_email(request.data['email'], otp)
|
||||
return custom_response(SUCCESS_CODE['3001'], {"email_otp": otp},
|
||||
response_status=status.HTTP_200_OK)
|
||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
else:
|
||||
return custom_error_response(ERROR_CODE['2028'], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class UpdateGuardianProfile(viewsets.ViewSet):
|
||||
"""Update guardian profile"""
|
||||
@ -46,3 +58,98 @@ class UpdateGuardianProfile(viewsets.ViewSet):
|
||||
serializer.save()
|
||||
return custom_response(None, serializer.data,response_status=status.HTTP_200_OK)
|
||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class AllTaskListAPIView(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
serializer_class = TaskDetailsSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""Create guardian profile"""
|
||||
queryset = JuniorTask.objects.filter(guardian__user=request.user)
|
||||
serializer = TaskDetailsSerializer(queryset, many=True)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
|
||||
class TaskListAPIView(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
serializer_class = TaskDetailsSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
pagination_class = PageNumberPagination
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""Create guardian profile"""
|
||||
status_value = self.request.GET.get('status')
|
||||
if status_value == 0:
|
||||
queryset = JuniorTask.objects.filter(guardian__user=request.user).order_by('created_at')
|
||||
else:
|
||||
queryset = JuniorTask.objects.filter(guardian__user=request.user,
|
||||
task_status=status_value).order_by('due_date','created_at')
|
||||
paginator = self.pagination_class()
|
||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||
serializer = TaskDetailsSerializer(paginated_queryset, many=True)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
|
||||
class CreateTaskAPIView(viewsets.ModelViewSet):
|
||||
"""create task for junior"""
|
||||
serializer_class = TaskSerializer
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
image = request.data['default_image']
|
||||
data = request.data
|
||||
if 'https' in str(image):
|
||||
image_data = image
|
||||
else:
|
||||
filename = f"images/{image}"
|
||||
image_url = upload_image_to_alibaba(image, filename)
|
||||
image_data = image_url
|
||||
data.pop('default_image')
|
||||
serializer = TaskSerializer(context={"user":request.user, "image":image_data}, data=data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return custom_response(SUCCESS_CODE['3018'], serializer.data, response_status=status.HTTP_200_OK)
|
||||
return custom_error_response(serializer.errors, response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class SearchTaskListAPIView(viewsets.ModelViewSet):
|
||||
"""Update guardian profile"""
|
||||
serializer_class = TaskDetailsSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
pagination_class = PageNumberPagination
|
||||
|
||||
def get_queryset(self):
|
||||
"""Get the queryset for the view"""
|
||||
title = self.request.GET.get('title')
|
||||
junior_queryset = JuniorTask.objects.filter(guardian__user=self.request.user, task_name__icontains=title)\
|
||||
.order_by('due_date', 'created_at')
|
||||
return junior_queryset
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""Create guardian profile"""
|
||||
queryset = self.get_queryset()
|
||||
|
||||
paginator = self.pagination_class()
|
||||
paginated_queryset = paginator.paginate_queryset(queryset, request)
|
||||
|
||||
serializer = TaskDetailsSerializer(paginated_queryset, many=True)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
|
||||
class TopJuniorListAPIView(viewsets.ModelViewSet):
|
||||
"""Top juniors list"""
|
||||
serializer_class = TopJuniorSerializer
|
||||
# permission_classes = [IsAuthenticated]
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
"""fetch junior list those complete their task"""
|
||||
junior_ids_with_total_points = JuniorTask.objects.filter(task_status=1) \
|
||||
.values('junior') \
|
||||
.annotate(total_points=Sum('points')) \
|
||||
.order_by('-total_points')
|
||||
|
||||
junior_ids = [item['junior'] for item in junior_ids_with_total_points]
|
||||
|
||||
juniors = Junior.objects.filter(id__in=junior_ids)
|
||||
|
||||
serializer = self.get_serializer(juniors, many=True, context={'junior_ids_with_total_points':
|
||||
junior_ids_with_total_points})
|
||||
return custom_response(serializer.data, response_status=status.HTTP_200_OK)
|
||||
|
||||
|
18
junior/migrations/0007_alter_junior_image.py
Normal file
18
junior/migrations/0007_alter_junior_image.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.2 on 2023-07-06 12:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('junior', '0006_alter_junior_country_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='junior',
|
||||
name='image',
|
||||
field=models.URLField(blank=True, default=None, null=True),
|
||||
),
|
||||
]
|
@ -18,7 +18,7 @@ class Junior(models.Model):
|
||||
"""Personal info"""
|
||||
gender = models.CharField(max_length=10, choices=GENDERS, null=True, blank=True, default=None)
|
||||
dob = models.DateField(max_length=15, null=True, blank=True, default=None)
|
||||
image = models.ImageField(null=True, blank=True, default=None)
|
||||
image = models.URLField(null=True, blank=True, default=None)
|
||||
"""Codes"""
|
||||
junior_code = models.CharField(max_length=10, null=True, blank=True, default=None)
|
||||
guardian_code = ArrayField(models.CharField(max_length=10, null=True, blank=True, default=None),null=True)
|
||||
|
@ -8,7 +8,8 @@ import random
|
||||
from junior.models import Junior
|
||||
from guardian.utils import upload_image_to_alibaba
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from guardian.models import Guardian
|
||||
from guardian.models import Guardian, JuniorTask
|
||||
from base.constants import PENDING, IN_PROGRESS, REJECTED, REQUESTED, COMPLETED
|
||||
|
||||
class ListCharField(serializers.ListField):
|
||||
"""Serializer for Array field"""
|
||||
@ -59,11 +60,7 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
|
||||
def create(self, validated_data):
|
||||
"""Create junior profile"""
|
||||
image = validated_data.get('image', None)
|
||||
# phone_number = validated_data.get('phone', None)
|
||||
# guardian_data = Guardian.objects.filter(phone=phone_number)
|
||||
# junior_data = Junior.objects.filter(phone=phone_number)
|
||||
# if phone_number and (junior_data or guardian_data):
|
||||
# raise serializers.ValidationError({"details":ERROR_CODE['2012']})
|
||||
guardian_code = validated_data.get('guardian_code',None)
|
||||
user = User.objects.filter(username=self.context['user']).last()
|
||||
if user:
|
||||
"""Save first and last name of junior"""
|
||||
@ -82,6 +79,9 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
|
||||
junior.gender = validated_data.get('gender',junior.gender)
|
||||
"""Update guardian code"""
|
||||
junior.guardian_code = validated_data.get('guardian_code', junior.guardian_code)
|
||||
"""condition for guardian code"""
|
||||
if guardian_code:
|
||||
junior.guardian_code = guardian_code
|
||||
junior.dob = validated_data.get('dob',junior.dob)
|
||||
junior.passcode = validated_data.get('passcode', junior.passcode)
|
||||
junior.country_name = validated_data.get('country_name', junior.country_name)
|
||||
@ -107,3 +107,88 @@ class CreateJuniorSerializer(serializers.ModelSerializer):
|
||||
with transaction.atomic():
|
||||
instance = super().save(**kwargs)
|
||||
return instance
|
||||
|
||||
class JuniorDetailSerializer(serializers.ModelSerializer):
|
||||
"""junior serializer"""
|
||||
email = serializers.SerializerMethodField('get_auth')
|
||||
first_name = serializers.SerializerMethodField('get_first_name')
|
||||
last_name = serializers.SerializerMethodField('get_last_name')
|
||||
|
||||
def get_auth(self, obj):
|
||||
"""user email address"""
|
||||
return obj.auth.username
|
||||
|
||||
def get_first_name(self, obj):
|
||||
"""user first name"""
|
||||
return obj.auth.first_name
|
||||
|
||||
def get_last_name(self, obj):
|
||||
"""user last name"""
|
||||
return obj.auth.last_name
|
||||
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Junior
|
||||
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
||||
'updated_at']
|
||||
|
||||
class JuniorDetailListSerializer(serializers.ModelSerializer):
|
||||
"""junior serializer"""
|
||||
|
||||
email = serializers.SerializerMethodField('get_auth')
|
||||
first_name = serializers.SerializerMethodField('get_first_name')
|
||||
last_name = serializers.SerializerMethodField('get_last_name')
|
||||
assigned_task = serializers.SerializerMethodField('get_assigned_task')
|
||||
points = serializers.SerializerMethodField('get_points')
|
||||
in_progress_task = serializers.SerializerMethodField('get_in_progress_task')
|
||||
completed_task = serializers.SerializerMethodField('get_completed_task')
|
||||
requested_task = serializers.SerializerMethodField('get_requested_task')
|
||||
rejected_task = serializers.SerializerMethodField('get_rejected_task')
|
||||
pending_task = serializers.SerializerMethodField('get_pending_task')
|
||||
|
||||
|
||||
def get_auth(self, obj):
|
||||
return obj.auth.username
|
||||
|
||||
def get_first_name(self, obj):
|
||||
return obj.auth.first_name
|
||||
|
||||
def get_last_name(self, obj):
|
||||
return obj.auth.last_name
|
||||
|
||||
def get_assigned_task(self, obj):
|
||||
data = JuniorTask.objects.filter(junior=obj).count()
|
||||
return data
|
||||
|
||||
def get_points(self, obj):
|
||||
data = sum(JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).values_list('points', flat=True))
|
||||
return data
|
||||
|
||||
def get_in_progress_task(self, obj):
|
||||
data = JuniorTask.objects.filter(junior=obj, task_status=IN_PROGRESS).count()
|
||||
return data
|
||||
|
||||
def get_completed_task(self, obj):
|
||||
data = JuniorTask.objects.filter(junior=obj, task_status=COMPLETED).count()
|
||||
return data
|
||||
|
||||
|
||||
def get_requested_task(self, obj):
|
||||
data = JuniorTask.objects.filter(junior=obj, task_status=REQUESTED).count()
|
||||
return data
|
||||
|
||||
def get_rejected_task(self, obj):
|
||||
data = JuniorTask.objects.filter(junior=obj, task_status=REJECTED).count()
|
||||
return data
|
||||
|
||||
def get_pending_task(self, obj):
|
||||
data = JuniorTask.objects.filter(junior=obj, task_status=PENDING).count()
|
||||
return data
|
||||
class Meta(object):
|
||||
"""Meta info"""
|
||||
model = Junior
|
||||
fields = ['id', 'email', 'first_name', 'last_name', 'country_code', 'phone', 'gender', 'dob',
|
||||
'guardian_code', 'referral_code','is_active', 'is_complete_profile', 'created_at', 'image',
|
||||
'updated_at', 'assigned_task','points', 'pending_task', 'in_progress_task', 'completed_task',
|
||||
'requested_task', 'rejected_task']
|
||||
|
@ -1,7 +1,7 @@
|
||||
""" Urls files"""
|
||||
"""Django import"""
|
||||
from django.urls import path, include
|
||||
from .views import UpdateJuniorProfile, ValidateGuardianCode
|
||||
from .views import UpdateJuniorProfile, ValidateGuardianCode, JuniorListAPIView
|
||||
"""Third party import"""
|
||||
from rest_framework import routers
|
||||
|
||||
@ -13,6 +13,8 @@ router = routers.SimpleRouter()
|
||||
router.register('create-junior-profile', UpdateJuniorProfile, basename='profile-update')
|
||||
"""validate guardian code API"""
|
||||
router.register('validate-guardian-code', ValidateGuardianCode, basename='validate-guardian-code')
|
||||
"""junior list API"""
|
||||
router.register('junior-list', JuniorListAPIView, basename='junior-list')
|
||||
"""Define url pattern"""
|
||||
urlpatterns = [
|
||||
path('api/v1/', include(router.urls)),
|
||||
|
@ -3,7 +3,7 @@ from rest_framework import viewsets, status
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
"""Django app import"""
|
||||
from junior.models import Junior
|
||||
from .serializers import CreateJuniorSerializer
|
||||
from .serializers import CreateJuniorSerializer, JuniorDetailListSerializer
|
||||
from guardian.models import Guardian
|
||||
from base.messages import ERROR_CODE, SUCCESS_CODE
|
||||
from account.utils import custom_response, custom_error_response
|
||||
@ -38,3 +38,15 @@ class ValidateGuardianCode(viewsets.ViewSet):
|
||||
return custom_response(SUCCESS_CODE['3013'], response_status=status.HTTP_200_OK)
|
||||
else:
|
||||
return custom_error_response(ERROR_CODE["2022"], response_status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
class JuniorListAPIView(viewsets.ModelViewSet):
|
||||
"""Junior list of assosicated guardian"""
|
||||
|
||||
serializer_class = JuniorDetailListSerializer
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
""" junior list"""
|
||||
guardian_data = Guardian.objects.filter(user__email=request.user).last()
|
||||
queryset = Junior.objects.filter(guardian_code__icontains=str(guardian_data.guardian_code))
|
||||
serializer = JuniorDetailListSerializer(queryset, many=True)
|
||||
return custom_response(None, serializer.data, response_status=status.HTTP_200_OK)
|
||||
|
@ -8,6 +8,7 @@ async-timeout==4.0.2
|
||||
billiard==4.1.0
|
||||
boto3==1.26.157
|
||||
botocore==1.29.157
|
||||
cachetools==5.3.1
|
||||
celery==5.3.1
|
||||
certifi==2023.5.7
|
||||
cffi==1.15.1
|
||||
@ -18,6 +19,8 @@ click==8.1.3
|
||||
click-didyoumean==0.3.0
|
||||
click-plugins==1.1.1
|
||||
click-repl==0.3.0
|
||||
coreapi==2.3.3
|
||||
coreschema==0.0.4
|
||||
crcmod==1.7
|
||||
cron-descriptor==1.4.0
|
||||
cryptography==41.0.1
|
||||
@ -38,11 +41,15 @@ django-timezone-field==5.1
|
||||
djangorestframework==3.14.0
|
||||
djangorestframework-simplejwt==5.2.2
|
||||
drf-yasg==1.21.6
|
||||
google-auth==2.21.0
|
||||
gunicorn==20.1.0
|
||||
idna==3.4
|
||||
inflection==0.5.1
|
||||
itypes==1.2.0
|
||||
Jinja2==3.1.2
|
||||
jmespath==0.10.0
|
||||
kombu==5.3.1
|
||||
MarkupSafe==2.1.3
|
||||
msgpack==1.0.5
|
||||
oss2==2.18.0
|
||||
packaging==23.1
|
||||
@ -50,6 +57,8 @@ phonenumbers==8.13.15
|
||||
Pillow==9.5.0
|
||||
prompt-toolkit==3.0.38
|
||||
psycopg==3.1.9
|
||||
pyasn1==0.5.0
|
||||
pyasn1-modules==0.3.0
|
||||
pycparser==2.21
|
||||
pycryptodome==3.18.0
|
||||
PyJWT==2.7.0
|
||||
@ -60,6 +69,7 @@ pytz==2023.3
|
||||
PyYAML==6.0
|
||||
redis==4.5.5
|
||||
requests==2.31.0
|
||||
rsa==4.9
|
||||
s3transfer==0.6.1
|
||||
six==1.16.0
|
||||
sqlparse==0.4.4
|
||||
|
@ -56,6 +56,7 @@ INSTALLED_APPS = [
|
||||
'account',
|
||||
'junior',
|
||||
'guardian',
|
||||
# 'social_django'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@ -91,11 +92,12 @@ REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
# 'rest_framework.authentication.SessionAuthentication',
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
||||
]
|
||||
'rest_framework_simplejwt.authentication.JWTAuthentication',],
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
|
||||
'PAGE_SIZE': 5, # Set the default pagination size
|
||||
}
|
||||
SIMPLE_JWT = {
|
||||
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
|
||||
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=50),
|
||||
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
|
||||
}
|
||||
# Database
|
||||
@ -172,6 +174,9 @@ CORS_ALLOW_HEADERS = (
|
||||
https://docs.djangoproject.com/en/3.0/howto/static-files/"""
|
||||
|
||||
|
||||
GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID')
|
||||
GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET')
|
||||
|
||||
# EMAIL_BACKEND = os.getenv('EMAIL_BACKEND')
|
||||
# EMAIL_HOST = os.getenv('EMAIL_HOST')
|
||||
# EMAIL_PORT = os.getenv('EMAIL_PORT')
|
||||
@ -186,19 +191,16 @@ EMAIL_PORT="587"
|
||||
EMAIL_USE_TLS="True"
|
||||
EMAIL_HOST_USER="apikey" # Replace with your Gmail email address
|
||||
EMAIL_HOST_PASSWORD="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"
|
||||
EMAIL_FROM_ADDRESS="zodbank@yopmail.com"
|
||||
EMAIL_FROM_ADDRESS="support@zodbank.com"
|
||||
# EMAIL_FROM_ADDRESS="zodbank@yopmail.com"
|
||||
|
||||
# ALIYUN_OSS_ACCESS_KEY_ID = os.getenv('ALIYUN_OSS_ACCESS_KEY_ID')
|
||||
# ALIYUN_OSS_ACCESS_KEY_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET')
|
||||
# ALIYUN_OSS_BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME')
|
||||
# ALIYUN_OSS_ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT')
|
||||
# ALIYUN_OSS_REGION = os.getenv('ALIYUN_OSS_REGION')
|
||||
ALIYUN_OSS_ACCESS_KEY_ID = os.getenv('ALIYUN_OSS_ACCESS_KEY_ID')
|
||||
ALIYUN_OSS_ACCESS_KEY_SECRET = os.getenv('ALIYUN_OSS_ACCESS_KEY_SECRET')
|
||||
ALIYUN_OSS_BUCKET_NAME = os.getenv('ALIYUN_OSS_BUCKET_NAME')
|
||||
ALIYUN_OSS_ENDPOINT = os.getenv('ALIYUN_OSS_ENDPOINT')
|
||||
ALIYUN_OSS_REGION = os.getenv('ALIYUN_OSS_REGION')
|
||||
|
||||
ALIYUN_OSS_ACCESS_KEY_ID="LTAI5t7w1gq1CswJtvxtEZTd"
|
||||
ALIYUN_OSS_ACCESS_KEY_SECRET="6yknAFpP2gVMhCWAJwbAjCEw2eehpf"
|
||||
ALIYUN_OSS_BUCKET_NAME="zod-dev"
|
||||
ALIYUN_OSS_ENDPOINT="oss-me-central-1.aliyuncs.com"
|
||||
ALIYUN_OSS_REGION="Global"
|
||||
|
||||
STATIC_URL = 'static/'
|
||||
STATIC_ROOT = 'static'
|
||||
|
||||
|
Reference in New Issue
Block a user